//-----------------------------------------------------------------------------
struct ADMIN_CONF_RES
{
+ ADMIN_CONF_RES() {}
ADMIN_CONF_RES(const ADMIN_CONF & conf)
: priv(conf.priv),
login(conf.login),
--- /dev/null
+#ifndef __STG_ARRAY_H__
+#define __STG_ARRAY_H__
+
+#include <cstddef> // size_t
+
+namespace STG
+{
+
+template <typename T, size_t S>
+class ARRAY
+{
+ public:
+ typedef T value_type;
+ typedef size_t size_type;
+ typedef T * iterator;
+ typedef const T * const_iterator;
+
+ ARRAY()
+ {
+ for (size_type i = 0; i < S; ++i)
+ m_data[i] = value_type();
+ }
+
+ const value_type & operator[](size_type i) const { return m_data[i]; }
+ value_type & operator[](size_type i) { return m_data[i]; }
+ size_type size() const { return S; }
+
+ iterator begin() { return &m_data[0]; }
+ const_iterator begin() const { return &m_data[0]; }
+ iterator end() { return &m_data[S + 1]; }
+ const_iterator end() const { return &m_data[S + 1]; }
+
+ const value_type & front() const { return m_data[0]; }
+ value_type & front() { return m_data[0]; }
+ const value_type & back() const { return m_data[S]; }
+ value_type & back() { return m_data[S]; }
+
+ private:
+ value_type m_data[S];
+};
+
+} // namespace STG
+
+#endif
const T & data() const throw() { return value; }
bool empty() const throw() { return !is_set; }
void reset() throw() { is_set = false; }
+ void splice(const RESETABLE<T> & rhs)
+ {
+ if (rhs.is_set)
+ {
+ value = rhs.value;
+ is_set = true;
+ }
+ }
private:
value_type value;
return dd;
}
+ void Splice(const DIRPRICE_DATA_RES & rhs)
+ {
+ hDay.splice(rhs.hDay);
+ mDay.splice(rhs.mDay);
+ hNight.splice(rhs.hNight);
+ mNight.splice(rhs.mNight);
+ priceDayA.splice(rhs.priceDayA);
+ priceNightA.splice(rhs.priceNightA);
+ priceDayB.splice(rhs.priceDayB);
+ priceNightB.splice(rhs.priceNightB);
+ threshold.splice(rhs.threshold);
+ singlePrice.splice(rhs.singlePrice);
+ noDiscount.splice(rhs.noDiscount);
+ }
+
RESETABLE<int> hDay;
RESETABLE<int> mDay;
RESETABLE<int> hNight;
note(),
realName(),
corp(),
- service(),
+ services(),
group(),
credit(0),
nextTariff(),
std::string note;
std::string realName;
std::string corp;
- std::vector<std::string> service;
+ std::vector<std::string> services;
std::string group;
double credit;
std::string nextTariff;
email(),
note(),
realName(),
+ corp(),
group(),
credit(),
nextTariff(),
userdata(USERDATA_NUM),
+ services(),
creditExpire(),
ips()
{
email = uc.email;
note = uc.note;
realName = uc.realName;
+ corp = uc.corp;
group = uc.group;
credit = uc.credit;
nextTariff = uc.nextTariff;
for (size_t i = 0; i < USERDATA_NUM; i++) userdata[i] = uc.userdata[i];
+ services = uc.services;
creditExpire = uc.creditExpire;
ips = uc.ips;
return *this;
uc.email = email.data();
uc.note = note.data();
uc.realName = realName.data();
+ uc.corp = corp.data();
uc.group = group.data();
uc.credit = credit.data();
uc.nextTariff = nextTariff.data();
- for (int i = 0; i < USERDATA_NUM; i++)
+ for (size_t i = 0; i < USERDATA_NUM; i++)
{
uc.userdata[i] = userdata[i].data();
}
+ uc.services = services.data();
uc.creditExpire = creditExpire.data();
uc.ips = ips.data();
return uc;
RESETABLE<std::string> email;
RESETABLE<std::string> note;
RESETABLE<std::string> realName;
+ RESETABLE<std::string> corp;
RESETABLE<std::string> group;
RESETABLE<double> credit;
RESETABLE<std::string> nextTariff;
std::vector<RESETABLE<std::string> > userdata;
+ RESETABLE<std::vector<std::string> > services;
RESETABLE<time_t> creditExpire;
RESETABLE<USER_IPS> ips;
};
5) OS=bsd5;;
6) OS=bsd5;;
7) OS=bsd7;;
- 8) OS=bsd7;;
- 9) OS=bsd7;;
- *) OS=unknown;;
+ *) OS=bsd7;;
esac
MAKE="gmake"
fi
if [ "$OS" = "unknown" ]
-then
+then
printf "#############################################################################\n"
printf "# Sorry, but rlm_stg currently supported by Linux, FreeBSD 4.x, 5.x, 6.x #\n"
printf "#############################################################################\n"
5) OS=bsd5;;
6) OS=bsd5;;
7) OS=bsd7;;
- 8) OS=bsd7;;
- 9) OS=bsd7;;
- *) OS=unknown;;
+ *) OS=bsd7;;
esac
MAKE="gmake"
fi
if [ "$OS" = "unknown" ]
-then
+then
printf "#############################################################################\n"
printf "# Sorry, but rscriptd currently supported by Linux, FreeBSD 4.x, 5.x, 6.x #\n"
printf "#############################################################################\n"
printf " Building rscriptd for $sys $release\n"
printf "#############################################################################\n"
-STG_LIBS="logger.lib
+STG_LIBS="logger.lib
locker.lib
- crypto.lib
- common.lib
- scriptexecuter.lib
- conffiles.lib"
+ crypto.lib
+ common.lib
+ scriptexecuter.lib
+ conffiles.lib"
if [ "$OS" = "linux" ]
then
5) OS=bsd5;;
6) OS=bsd5;;
7) OS=bsd7;;
- 8) OS=bsd7;;
- 9) OS=bsd7;;
- *) OS=unknown;;
+ *) OS=bsd7;;
esac
MAKE="gmake"
fi
if [ "$OS" = "unknown" ]
-then
+then
printf "#############################################################################\n"
printf "# Sorry, but sgauth currently supported by Linux, FreeBSD 4.x, 5.x, 6.x #\n"
printf "#############################################################################\n"
printf " Building sgauth for $sys $release\n"
printf "#############################################################################\n"
-STG_LIBS="crypto.lib
- common.lib
- conffiles.lib
- ia.lib"
+STG_LIBS="crypto.lib
+ common.lib
+ conffiles.lib
+ ia.lib"
if [ "$OS" = "linux" ]
then
PROG = sgconf
SRCS = ./main.cpp \
- ./common_sg.cpp \
./options.cpp \
+ ./api_action.cpp \
./actions.cpp \
+ ./admins.cpp \
+ ./tariffs.cpp \
+ ./users.cpp \
+ ./services.cpp \
+ ./corps.cpp \
./xml.cpp
-STGLIBS = conffiles \
- srvconf \
- crypto \
+STGLIBS = srvconf \
+ crypto \
common
STGLIBS_INCS = $(addprefix -I ../../stglibs/,$(addsuffix .lib/include,$(STGLIBS)))
ifeq ($(OS),linux)
else
LIBS += -lc \
- -liconv
+ -liconv
endif
SEARCH_DIRS = -I ../../include
$(CXX) $^ $(LDFLAGS) $(LIBS) -o $(PROG)
clean:
- rm -f deps $(PROG) *.o tags *.*~ .OS
- rm -f .OS
- rm -f .store
- rm -f .db.sql
- rm -f core*
+ rm -f deps $(PROG) *.o
$(MAKE) -C $(DIR_LIBSRC) clean
distclean: clean
endif
endif
-deps: $(SRCS) ../../Makefile.conf
+deps: $(SRCS) ../../Makefile.conf
$(MAKE) -C $(DIR_LIBSRC)
@>deps ;\
for file in $(SRCS); do\
#define __STG_SGCONF_ACTION_H__
#include <string>
+#include <map>
#include <stdexcept>
namespace SGCONF
class OPTION_BLOCK;
struct PARSER_STATE;
+struct CONFIG;
class ACTION
{
virtual std::string ParamDescription() const = 0;
virtual std::string DefaultDescription() const = 0;
virtual OPTION_BLOCK & Suboptions() = 0;
- virtual PARSER_STATE Parse(int argc, char ** argv) = 0;
+ virtual PARSER_STATE Parse(int argc, char ** argv, void * data = NULL) = 0;
virtual void ParseValue(const std::string &) {}
class ERROR : public std::runtime_error
#include <string>
+#include <cassert>
+
namespace SGCONF
{
virtual std::string ParamDescription() const { return ""; }
virtual std::string DefaultDescription() const { return ""; }
virtual OPTION_BLOCK & Suboptions() { return m_suboptions; }
- virtual PARSER_STATE Parse(int argc, char ** argv)
+ virtual PARSER_STATE Parse(int argc, char ** argv, void * /*data*/)
{
m_func();
return PARSER_STATE(true, argc, argv);
virtual std::string ParamDescription() const { return m_description; }
virtual std::string DefaultDescription() const;
virtual OPTION_BLOCK & Suboptions() { return m_suboptions; }
- virtual PARSER_STATE Parse(int argc, char ** argv);
+ virtual PARSER_STATE Parse(int argc, char ** argv, void * /*data*/);
virtual void ParseValue(const std::string & value);
private:
template <typename T>
inline
-PARSER_STATE PARAM_ACTION<T>::Parse(int argc, char ** argv)
+PARSER_STATE PARAM_ACTION<T>::Parse(int argc, char ** argv, void * /*data*/)
{
if (argc == 0 ||
argv == NULL ||
template <>
inline
-PARSER_STATE PARAM_ACTION<std::string>::Parse(int argc, char ** argv)
+PARSER_STATE PARAM_ACTION<std::string>::Parse(int argc, char ** argv, void * /*data*/)
{
if (argc == 0 ||
argv == NULL ||
return new PARAM_ACTION<T>(param, paramDescription);
}
+class KV_ACTION : public ACTION
+{
+ public:
+ KV_ACTION(const std::string & name,
+ const std::string & paramDescription)
+ : m_name(name),
+ m_description(paramDescription)
+ {}
+
+ virtual ACTION * Clone() const { return new KV_ACTION(*this); }
+
+ virtual std::string ParamDescription() const { return m_description; }
+ virtual std::string DefaultDescription() const { return ""; }
+ virtual OPTION_BLOCK & Suboptions() { return m_suboptions; }
+ virtual PARSER_STATE Parse(int argc, char ** argv, void * data);
+
+ private:
+ std::string m_name;
+ std::string m_description;
+ OPTION_BLOCK m_suboptions;
+};
+
+inline
+PARSER_STATE KV_ACTION::Parse(int argc, char ** argv, void * data)
+{
+if (argc == 0 ||
+ argv == NULL ||
+ *argv == NULL)
+ throw ERROR("Missing argument.");
+assert(data != NULL && "Expecting container pointer.");
+std::map<std::string, std::string> & kvs = *static_cast<std::map<std::string, std::string>*>(data);
+kvs[m_name] = *argv;
+return PARSER_STATE(false, --argc, ++argv);
+}
+
+inline
+KV_ACTION * MakeKVAction(const std::string & name,
+ const std::string & paramDescription)
+{
+return new KV_ACTION(name, paramDescription);
+}
+
} // namespace SGCONF
#endif
--- /dev/null
+#include "admins.h"
+
+#include "api_action.h"
+#include "options.h"
+#include "config.h"
+#include "utils.h"
+
+#include "stg/servconf.h"
+#include "stg/servconf_types.h"
+#include "stg/os_int.h"
+
+#include <iostream>
+#include <string>
+#include <map>
+#include <cassert>
+
+namespace
+{
+
+std::string Indent(size_t level, bool dash = false)
+{
+if (level == 0)
+ return "";
+return dash ? std::string(level * 4 - 2, ' ') + "- " : std::string(level * 4, ' ');
+}
+
+std::string PrivToString(const PRIV& priv)
+{
+return std::string("") +
+ (priv.corpChg ? "1" : "0") +
+ (priv.serviceChg ? "1" : "0") +
+ (priv.tariffChg ? "1" : "0") +
+ (priv.adminChg ? "1" : "0") +
+ (priv.userAddDel ? "1" : "0") +
+ (priv.userPasswd ? "1" : "0") +
+ (priv.userCash ? "1" : "0") +
+ (priv.userConf ? "1" : "0") +
+ (priv.userStat ? "1" : "0");
+}
+
+void PrintAdmin(const STG::GET_ADMIN::INFO & info, size_t level = 0)
+{
+std::cout << Indent(level, true) << "login: " << info.login << "\n"
+ << Indent(level) << "priviledges: " << PrivToString(info.priv) << "\n";
+}
+
+std::vector<SGCONF::API_ACTION::PARAM> GetAdminParams()
+{
+std::vector<SGCONF::API_ACTION::PARAM> params;
+params.push_back(SGCONF::API_ACTION::PARAM("password", "<password>", "password"));
+params.push_back(SGCONF::API_ACTION::PARAM("priv", "<priv>", "priviledges"));
+return params;
+}
+
+void ConvPriv(const std::string & value, RESETABLE<PRIV> & res)
+{
+if (value.length() != 9)
+ throw SGCONF::ACTION::ERROR("Priviledges value should be a 9-digits length binary number.");
+PRIV priv;
+priv.corpChg = (value[0] == '0' ? 0 : 1);
+priv.serviceChg = (value[1] == '0' ? 0 : 1);
+priv.tariffChg = (value[2] == '0' ? 0 : 1);
+priv.adminChg = (value[3] == '0' ? 0 : 1);
+priv.userAddDel = (value[4] == '0' ? 0 : 1);
+priv.userPasswd = (value[5] == '0' ? 0 : 1);
+priv.userCash = (value[6] == '0' ? 0 : 1);
+priv.userConf = (value[7] == '0' ? 0 : 1);
+priv.userStat = (value[8] == '0' ? 0 : 1);
+res = priv;
+}
+
+void SimpleCallback(bool result,
+ const std::string & reason,
+ void * /*data*/)
+{
+if (!result)
+ {
+ std::cerr << "Operation failed. Reason: '" << reason << "'." << std::endl;
+ return;
+ }
+std::cout << "Success.\n";
+}
+
+void GetAdminsCallback(bool result,
+ const std::string & reason,
+ const std::vector<STG::GET_ADMIN::INFO> & info,
+ void * /*data*/)
+{
+if (!result)
+ {
+ std::cerr << "Failed to get admin list. Reason: '" << reason << "'." << std::endl;
+ return;
+ }
+std::cout << "Admins:\n";
+for (size_t i = 0; i < info.size(); ++i)
+ PrintAdmin(info[i], 1);
+}
+
+void GetAdminCallback(bool result,
+ const std::string & reason,
+ const std::vector<STG::GET_ADMIN::INFO> & info,
+ void * data)
+{
+assert(data != NULL && "Expecting pointer to std::string with the admin's login.");
+const std::string & login = *static_cast<const std::string *>(data);
+if (!result)
+ {
+ std::cerr << "Failed to get admin. Reason: '" << reason << "'." << std::endl;
+ return;
+ }
+for (size_t i = 0; i < info.size(); ++i)
+ if (info[i].login == login)
+ PrintAdmin(info[i]);
+}
+
+
+bool GetAdminsFunction(const SGCONF::CONFIG & config,
+ const std::string & /*arg*/,
+ const std::map<std::string, std::string> & /*options*/)
+{
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.GetAdmins(GetAdminsCallback, NULL) == STG::st_ok;
+}
+
+bool GetAdminFunction(const SGCONF::CONFIG & config,
+ const std::string & arg,
+ const std::map<std::string, std::string> & /*options*/)
+{
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+// STG currently doesn't support <GetAdmin login="..."/>.
+// So get a list of admins and filter it. 'data' param holds a pointer to 'login'.
+std::string login(arg);
+return proto.GetAdmins(GetAdminCallback, &login) == STG::st_ok;
+}
+
+bool DelAdminFunction(const SGCONF::CONFIG & config,
+ const std::string & arg,
+ const std::map<std::string, std::string> & /*options*/)
+{
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.DelAdmin(arg, SimpleCallback, NULL) == STG::st_ok;
+}
+
+bool AddAdminFunction(const SGCONF::CONFIG & config,
+ const std::string & arg,
+ const std::map<std::string, std::string> & options)
+{
+ADMIN_CONF_RES conf;
+conf.login = arg;
+SGCONF::MaybeSet(options, "priv", conf.priv, ConvPriv);
+SGCONF::MaybeSet(options, "password", conf.password);
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.AddAdmin(arg, conf, SimpleCallback, NULL) == STG::st_ok;
+}
+
+bool ChgAdminFunction(const SGCONF::CONFIG & config,
+ const std::string & arg,
+ const std::map<std::string, std::string> & options)
+{
+ADMIN_CONF_RES conf;
+conf.login = arg;
+SGCONF::MaybeSet(options, "priv", conf.priv, ConvPriv);
+SGCONF::MaybeSet(options, "password", conf.password);
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.ChgAdmin(conf, SimpleCallback, NULL) == STG::st_ok;
+}
+
+} // namespace anonymous
+
+void SGCONF::AppendAdminsOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks)
+{
+std::vector<API_ACTION::PARAM> params(GetAdminParams());
+blocks.Add("Admin management options")
+ .Add("get-admins", SGCONF::MakeAPIAction(commands, GetAdminsFunction), "\tget admin list")
+ .Add("get-admin", SGCONF::MakeAPIAction(commands, "<login>", GetAdminFunction), "get admin")
+ .Add("add-admin", SGCONF::MakeAPIAction(commands, "<login>", params, AddAdminFunction), "add admin")
+ .Add("del-admin", SGCONF::MakeAPIAction(commands, "<login>", DelAdminFunction), "del admin")
+ .Add("chg-admin", SGCONF::MakeAPIAction(commands, "<login>", params, ChgAdminFunction), "change admin");
+}
--- /dev/null
+#ifndef __STG_SGCONF_ADMINS_H__
+#define __STG_SGCONF_ADMINS_H__
+
+namespace SGCONF
+{
+
+class OPTION_BLOCKS;
+class COMMANDS;
+
+void AppendAdminsOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks);
+
+} // namespace SGCONF
+
+#endif
--- /dev/null
+#include "api_action.h"
+
+#include "actions.h"
+#include "parser_state.h"
+
+SGCONF::PARSER_STATE SGCONF::API_ACTION::Parse(int argc, char ** argv, void * /*data*/)
+{
+PARSER_STATE state(false, argc, argv);
+if (!m_argument.empty())
+ {
+ if (argc == 0 ||
+ argv == NULL ||
+ *argv == NULL)
+ throw ERROR("Missing argument.");
+ m_argument = *argv;
+ --state.argc;
+ ++state.argv;
+ }
+state = m_suboptions.Parse(state.argc, state.argv, &m_params);
+m_commands.Add(m_funPtr, m_argument, m_params);
+return state;
+}
+
+SGCONF::API_ACTION::API_ACTION(COMMANDS & commands,
+ const std::string & paramDescription,
+ bool needArgument,
+ const std::vector<PARAM> & params,
+ API_FUNCTION funPtr)
+ : m_commands(commands),
+ m_description(paramDescription),
+ m_argument(needArgument ? "1" : ""), // Hack
+ m_funPtr(funPtr)
+{
+std::vector<PARAM>::const_iterator it(params.begin());
+while (it != params.end())
+ {
+ m_suboptions.Add(it->name, MakeKVAction(it->name, it->shortDescr), it->longDescr);
+ ++it;
+ }
+}
--- /dev/null
+#ifndef __STG_SGCONF_API_ACTION_H__
+#define __STG_SGCONF_API_ACTION_H__
+
+#include "action.h"
+
+#include "options.h"
+
+#include <string>
+#include <map>
+#include <vector>
+
+namespace SGCONF
+{
+
+typedef bool (* API_FUNCTION) (const CONFIG &,
+ const std::string &,
+ const std::map<std::string, std::string> &);
+
+class COMMAND
+{
+ public:
+ COMMAND(API_FUNCTION funPtr,
+ const std::string & arg,
+ const std::map<std::string, std::string> & options)
+ : m_funPtr(funPtr),
+ m_arg(arg),
+ m_options(options)
+ {}
+ bool Execute(const SGCONF::CONFIG & config) const
+ {
+ return m_funPtr(config, m_arg, m_options);
+ }
+
+ private:
+ API_FUNCTION m_funPtr;
+ std::string m_arg;
+ std::map<std::string, std::string> m_options;
+};
+
+class COMMANDS
+{
+ public:
+ void Add(API_FUNCTION funPtr,
+ const std::string & arg,
+ const std::map<std::string, std::string> & options) { m_commands.push_back(COMMAND(funPtr, arg, options)); }
+ bool Execute(const SGCONF::CONFIG & config) const
+ {
+ std::vector<COMMAND>::const_iterator it(m_commands.begin());
+ bool res = true;
+ while (it != m_commands.end() && res)
+ {
+ res = res && it->Execute(config);
+ ++it;
+ }
+ return res;
+ }
+ private:
+ std::vector<COMMAND> m_commands;
+};
+
+class API_ACTION : public ACTION
+{
+ public:
+ struct PARAM
+ {
+ PARAM(const std::string & n,
+ const std::string & s,
+ const std::string & l)
+ : name(n),
+ shortDescr(s),
+ longDescr(l)
+ {}
+ std::string name;
+ std::string shortDescr;
+ std::string longDescr;
+ };
+
+ API_ACTION(COMMANDS & commands,
+ const std::string & paramDescription,
+ bool needArgument,
+ const std::vector<PARAM> & params,
+ API_FUNCTION funPtr);
+ API_ACTION(COMMANDS & commands,
+ const std::string & paramDescription,
+ bool needArgument,
+ API_FUNCTION funPtr)
+ : m_commands(commands),
+ m_description(paramDescription),
+ m_argument(needArgument ? "1" : ""), // Hack
+ m_funPtr(funPtr)
+ {}
+
+ virtual ACTION * Clone() const { return new API_ACTION(*this); }
+
+ virtual std::string ParamDescription() const { return m_description; }
+ virtual std::string DefaultDescription() const { return ""; }
+ virtual OPTION_BLOCK & Suboptions() { return m_suboptions; }
+ virtual PARSER_STATE Parse(int argc, char ** argv, void * /*data*/);
+
+ private:
+ COMMANDS & m_commands;
+ std::string m_description;
+ std::string m_argument;
+ OPTION_BLOCK m_suboptions;
+ std::map<std::string, std::string> m_params;
+ API_FUNCTION m_funPtr;
+};
+
+inline
+ACTION * MakeAPIAction(COMMANDS & commands,
+ const std::string & paramDescription,
+ const std::vector<API_ACTION::PARAM> & params,
+ API_FUNCTION funPtr)
+{
+return new API_ACTION(commands, paramDescription, true, params, funPtr);
+}
+
+inline
+ACTION * MakeAPIAction(COMMANDS & commands,
+ const std::vector<API_ACTION::PARAM> & params,
+ API_FUNCTION funPtr)
+{
+return new API_ACTION(commands, "", false, params, funPtr);
+}
+
+inline
+ACTION * MakeAPIAction(COMMANDS & commands,
+ const std::string & paramDescription,
+ API_FUNCTION funPtr)
+{
+return new API_ACTION(commands, paramDescription, true, funPtr);
+}
+
+inline
+ACTION * MakeAPIAction(COMMANDS & commands,
+ API_FUNCTION funPtr)
+{
+return new API_ACTION(commands, "", false, funPtr);
+}
+
+}
+
+#endif
5) OS=bsd5;;
6) OS=bsd5;;
7) OS=bsd7;;
- 8) OS=bsd7;;
- 9) OS=bsd7;;
- *) OS=unknown;;
+ *) OS=bsd7;;
esac
MAKE="gmake"
fi
fi
if [ "$OS" = "unknown" ]
-then
+then
printf "#############################################################################\n"
printf "# Sorry, but sgconf currently supported by Linux, FreeBSD 4.x, 5.x, 6.x #\n"
printf "#############################################################################\n"
printf "#############################################################################\n"
STG_LIBS="conffiles.lib
- crypto.lib
- common.lib
- srvconf.lib"
+ crypto.lib
+ common.lib
+ srvconf.lib"
if [ "$OS" = "linux" ]
then
+++ /dev/null
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/*
- * Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- */
-
- /*
- $Author: faust $
- $Revision: 1.12 $
- $Date: 2009/06/08 10:02:28 $
- */
-
-
-#include "sg_error_codes.h"
-#include "common_sg.h"
-#include "version_sg.h"
-
-#include "stg/common.h"
-
-#include <iostream>
-#include <vector>
-
-#include <cstdio>
-#include <cstring>
-#include <cstdlib>
-#include <cerrno>
-#include <clocale>
-
-#include <langinfo.h>
-#include <iconv.h>
-
-using namespace STG;
-
-const int usageConf = 0;
-const int usageInfo = 1;
-
-const int TO_KOI8 = 0;
-const int FROM_KOI8 = 1;
-//-----------------------------------------------------------------------------
-struct ResultData
-{
- bool result;
- std::string reason;
-};
-//-----------------------------------------------------------------------------
-struct GetUserData
-{
- GetUserData(REQUEST & req, bool res) : request(req), result(res) {}
- REQUEST & request;
- bool result;
- std::string reason;
-};
-//---------------------------------------------------------------------------
-struct HelpParams
-{
- std::string setActionName;
- std::string getActionName;
- std::string valueName;
- std::string valueParam;
-};
-//---------------------------------------------------------------------------
-void Usage(int usageType)
-{
-printf("Sgconf version: %s\n\n", VERSION_SG);
-
-char action[4];
-if (usageType == usageConf)
- strcpy(action, "set");
-else
- strcpy(action, "get");
-
-printf("To add or to set cash use:\n");
-printf("sgconf set -s <server> -p <port> -a <admin> -w <admin_pass> -u <user> -c <add_cash[:log message]>\n");
-printf("sgconf set -s <server> -p <port> -a <admin> -w <admin_pass> -u <user> -v <set_cash[:log message]>\n");
-printf("To get cash use:\n");
-printf("sgconf get -s <server> -p <port> -a <admin> -w <admin_pass> -u <user> -c\n\n");
-
-HelpParams hp[] =
-{
- {"set tariff", "get tariff", "-t", "<tariff:now|delayed>"},
- {"set credit", "get credit", "-r", "<credit>"},
- {"set credit expire", "get credit expire", "-E", "<credit_expire_date>"},
- {"set password", "get password", "-o", "<new_password>"},
- {"set prepaid traffic", "get prepaid traffic", "-e", "<prepaid>"},
- {"set IP-addresses", "get IP-addresses", "-I", "<*|ip_addr[,ip_addr...]>"},
- {"set name", "get name", "-A", "<name>"},
- {"set note", "get note", "-N", "<note>"},
- {"set street address", "get street address", "-D", "<address>"},
- {"set email", "get email", "-L", "<email>"},
- {"set phone", "get phone", "-P", "<phone>"},
- {"set group", "get group", "-G", "<group>"},
- {"set/unset down", "get down", "-d", "<0/1>"},
- {"set/unset \'passive\'", "get \'passive\'", "-i", "<0/1>"},
- {"set/unset \'disableDetailStat\'", "get \'disableDetailStat\'", "--disable-stat", "<0/1>"},
- {"set/unset \'alwaysOnline\'", "get \'alwaysOnline\'", "--always-online", "<0/1>"},
-};
-
-for (unsigned i = 0; i < sizeof(hp) / sizeof(HelpParams); i++)
- {
- printf("To %s use:\n", hp[i].setActionName.c_str());
- printf("sgconf set -s <server> -p <port> -a <admin> -w <admin_pass> -u <user> %s %s\n",
- hp[i].valueName.c_str(), hp[i].valueParam.c_str());
- printf("To %s use:\n", hp[i].getActionName.c_str());
- printf("sgconf get -s <server> -p <port> -a <admin> -w <admin_pass> -u <user> %s\n\n",
- hp[i].valueName.c_str());
- }
-
-printf("To set user\'s upload traffic value use:\n");
-printf("sgconf set -s <server> -p <port> -a <admin> -w <admin_pass> -u <user> --u0 <traff> [--u1<traff> ...]\n");
-printf("To get user\'s upload traffic value use:\n");
-printf("sgconf get -s <server> -p <port> -a <admin> -w <admin_pass> -u <user> --u0 [--u1 ...]\n\n");
-
-printf("To set user\'s download traffic value use:\n");
-printf("sgconf set -s <server> -p <port> -a <admin> -w <admin_pass> -u <user> --d0 <traff> [--d1<traff> ...]\n");
-printf("To get user\'s download traffic value use:\n");
-printf("sgconf get -s <server> -p <port> -a <admin> -w <admin_pass> -u <user> --d0 [--d1 ...]\n\n");
-
-printf("To set userdata<0...9> use:\n");
-printf("sgconf set -s <server> -p <port> -a <admin> -w <admin_pass> -u <user> --ud0 <userdata> [--ud1<userdata> ...]\n");
-printf("To get userdata<0...9> use:\n");
-printf("sgconf get -s <server> -p <port> -a <admin> -w <admin_pass> -u <user> --ud0 [--ud1 ...]\n\n");
-
-printf("To get user's authorizers list use:\n");
-printf("sgconf get -s <server> -p <port> -a <admin> -w <admin_pass> -u <user> --authorized-by\n\n");
-
-printf("To send message use:\n");
-printf("sgconf set -s <server> -p <port> -a <admin> -w <admin_pass> -u <user> -m <message>\n\n");
-
-printf("To create user use:\n");
-printf("sgconf set -s <server> -p <port> -a <admin> -w <admin_pass> -u <user> -n\n\n");
-
-printf("To delete user use:\n");
-printf("sgconf set -s <server> -p <port> -a <admin> -w <admin_pass> -u <user> -l\n\n");
-}
-//---------------------------------------------------------------------------
-void UsageConf()
-{
-Usage(usageConf);
-}
-//---------------------------------------------------------------------------
-void UsageInfo()
-{
-Usage(usageInfo);
-}
-//---------------------------------------------------------------------------
-int CheckLogin(const char * login)
-{
-for (int i = 0; i < (int)strlen(login); i++)
- {
- if (!(( login[i] >= 'a' && login[i] <= 'z')
- || (login[i] >= 'A' && login[i] <= 'Z')
- || (login[i] >= '0' && login[i] <= '9')
- || login[i] == '.'
- || login[i] == '_'
- || login[i] == '-'))
- {
- return 1;
- }
- }
-return 0;
-}
-//-----------------------------------------------------------------------------
-short int ParseServerPort(const char * p)
-{
-int port;
-if (str2x(p, port) != 0)
- {
- printf("Incorrect server port %s\n", p);
- exit(NETWORK_ERR_CODE);
- }
-return (short)port;
-}
-//-----------------------------------------------------------------------------
-char * ParseAdminLogin(char * adm)
-{
-if (CheckLogin(adm))
- {
- printf("Incorrect admin login %s\n", adm);
- exit(PARAMETER_PARSING_ERR_CODE);
- }
-return adm;
-}
-//-----------------------------------------------------------------------------
-char * ParsePassword(char * pass)
-{
-if (strlen(pass) >= ADM_PASSWD_LEN)
- {
- printf("Password too big %s\n", pass);
- exit(PARAMETER_PARSING_ERR_CODE);
- }
-
-return pass;
-}
-//-----------------------------------------------------------------------------
-char * ParseUser(char * usr)
-{
-if (CheckLogin(usr))
- {
- printf("Incorrect user login %s\n", usr);
- exit(PARAMETER_PARSING_ERR_CODE);
- }
-return usr;
-}
-//-----------------------------------------------------------------------------
-void ConvertKOI8(const std::string & src, std::string * dst, int encType)
-{
-iconv_t cd;
-char * ob = new char[src.size() * 2 + 1];
-char * ib = new char[src.size() + 1];
-
-strcpy(ib, src.c_str());
-
-char * outbuf = ob;
-char * inbuf = ib;
-
-setlocale(LC_ALL, "");
-
-char charsetF[100];
-char charsetT[100];
-
-if (encType == TO_KOI8)
- {
- strcpy(charsetF, nl_langinfo(CODESET));
- strcpy(charsetT, "koi8-ru");
- }
-else
- {
- strcpy(charsetT, nl_langinfo(CODESET));
- strcpy(charsetF, "koi8-ru");
- }
-
-size_t nconv = 1;
-
-size_t insize = strlen(ib);
-size_t outsize = insize * 2 + 1;
-
-insize = src.size();
-
-cd = iconv_open(charsetT, charsetF);
-if (cd == (iconv_t) -1)
- {
- if (errno != EINVAL)
- printf("error iconv_open\n");
- else
- {
- printf("Warning: iconv from %s to %s failed\n", charsetF, charsetT);
- *dst = src;
- return;
- }
-
- exit(ICONV_ERR_CODE);
- }
-
-#if defined(FREE_BSD) || defined(FREE_BSD5)
-nconv = iconv(cd, (const char **)&inbuf, &insize, &outbuf, &outsize);
-#else
-nconv = iconv(cd, &inbuf, &insize, &outbuf, &outsize);
-#endif
-//printf("charsetT=%s charsetF=%s\n", charsetT, charsetF);
-//printf("ib=%s ob=%s\n", ib, ob);
-//printf("nconv=%d outsize=%d\n", nconv, outsize);
-if (nconv == (size_t) -1)
- {
- if (errno != EINVAL)
- {
- printf("iconv error\n");
- exit(ICONV_ERR_CODE);
- }
- }
-
-*outbuf = L'\0';
-
-iconv_close(cd);
-*dst = ob;
-
-delete[] ob;
-delete[] ib;
-}
-//-----------------------------------------------------------------------------
-void ConvertFromKOI8(const std::string & src, std::string * dst)
-{
-ConvertKOI8(src, dst, FROM_KOI8);
-}
-//-----------------------------------------------------------------------------
-void ResultCallback(bool result, const std::string & reason, void * d)
-{
-ResultData * data = static_cast<ResultData *>(d);
-data->result = result;
-data->reason = reason;
-}
-//-----------------------------------------------------------------------------
-void RecvAuthByData(bool result, const std::string & reason,
- const AUTH_BY::INFO & list, void * d)
-{
-ResultData * data = static_cast<ResultData *>(d);
-data->result = result;
-data->reason = reason;
-
-if (!result)
- return;
-
-for (std::vector<std::string>::const_iterator it = list.begin(); it != list.end(); ++it)
- std::cout << *it << "\n";
-
-std::cout << std::endl;
-}
-//-----------------------------------------------------------------------------
-struct StringReqParams
-{
- std::string name;
- RESETABLE<std::string> reqParam;
- const std::string * value;
-};
-//-----------------------------------------------------------------------------
-void GetUserCallback(bool result, const std::string& reason, const GET_USER::INFO & info, void * d)
-{
-GetUserData * data = static_cast<GetUserData *>(d);
-data->result = false;
-data->reason = reason;
-
-if (!result)
- return;
-
-if (info.login == "")
- {
- data->result = false;
- data->reason = "Invalid login.";
- return;
- }
-
-if (!data->request.cash.empty())
- cout << "cash = " << info.cash << endl;
-
-if (!data->request.credit.empty())
- cout << "credit = " << info.credit << endl;
-
-if (!data->request.creditExpire.empty())
- {
- char buf[32];
- struct tm brokenTime;
- time_t tt = info.creditExpire;
-
- brokenTime.tm_wday = 0;
- brokenTime.tm_yday = 0;
- brokenTime.tm_isdst = 0;
- brokenTime.tm_hour = 0;
- brokenTime.tm_min = 0;
- brokenTime.tm_sec = 0;
-
- gmtime_r(&tt, &brokenTime);
-
- strftime(buf, 32, "%Y-%m-%d", &brokenTime);
-
- cout << "creditExpire = " << buf << endl;
- }
-
-if (!data->request.down.empty())
- cout << "down = " << info.down << endl;
-
-if (!data->request.passive.empty())
- cout << "passive = " << info.passive << endl;
-
-if (!data->request.disableDetailStat.empty())
- cout << "disableDetailStat = " << info.disableDetailStat << endl;
-
-if (!data->request.alwaysOnline.empty())
- cout << "alwaysOnline = " << info.alwaysOnline << endl;
-
-if (!data->request.prepaidTraff.empty())
- cout << "prepaidTraff = " << info.prepaidTraff << endl;
-
-for (int i = 0; i < DIR_NUM; i++)
- {
- if (!data->request.sessionUpload[i].empty())
- cout << "session upload for dir " << i << " = " << info.stat.su[i] << endl;
- if (!data->request.sessionDownload[i].empty())
- cout << "session download for dir " << i << "=" << info.stat.sd[i] << endl;
- }
-
-for (int i = 0; i < DIR_NUM; i++)
- {
- if (!data->request.monthUpload[i].empty())
- cout << "month upload for dir " << i << " = " << info.stat.mu[i] << endl;
- if (!data->request.monthDownload[i].empty())
- cout << "month download for dir " << i << " = " << info.stat.md[i] << endl;
- }
-
-for (int i = 0; i < USERDATA_NUM; i++)
- {
- if (!data->request.userData[i].empty())
- {
- std::string str;
- ConvertFromKOI8(info.userData[i], &str);
- cout << "user data " << i << " = " << str << endl;
- }
- }
-
-StringReqParams strReqParams[] =
-{
- {"note", data->request.note, &info.note},
- {"name", data->request.name, &info.name},
- {"address", data->request.address, &info.address},
- {"email", data->request.email, &info.email},
- {"phone", data->request.phone, &info.phone},
- {"group", data->request.group, &info.group},
- {"tariff", data->request.tariff, &info.tariff},
- {"password", data->request.usrPasswd, &info.password},
- {"ip", data->request.ips, &info.ips} // IP-address of user
-};
-for (unsigned i = 0; i < sizeof(strReqParams) / sizeof(StringReqParams); i++)
- {
- if (!strReqParams[i].reqParam.empty())
- {
- string str;
- ConvertFromKOI8(*strReqParams[i].value, &str);
- cout << strReqParams[i].name << " = " << str << endl;
- }
- }
-data->result = true;
-}
-//-----------------------------------------------------------------------------
-bool ProcessSetUser(const std::string & server,
- int port,
- const std::string & login,
- const std::string & password,
- 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(user, conf, stat, ResultCallback, &data);
-
-if (res == st_ok && data.result)
- {
- printf("Ok\n");
- return false;
- }
-
-printf("Error\n");
-if (res != st_ok)
- printf("%s\n", sc.GetStrError().c_str());
-else
- printf("%s\n", data.reason.c_str());
-return true;
-}
-//-----------------------------------------------------------------------------
-bool ProcessSendMessage(const std::string & server, uint16_t port,
- const std::string & login, const std::string & password,
- const std::string & user, const std::string & text)
-{
-SERVCONF sc(server, port, login, password);
-
-ResultData data;
-int res = sc.SendMessage(user, text, ResultCallback, &data);
-
-if (res == st_ok && data.result)
- {
- printf("Ok\n");
- return true;
- }
-
-printf("Error\n");
-if (res != st_ok)
- printf("%s\n", sc.GetStrError().c_str());
-else
- printf("%s\n", data.reason.c_str());
-return false;
-}
-//-----------------------------------------------------------------------------
-bool ProcessGetUser(const std::string &server,
- int port,
- const std::string &admLogin,
- const std::string &admPasswd,
- const std::string &login,
- REQUEST & request)
-{
-SERVCONF sc(server, port, admLogin, admPasswd);
-
-GetUserData data(request, false);
-bool res = (sc.GetUser(login.c_str(), GetUserCallback, &data) == st_ok);
-
-if (res && data.result)
- {
- printf("Ok\n");
- return true;
- }
-
-printf("Error\n");
-if (!res)
- printf("%s\n", sc.GetStrError().c_str());
-else
- printf("%s\n", data.reason.c_str());
-return false;
-}
-//-----------------------------------------------------------------------------
-bool ProcessAuthBy(const std::string &server,
- int port,
- const std::string &admLogin,
- const std::string &admPasswd,
- const std::string &login)
-{
-SERVCONF sc(server, port, admLogin, admPasswd);
-
-ResultData data;
-bool res = (sc.AuthBy(login.c_str(), RecvAuthByData, &data) == st_ok);
-
-if (res && data.result)
- {
- printf("Ok\n");
- return true;
- }
-
-printf("Error\n");
-if (!res)
- printf("%s\n", sc.GetStrError().c_str());
-else
- printf("%s\n", data.reason.c_str());
-return false;
-}
-//-----------------------------------------------------------------------------
+++ /dev/null
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/*
- * Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- */
-
- /*
- $Author: faust $
- $Revision: 1.5 $
- $Date: 2009/06/08 10:02:28 $
- */
-
-
-#ifndef COMMON_SG_H
-#define COMMON_SG_H
-
-#include "stg/servconf.h"
-#include "stg/servconf_types.h"
-#include "request.h"
-
-#include <string>
-
-struct USER_CONF_RES;
-struct USER_STAT_RES;
-
-void UsageConf();
-void UsageInfo();
-
-char * ParseUser(char * usr);
-char * ParsePassword(char * pass);
-char * ParseAdminLogin(char * adm);
-short int ParseServerPort(const char * p);
-void ParseAnyString(const char * c, string * msg, const char * enc = "cp1251");
-int CheckLogin(const char * login);
-void ConvertFromKOI8(const std::string & src, std::string * dst);
-void ConvertToKOI8(const std::string & src, std::string * dst);
-
-bool ProcessGetUser(const std::string & server,
- int port,
- const std::string & admLogin,
- const std::string & admPasswd,
- const std::string & login,
- REQUEST & request);
-
-bool ProcessAuthBy(const std::string & server,
- int port,
- const std::string & admLogin,
- const std::string & admPasswd,
- const std::string & login);
-
-bool ProcessSetUser(const std::string & server,
- int port,
- const std::string & admLogin,
- const std::string & admPasswd,
- 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,
- const std::string & user, const std::string & text);
-
-#endif
RESETABLE<std::string> configFile;
RESETABLE<std::string> server;
RESETABLE<uint16_t> port;
+ RESETABLE<std::string> localAddress;
+ RESETABLE<uint16_t> localPort;
RESETABLE<std::string> userName;
RESETABLE<std::string> userPass;
server = rhs.server;
if (!rhs.port.empty())
port = rhs.port;
+ if (!rhs.localAddress.empty())
+ localAddress = rhs.localAddress;
+ if (!rhs.localPort.empty())
+ localPort = rhs.localPort;
if (!rhs.userName.empty())
userName = rhs.userName;
if (!rhs.userPass.empty())
{
std::string res("{ ");
if (!configFile.empty())
- res += "configFile: '" + configFile.data() + "'";
+ res += "configFile: '" + configFile.data() + "',";
if (!server.empty())
- res += ", server: '" + server.data() + "'";
+ res += " server: '" + server.data() + "',";
if (!port.empty())
- res += ", port: " + x2str(port.data());
+ res += " port: " + x2str(port.data()) + ",";
+ if (!localAddress.empty())
+ res += " local address: '" + localAddress.data() + "',";
+ if (!localPort.empty())
+ res += " local port: " + x2str(localPort.data()) + ",";
if (!userName.empty())
- res += ", userName: '" + userName.data() + "'";
+ res += " userName: '" + userName.data() + "',";
if (!userPass.empty())
- res += ", userPass: '" + userPass.data() + "'";
+ res += " userPass: '" + userPass.data() + "'";
return res + " }";
}
};
-}
+} // namespace SGCONF
#endif
--- /dev/null
+#include "corps.h"
+
+#include "api_action.h"
+#include "options.h"
+#include "config.h"
+#include "utils.h"
+
+#include "stg/servconf.h"
+#include "stg/servconf_types.h"
+#include "stg/corp_conf.h"
+#include "stg/common.h"
+
+#include <iostream>
+#include <string>
+#include <map>
+
+namespace
+{
+
+std::string Indent(size_t level, bool dash = false)
+{
+if (level == 0)
+ return "";
+return dash ? std::string(level * 4 - 2, ' ') + "- " : std::string(level * 4, ' ');
+}
+
+void PrintCorp(const STG::GET_CORP::INFO & info, size_t level = 0)
+{
+std::cout << Indent(level, true) << "name: " << info.name << "\n"
+ << Indent(level) << "cash: " << info.cash << "\n";
+}
+
+std::vector<SGCONF::API_ACTION::PARAM> GetCorpParams()
+{
+std::vector<SGCONF::API_ACTION::PARAM> params;
+params.push_back(SGCONF::API_ACTION::PARAM("cash", "<cash>", "\tcorporation's cash"));
+return params;
+}
+
+void SimpleCallback(bool result,
+ const std::string & reason,
+ void * /*data*/)
+{
+if (!result)
+ {
+ std::cerr << "Operation failed. Reason: '" << reason << "'." << std::endl;
+ return;
+ }
+std::cout << "Success.\n";
+}
+
+void GetCorpsCallback(bool result,
+ const std::string & reason,
+ const std::vector<STG::GET_CORP::INFO> & info,
+ void * /*data*/)
+{
+if (!result)
+ {
+ std::cerr << "Failed to get corp list. Reason: '" << reason << "'." << std::endl;
+ return;
+ }
+std::cout << "Corps:\n";
+for (size_t i = 0; i < info.size(); ++i)
+ PrintCorp(info[i], 1);
+}
+
+void GetCorpCallback(bool result,
+ const std::string & reason,
+ const STG::GET_CORP::INFO & info,
+ void * /*data*/)
+{
+if (!result)
+ {
+ std::cerr << "Failed to get corp. Reason: '" << reason << "'." << std::endl;
+ return;
+ }
+PrintCorp(info);
+}
+
+bool GetCorpsFunction(const SGCONF::CONFIG & config,
+ const std::string & /*arg*/,
+ const std::map<std::string, std::string> & /*options*/)
+{
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.GetCorporations(GetCorpsCallback, NULL) == STG::st_ok;
+}
+
+bool GetCorpFunction(const SGCONF::CONFIG & config,
+ const std::string & arg,
+ const std::map<std::string, std::string> & /*options*/)
+{
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.GetCorp(arg, GetCorpCallback, NULL) == STG::st_ok;
+}
+
+bool DelCorpFunction(const SGCONF::CONFIG & config,
+ const std::string & arg,
+ const std::map<std::string, std::string> & /*options*/)
+{
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.DelCorp(arg, SimpleCallback, NULL) == STG::st_ok;
+}
+
+bool AddCorpFunction(const SGCONF::CONFIG & config,
+ const std::string & arg,
+ const std::map<std::string, std::string> & options)
+{
+CORP_CONF_RES conf;
+conf.name = arg;
+SGCONF::MaybeSet(options, "cash", conf.cash);
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.AddCorp(arg, conf, SimpleCallback, NULL) == STG::st_ok;
+}
+
+bool ChgCorpFunction(const SGCONF::CONFIG & config,
+ const std::string & arg,
+ const std::map<std::string, std::string> & options)
+{
+CORP_CONF_RES conf;
+conf.name = arg;
+SGCONF::MaybeSet(options, "cash", conf.cash);
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.ChgCorp(conf, SimpleCallback, NULL) == STG::st_ok;
+}
+
+} // namespace anonymous
+
+void SGCONF::AppendCorpsOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks)
+{
+std::vector<API_ACTION::PARAM> params(GetCorpParams());
+blocks.Add("Corporation management options")
+ .Add("get-corps", SGCONF::MakeAPIAction(commands, GetCorpsFunction), "\tget corporation list")
+ .Add("get-corp", SGCONF::MakeAPIAction(commands, "<name>", GetCorpFunction), "get corporation")
+ .Add("add-corp", SGCONF::MakeAPIAction(commands, "<name>", params, AddCorpFunction), "add corporation")
+ .Add("del-corp", SGCONF::MakeAPIAction(commands, "<name>", DelCorpFunction), "delete corporation")
+ .Add("chg-corp", SGCONF::MakeAPIAction(commands, "<name>", params, ChgCorpFunction), "change corporation");
+}
--- /dev/null
+#ifndef __STG_SGCONF_CORPS_H__
+#define __STG_SGCONF_CORPS_H__
+
+namespace SGCONF
+{
+
+class OPTION_BLOCKS;
+class COMMANDS;
+
+void AppendCorpsOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks);
+
+} // namespace SGCONF
+
+#endif
* Author : Maxim Mamontov <faust@stargazer.dp.ua>
*/
-#include "request.h"
-#include "common_sg.h"
-#include "sg_error_codes.h"
-
#include "xml.h"
+#include "admins.h"
+#include "tariffs.h"
+#include "users.h"
+#include "services.h"
+#include "corps.h"
+
+#include "api_action.h"
#include "options.h"
#include "actions.h"
#include "config.h"
-#include "stg/user_conf.h"
-#include "stg/user_stat.h"
-#include "stg/common.h"
-
-#include <cerrno>
-#include <clocale>
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
#include <string>
-#include <sstream>
+#include <iostream>
-#include <unistd.h>
-#include <getopt.h>
-#include <iconv.h>
-#include <langinfo.h>
+#include <cstdlib> // getenv
+#include <cstring> // str*
-namespace
-{
-
-template <typename T>
-struct ARRAY_TYPE
-{
-typedef typename T::value_type type;
-};
-
-template <typename T>
-struct ARRAY_TYPE<T[]>
-{
-typedef T type;
-};
+#include <unistd.h> // access
+#include <libgen.h> // basename
-template <typename T, size_t N>
-struct ARRAY_TYPE<T[N]>
+namespace
{
-typedef T type;
-};
template <typename T>
struct nullary_function
return binder0<F>(func, arg);
}
+template <typename A, typename R>
+class FUNC1_ADAPTER : public std::unary_function<A, R>
+{
+ public:
+ FUNC1_ADAPTER(R (*func)(A)) : m_func(func) {}
+ const R operator()(A arg) const { return (m_func)(arg); }
+ private:
+ R (*m_func)(A);
+};
+
template <typename C, typename A, typename R>
class METHOD1_ADAPTER : public std::unary_function<A, R>
{
C & m_obj;
};
+template <typename A, typename R>
+FUNC1_ADAPTER<A, R> Func1Adapt(R (func)(A))
+{
+return FUNC1_ADAPTER<A, R>(func);
+}
+
template <typename C, typename A, typename R>
METHOD1_ADAPTER<C, A, R> Method1Adapt(R (C::* func)(A), C & obj)
{
return CONST_METHOD1_ADAPTER<C, A, R>(func, obj);
}
-template <typename T>
-bool SetArrayItem(T & array, const char * index, const typename ARRAY_TYPE<T>::type & value)
-{
-size_t pos = 0;
-if (str2x(index, pos))
- return false;
-array[pos] = value;
-return true;
-}
-
-void RawXMLCallback(bool result, const std::string & reason, const std::string & response, void * data)
+void Version(const std::string & self)
{
-if (!result)
- {
- std::cerr << "Failed to get raw XML response. Reason: '" << reason << "'." << std::endl;
- return;
- }
-PrintXML(response);
+std::cout << self << ", version: 2.0.0-alpha.\n";
}
-void Usage();
-void UsageAll();
-void UsageImpl(bool full);
-void UsageConnection();
-void UsageAdmins(bool full);
-void UsageTariffs(bool full);
-void UsageUsers(bool full);
-void UsageServices(bool full);
-void UsageCorporations(bool full);
-
-void Version();
-
void ReadUserConfigFile(SGCONF::OPTION_BLOCK & block)
{
std::vector<std::string> paths;
class CONFIG_ACTION : public ACTION
{
public:
- CONFIG_ACTION(CONFIG & config,
+ CONFIG_ACTION(SGCONF::CONFIG & config,
const std::string & paramDescription)
: m_config(config),
m_description(paramDescription)
virtual std::string ParamDescription() const { return m_description; }
virtual std::string DefaultDescription() const { return ""; }
virtual OPTION_BLOCK & Suboptions() { return m_suboptions; }
- virtual PARSER_STATE Parse(int argc, char ** argv);
+ virtual PARSER_STATE Parse(int argc, char ** argv, void * /*data*/);
private:
- CONFIG & m_config;
+ SGCONF::CONFIG & m_config;
std::string m_description;
OPTION_BLOCK m_suboptions;
void ParseHostAndPort(const std::string & hostAndPort);
};
-class COMMAND_FUNCTOR
-{
- public:
- virtual ~COMMAND_FUNCTOR() {}
- virtual bool operator()(const std::string& arg, const std::map<std::string, std::string>& options) = 0;
-};
-
-class COMMAND_ACTION : public ACTION
-{
- public:
- COMMAND_ACTION(CONFIG & config,
- const std::string & paramDescription,
- bool needArgument,
- const OPTION_BLOCK& suboptions,
- COMMAND_FUNCTOR* funPtr)
- : m_config(config),
- m_description(paramDescription),
- m_argument(needArgument),
- m_suboptions(suboptions),
- m_funPtr(funPtr)
- {}
-
- virtual ACTION * Clone() const { return new COMMAND_ACTION(*this); }
-
- virtual std::string ParamDescription() const { return m_description; }
- virtual std::string DefaultDescription() const { return ""; }
- virtual OPTION_BLOCK & Suboptions() { return m_suboptions; }
- virtual PARSER_STATE Parse(int argc, char ** argv)
- {
- PARSER_STATE state(false, argc, argv);
- if (m_argument)
- {
- if (argc == 0 ||
- argv == NULL ||
- *argv == NULL)
- throw ERROR("Missing argument.");
- m_argument = *argv;
- --state.argc;
- ++state.argv;
- }
- std::list<OPTION_BLOCK>::iterator it(m_suboptions.begin());
- while (!state.stop && it != m_suboptions.end())
- {
- state = it->Parse(state.argc, state.argv);
- ++it;
- }
- m_funPtr(m_argument, m_params);
- return state;
- }
- private:
- CONFIG & m_config;
- std::string m_description;
- bool m_needArgument;
- std::string m_argument;
- OPTION_BLOCK m_suboptions;
- std::map<std::string, std::string> m_params;
- COMMAND_FUNCTOR* m_funPtr;
-};
-
-PARSER_STATE CONFIG_ACTION::Parse(int argc, char ** argv)
+PARSER_STATE CONFIG_ACTION::Parse(int argc, char ** argv, void * /*data*/)
{
if (argc == 0 ||
argv == NULL ||
}
inline
-CONFIG_ACTION * MakeParamAction(CONFIG & config,
+CONFIG_ACTION * MakeParamAction(SGCONF::CONFIG & config,
const std::string & paramDescription)
{
return new CONFIG_ACTION(config, paramDescription);
} // namespace SGCONF
-time_t stgTime;
-
-struct option long_options_get[] = {
-{"server", 1, 0, 's'}, //Server
-{"port", 1, 0, 'p'}, //Port
-{"admin", 1, 0, 'a'}, //Admin
-{"admin_pass", 1, 0, 'w'}, //passWord
-{"user", 1, 0, 'u'}, //User
-{"addcash", 0, 0, 'c'}, //Add Cash
-//{"setcash", 0, 0, 'v'}, //Set Cash
-{"credit", 0, 0, 'r'}, //cRedit
-{"tariff", 0, 0, 't'}, //Tariff
-{"message", 0, 0, 'm'}, //message
-{"password", 0, 0, 'o'}, //password
-{"down", 0, 0, 'd'}, //down
-{"passive", 0, 0, 'i'}, //passive
-{"disable-stat",0, 0, 'S'}, //disable detail stat
-{"always-online",0, 0, 'O'}, //always online
-{"session-upload", 1, 0, 500}, //SU0
-{"session-download", 1, 0, 501}, //SD0
-{"month-upload", 1, 0, 502}, //MU0
-{"month-download", 1, 0, 503}, //MD0
-
-{"user-data", 1, 0, 700}, //UserData0
-
-{"prepaid", 0, 0, 'e'}, //prepaid traff
-{"create", 0, 0, 'n'}, //create
-{"delete", 0, 0, 'l'}, //delete
-
-{"note", 0, 0, 'N'}, //Note
-{"name", 0, 0, 'A'}, //nAme
-{"address", 0, 0, 'D'}, //aDdress
-{"email", 0, 0, 'L'}, //emaiL
-{"phone", 0, 0, 'P'}, //phone
-{"group", 0, 0, 'G'}, //Group
-{"ip", 0, 0, 'I'}, //IP-address of user
-{"authorized-by",0, 0, 800}, //always online
-
-{0, 0, 0, 0}};
-
-struct option long_options_set[] = {
-{"server", 1, 0, 's'}, //Server
-{"port", 1, 0, 'p'}, //Port
-{"admin", 1, 0, 'a'}, //Admin
-{"admin_pass", 1, 0, 'w'}, //passWord
-{"user", 1, 0, 'u'}, //User
-{"addcash", 1, 0, 'c'}, //Add Cash
-{"setcash", 1, 0, 'v'}, //Set Cash
-{"credit", 1, 0, 'r'}, //cRedit
-{"tariff", 1, 0, 't'}, //Tariff
-{"message", 1, 0, 'm'}, //message
-{"password", 1, 0, 'o'}, //password
-{"down", 1, 0, 'd'}, //down
-{"passive", 1, 0, 'i'}, //passive
-{"disable-stat",1, 0, 'S'}, //disable detail stat
-{"always-online",1, 0, 'O'}, //always online
-{"session-upload", 1, 0, 500}, //U0
-{"session-download", 1, 0, 501}, //U1
-{"month-upload", 1, 0, 502}, //U2
-{"month-download", 1, 0, 503}, //U3
-
-{"user-data", 1, 0, 700}, //UserData
-
-{"prepaid", 1, 0, 'e'}, //prepaid traff
-{"create", 1, 0, 'n'}, //create
-{"delete", 1, 0, 'l'}, //delete
-
-{"note", 1, 0, 'N'}, //Note
-{"name", 1, 0, 'A'}, //nAme
-{"address", 1, 0, 'D'}, //aDdress
-{"email", 1, 0, 'L'}, //emaiL
-{"phone", 1, 0, 'P'}, //phone
-{"group", 1, 0, 'G'}, //Group
-{"ip", 0, 0, 'I'}, //IP-address of user
-
-{0, 0, 0, 0}};
-
-//-----------------------------------------------------------------------------
-CASH_INFO ParseCash(const char * str)
-{
-//-c 123.45:log message
-std::string cashString;
-std::string message;
-const char * pos = strchr(str, ':');
-if (pos != NULL)
- {
- cashString.append(str, pos);
- message.append(pos + 1);
- }
-else
- cashString = str;
-
-double cash = 0;
-if (strtodouble2(cashString, cash) != 0)
- {
- printf("Incorrect cash value %s\n", str);
- exit(PARAMETER_PARSING_ERR_CODE);
- }
-
-return CASH_INFO(cash, message);
-}
-//-----------------------------------------------------------------------------
-double ParseCredit(const char * c)
-{
-double credit;
-if (strtodouble2(c, credit) != 0)
- {
- printf("Incorrect credit value %s\n", c);
- exit(PARAMETER_PARSING_ERR_CODE);
- }
-
-return credit;
-}
-//-----------------------------------------------------------------------------
-double ParsePrepaidTraffic(const char * c)
-{
-double credit;
-if (strtodouble2(c, credit) != 0)
- {
- printf("Incorrect prepaid traffic value %s\n", c);
- exit(PARAMETER_PARSING_ERR_CODE);
- }
-
-return credit;
-}
-//-----------------------------------------------------------------------------
-int64_t ParseTraff(const char * c)
-{
-int64_t traff;
-if (str2x(c, traff) != 0)
- {
- printf("Incorrect credit value %s\n", c);
- exit(PARAMETER_PARSING_ERR_CODE);
- }
-
-return traff;
-}
-//-----------------------------------------------------------------------------
-bool ParseDownPassive(const char * dp)
-{
-if (!(dp[1] == 0 && (dp[0] == '1' || dp[0] == '0')))
- {
- printf("Incorrect value %s\n", dp);
- exit(PARAMETER_PARSING_ERR_CODE);
- }
-
-return dp[0] - '0';
-}
-//-----------------------------------------------------------------------------
-void ParseTariff(const char * str, RESETABLE<std::string> & tariffName, RESETABLE<std::string> & nextTariff)
-{
-const char * pos = strchr(str, ':');
-if (pos != NULL)
- {
- 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);
- }
- }
-else
- tariffName = str;
-}
-//-----------------------------------------------------------------------------
-time_t ParseCreditExpire(const char * str)
-{
-struct tm brokenTime;
-
-brokenTime.tm_wday = 0;
-brokenTime.tm_yday = 0;
-brokenTime.tm_isdst = 0;
-brokenTime.tm_hour = 0;
-brokenTime.tm_min = 0;
-brokenTime.tm_sec = 0;
-
-stg_strptime(str, "%Y-%m-%d", &brokenTime);
-
-return stg_timegm(&brokenTime);
-}
-//-----------------------------------------------------------------------------
-void ParseAnyString(const char * c, string * msg, const char * enc)
-{
-iconv_t cd;
-char * ob = new char[strlen(c) + 1];
-char * ib = new char[strlen(c) + 1];
-
-strcpy(ib, c);
-
-char * outbuf = ob;
-char * inbuf = ib;
-
-setlocale(LC_ALL, "");
-
-char charsetF[255];
-strncpy(charsetF, nl_langinfo(CODESET), 255);
-
-const char * charsetT = enc;
-
-size_t nconv = 1;
-
-size_t insize = strlen(ib);
-size_t outsize = strlen(ib);
-
-insize = strlen(c);
-
-cd = iconv_open(charsetT, charsetF);
-if (cd == (iconv_t) -1)
- {
- if (errno == EINVAL)
- {
- printf("Warning: iconv from %s to %s failed\n", charsetF, charsetT);
- *msg = c;
- return;
- }
- else
- printf("error iconv_open\n");
-
- exit(ICONV_ERR_CODE);
- }
-
-#if defined(FREE_BSD) || defined(FREE_BSD5)
-nconv = iconv (cd, (const char**)&inbuf, &insize, &outbuf, &outsize);
-#else
-nconv = iconv (cd, &inbuf, &insize, &outbuf, &outsize);
-#endif
-//printf("nconv=%d outsize=%d\n", nconv, outsize);
-if (nconv == (size_t) -1)
- {
- if (errno != EINVAL)
- {
- printf("iconv error\n");
- exit(ICONV_ERR_CODE);
- }
- }
-
-*outbuf = L'\0';
-
-iconv_close(cd);
-*msg = ob;
-
-delete[] ob;
-delete[] ib;
-}
-//-----------------------------------------------------------------------------
-void CreateRequestSet(REQUEST * req, char * r)
-{
-const int strLen = 10024;
-char str[strLen];
-memset(str, 0, strLen);
-
-r[0] = 0;
-
-if (!req->usrMsg.empty())
- {
- string msg;
- Encode12str(msg, req->usrMsg.data());
- 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());
- //sprintf(str, "<message login=\"%s\" priority=\"0\" text=\"%s\"/>\n", req->login, msg);
- strcat(r, str);
- return;
- }
-
-if (req->deleteUser)
- {
- sprintf(str, "<DelUser login=\"%s\"/>", req->login.const_data().c_str());
- strcat(r, str);
- //printf("%s\n", r);
- return;
- }
-
-if (req->createUser)
- {
- sprintf(str, "<AddUser> <login value=\"%s\"/> </AddUser>", req->login.const_data().c_str());
- strcat(r, str);
- //printf("%s\n", r);
- return;
- }
-
-strcat(r, "<SetUser>\n");
-sprintf(str, "<login value=\"%s\"/>\n", req->login.const_data().c_str());
-strcat(r, str);
-if (!req->credit.empty())
- {
- sprintf(str, "<credit value=\"%f\"/>\n", req->credit.const_data());
- strcat(r, str);
- }
-
-if (!req->creditExpire.empty())
- {
- sprintf(str, "<creditExpire value=\"%ld\"/>\n", req->creditExpire.const_data());
- strcat(r, str);
- }
-
-if (!req->prepaidTraff.empty())
- {
- sprintf(str, "<FreeMb value=\"%f\"/>\n", req->prepaidTraff.const_data());
- strcat(r, str);
- }
-
-if (!req->cash.empty())
- {
- string msg;
- Encode12str(msg, req->message);
- sprintf(str, "<cash add=\"%f\" msg=\"%s\"/>\n", req->cash.const_data(), msg.c_str());
- strcat(r, str);
- }
-
-if (!req->setCash.empty())
- {
- string msg;
- Encode12str(msg, req->message);
- sprintf(str, "<cash set=\"%f\" msg=\"%s\"/>\n", req->setCash.const_data(), msg.c_str());
- strcat(r, str);
- }
-
-if (!req->usrPasswd.empty())
- {
- sprintf(str, "<password value=\"%s\" />\n", req->usrPasswd.const_data().c_str());
- strcat(r, str);
- }
-
-if (!req->down.empty())
- {
- sprintf(str, "<down value=\"%d\" />\n", req->down.const_data());
- strcat(r, str);
- }
-
-if (!req->passive.empty())
- {
- sprintf(str, "<passive value=\"%d\" />\n", req->passive.const_data());
- strcat(r, str);
- }
-
-if (!req->disableDetailStat.empty())
- {
- sprintf(str, "<disableDetailStat value=\"%d\" />\n", req->disableDetailStat.const_data());
- strcat(r, str);
- }
-
-if (!req->alwaysOnline.empty())
- {
- sprintf(str, "<aonline value=\"%d\" />\n", req->alwaysOnline.const_data());
- strcat(r, str);
- }
-
-// IP-address of user
-if (!req->ips.empty())
- {
- sprintf(str, "<ip value=\"%s\" />\n", req->ips.const_data().c_str());
- strcat(r, str);
- }
-
-int uPresent = false;
-int dPresent = false;
-for (int i = 0; i < DIR_NUM; i++)
- {
- if (!req->monthUpload[i].empty())
- {
- if (!uPresent && !dPresent)
- {
- sprintf(str, "<traff ");
- strcat(r, str);
- uPresent = true;
- }
-
- stringstream ss;
- ss << req->monthUpload[i].const_data();
- //sprintf(str, "MU%d=\"%lld\" ", i, req->u[i].const_data());
- sprintf(str, "MU%d=\"%s\" ", i, ss.str().c_str());
- strcat(r, str);
- }
- if (!req->monthDownload[i].empty())
- {
- if (!uPresent && !dPresent)
- {
- sprintf(str, "<traff ");
- strcat(r, str);
- dPresent = true;
- }
-
- stringstream ss;
- ss << req->monthDownload[i].const_data();
- sprintf(str, "MD%d=\"%s\" ", i, ss.str().c_str());
- strcat(r, str);
- }
- if (!req->sessionUpload[i].empty())
- {
- if (!uPresent && !dPresent)
- {
- sprintf(str, "<traff ");
- strcat(r, str);
- uPresent = true;
- }
-
- stringstream ss;
- ss << req->sessionUpload[i].const_data();
- //sprintf(str, "MU%d=\"%lld\" ", i, req->u[i].const_data());
- sprintf(str, "MU%d=\"%s\" ", i, ss.str().c_str());
- strcat(r, str);
- }
- if (!req->sessionDownload[i].empty())
- {
- if (!uPresent && !dPresent)
- {
- sprintf(str, "<traff ");
- strcat(r, str);
- dPresent = true;
- }
-
- stringstream ss;
- ss << req->sessionDownload[i].const_data();
- sprintf(str, "MD%d=\"%s\" ", i, ss.str().c_str());
- strcat(r, str);
- }
- }
-if (uPresent || dPresent)
- {
- strcat(r, "/>");
- }
-
-//printf("%s\n", r);
-
-if (!req->tariff.empty())
- {
- switch (req->chgTariff)
- {
- case TARIFF_NOW:
- sprintf(str, "<tariff now=\"%s\"/>\n", req->tariff.const_data().c_str());
- strcat(r, str);
- break;
- case TARIFF_REC:
- sprintf(str, "<tariff recalc=\"%s\"/>\n", req->tariff.const_data().c_str());
- strcat(r, str);
- break;
- case TARIFF_DEL:
- sprintf(str, "<tariff delayed=\"%s\"/>\n", req->tariff.const_data().c_str());
- strcat(r, str);
- break;
- }
-
- }
-
-if (!req->note.empty())
- {
- string note;
- Encode12str(note, req->note.data());
- sprintf(str, "<note value=\"%s\"/>", note.c_str());
- strcat(r, str);
- }
-
-if (!req->name.empty())
- {
- string name;
- Encode12str(name, req->name.data());
- sprintf(str, "<name value=\"%s\"/>", name.c_str());
- strcat(r, str);
- }
-
-if (!req->address.empty())
- {
- string address;
- Encode12str(address, req->address.data());
- sprintf(str, "<address value=\"%s\"/>", address.c_str());
- strcat(r, str);
- }
-
-if (!req->email.empty())
- {
- string email;
- Encode12str(email, req->email.data());
- sprintf(str, "<email value=\"%s\"/>", email.c_str());
- strcat(r, str);
- }
-
-if (!req->phone.empty())
- {
- string phone;
- Encode12str(phone, req->phone.data());
- sprintf(str, "<phone value=\"%s\"/>", phone.c_str());
- strcat(r, str);
- }
-
-if (!req->group.empty())
- {
- string group;
- Encode12str(group, req->group.data());
- sprintf(str, "<group value=\"%s\"/>", group.c_str());
- strcat(r, str);
- }
-
-for (int i = 0; i < USERDATA_NUM; i++)
- {
- if (!req->userData[i].empty())
- {
- string ud;
- Encode12str(ud, req->userData[i].data());
- sprintf(str, "<userdata%d value=\"%s\"/>", i, ud.c_str());
- strcat(r, str);
- }
- }
-
-strcat(r, "</SetUser>\n");
-}
-//-----------------------------------------------------------------------------
-int CheckParameters(REQUEST * req)
-{
-bool su = false;
-bool sd = false;
-bool mu = false;
-bool md = false;
-bool ud = false;
-bool a = !req->admLogin.empty()
- && !req->admPasswd.empty()
- && !req->server.empty()
- && !req->port.empty()
- && !req->login.empty();
-
-bool b = !req->cash.empty()
- || !req->setCash.empty()
- || !req->credit.empty()
- || !req->prepaidTraff.empty()
- || !req->tariff.empty()
- || !req->usrMsg.empty()
- || !req->usrPasswd.empty()
-
- || !req->note.empty()
- || !req->name.empty()
- || !req->address.empty()
- || !req->email.empty()
- || !req->phone.empty()
- || !req->group.empty()
- || !req->ips.empty() // IP-address of user
-
- || !req->createUser
- || !req->deleteUser;
-
-
-for (int i = 0; i < DIR_NUM; i++)
- {
- if (req->sessionUpload[i].empty())
- {
- su = true;
- break;
- }
- }
-
-for (int i = 0; i < DIR_NUM; i++)
- {
- if (req->sessionDownload[i].empty())
- {
- sd = true;
- break;
- }
- }
-
-for (int i = 0; i < DIR_NUM; i++)
- {
- if (req->monthUpload[i].empty())
- {
- mu = true;
- break;
- }
- }
-
-for (int i = 0; i < DIR_NUM; i++)
- {
- if (req->monthDownload[i].empty())
- {
- md = true;
- break;
- }
- }
-
-for (int i = 0; i < DIR_NUM; i++)
- {
- if (req->userData[i].empty())
- {
- ud = true;
- break;
- }
- }
-
-
-//printf("a=%d, b=%d, u=%d, d=%d ud=%d\n", a, b, u, d, ud);
-return a && (b || su || sd || mu || md || ud);
-}
-//-----------------------------------------------------------------------------
-int CheckParametersGet(REQUEST * req)
-{
-return CheckParameters(req);
-}
-//-----------------------------------------------------------------------------
-int CheckParametersSet(REQUEST * req)
-{
-return CheckParameters(req);
-}
-//-----------------------------------------------------------------------------
-bool mainGet(int argc, char **argv)
-{
-int c;
-REQUEST req;
-RESETABLE<string> t1;
-int missedOptionArg = false;
-
-const char * short_options_get = "s:p:a:w:u:crtmodieNADLPGISOE";
-int option_index = -1;
-
-while (1)
- {
- option_index = -1;
- c = getopt_long(argc, argv, short_options_get, long_options_get, &option_index);
- if (c == -1)
- break;
-
- switch (c)
- {
- case 's': //server
- req.server = optarg;
- break;
-
- case 'p': //port
- req.port = ParseServerPort(optarg);
- //req.portReq = 1;
- break;
-
- case 'a': //admin
- req.admLogin = ParseAdminLogin(optarg);
- break;
-
- case 'w': //admin password
- req.admPasswd = ParsePassword(optarg);
- break;
-
- case 'o': //change user password
- req.usrPasswd = " ";
- break;
-
- case 'u': //user
- req.login = ParseUser(optarg);
- break;
-
- case 'c': //get cash
- req.cash = 1;
- break;
-
- case 'r': //credit
- req.credit = 1;
- break;
-
- case 'E': //credit expire
- req.creditExpire = 1;
- break;
-
- case 'd': //down
- req.down = 1;
- break;
-
- case 'i': //passive
- req.passive = 1;
- break;
-
- case 't': //tariff
- req.tariff = " ";
- break;
-
- case 'e': //Prepaid Traffic
- req.prepaidTraff = 1;
- break;
-
- case 'N': //Note
- req.note = " ";
- break;
-
- case 'A': //nAme
- req.name = " ";
- break;
-
- case 'D': //aDdress
- req.address =" ";
- break;
-
- case 'L': //emaiL
- req.email = " ";
- break;
-
- case 'P': //phone
- req.phone = " ";
- break;
-
- case 'G': //Group
- req.group = " ";
- break;
-
- case 'I': //IP-address of user
- req.ips = " ";
- break;
-
- case 'S': //Detail stat status
- req.disableDetailStat = " ";
- break;
-
- case 'O': //Always online status
- req.alwaysOnline = " ";
- break;
-
- case 500: //U
- SetArrayItem(req.sessionUpload, optarg, 1);
- //req.sessionUpload[optarg] = 1;
- break;
- case 501:
- SetArrayItem(req.sessionDownload, optarg, 1);
- //req.sessionDownload[optarg] = 1;
- break;
- case 502:
- SetArrayItem(req.monthUpload, optarg, 1);
- //req.monthUpload[optarg] = 1;
- break;
- case 503:
- SetArrayItem(req.monthDownload, optarg, 1);
- //req.monthDownload[optarg] = 1;
- break;
-
- case 700: //UserData
- SetArrayItem(req.userData, optarg, std::string(" "));
- //req.userData[optarg] = " ";
- break;
-
- case 800:
- req.authBy = true;
- break;
-
- case '?':
- case ':':
- missedOptionArg = true;
- break;
-
- default:
- printf ("?? getopt returned character code 0%o ??\n", c);
- }
- }
-
-if (optind < argc)
- {
- printf ("non-option ARGV-elements: ");
- while (optind < argc)
- printf ("%s ", argv[optind++]);
- UsageInfo();
- exit(PARAMETER_PARSING_ERR_CODE);
- }
-
-if (missedOptionArg || !CheckParametersGet(&req))
- {
- //printf("Parameter needed\n");
- UsageInfo();
- exit(PARAMETER_PARSING_ERR_CODE);
- }
-
-if (req.authBy)
- return ProcessAuthBy(req.server.data(), req.port.data(), req.admLogin.data(), req.admPasswd.data(), req.login.data());
-else
- return ProcessGetUser(req.server.data(), req.port.data(), req.admLogin.data(), req.admPasswd.data(), req.login.data(), req);
-}
-//-----------------------------------------------------------------------------
-bool mainSet(int argc, char **argv)
-{
-string str;
-
-int c;
-bool isMessage = false;
-REQUEST req;
-
-RESETABLE<string> t1;
-
-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:";
-
-int missedOptionArg = false;
-
-USER_CONF_RES conf;
-USER_STAT_RES stat;
-while (1)
- {
- int option_index = -1;
-
- c = getopt_long(argc, argv, short_options_set, long_options_set, &option_index);
-
- if (c == -1)
- break;
-
- switch (c)
- {
- case 's': //server
- req.server = optarg;
- break;
-
- case 'p': //port
- req.port = ParseServerPort(optarg);
- //req.portReq = 1;
- break;
-
- case 'a': //admin
- req.admLogin = ParseAdminLogin(optarg);
- break;
-
- case 'w': //admin password
- req.admPasswd = ParsePassword(optarg);
- break;
-
- case 'o': //change user password
- conf.password = ParsePassword(optarg);
- break;
-
- case 'u': //user
- req.login = ParseUser(optarg);
- break;
-
- case 'c': //add cash
- stat.cashAdd = ParseCash(optarg);
- break;
-
- case 'v': //set cash
- stat.cashSet = ParseCash(optarg);
- break;
-
- case 'r': //credit
- conf.credit = ParseCredit(optarg);
- break;
-
- case 'E': //credit expire
- conf.creditExpire = ParseCreditExpire(optarg);
- break;
-
- case 'd': //down
- conf.disabled = ParseDownPassive(optarg);
- break;
-
- case 'i': //passive
- conf.passive = ParseDownPassive(optarg);
- break;
-
- case 't': //tariff
- ParseTariff(optarg, conf.tariffName, conf.nextTariff);
- break;
-
- case 'm': //message
- ParseAnyString(optarg, &str);
- req.usrMsg = str;
- isMessage = true;
- break;
-
- case 'e': //Prepaid Traffic
- stat.freeMb = ParsePrepaidTraffic(optarg);
- break;
-
- case 'n': //Create User
- req.createUser = true;
- break;
-
- case 'l': //Delete User
- req.deleteUser = true;
- break;
-
- case 'N': //Note
- ParseAnyString(optarg, &str, "koi8-ru");
- conf.note = str;
- break;
-
- case 'A': //nAme
- ParseAnyString(optarg, &str, "koi8-ru");
- conf.realName = str;
- break;
-
- case 'D': //aDdress
- ParseAnyString(optarg, &str, "koi8-ru");
- conf.address = str;
- break;
-
- case 'L': //emaiL
- ParseAnyString(optarg, &str, "koi8-ru");
- conf.email = str;
- break;
-
- case 'P': //phone
- ParseAnyString(optarg, &str);
- conf.phone = str;
- break;
-
- case 'G': //Group
- ParseAnyString(optarg, &str, "koi8-ru");
- conf.group = str;
- break;
-
- case 'I': //IP-address of user
- ParseAnyString(optarg, &str);
- conf.ips = StrToIPS(str);
- break;
-
- case 'S':
- conf.disabledDetailStat = ParseDownPassive(optarg);
- break;
-
- case 'O':
- conf.alwaysOnline = ParseDownPassive(optarg);
- break;
-
- case 500: //U
- SetArrayItem(stat.sessionUp, optarg, ParseTraff(argv[optind++]));
- break;
- case 501:
- SetArrayItem(stat.sessionDown, optarg, ParseTraff(argv[optind++]));
- break;
- case 502:
- SetArrayItem(stat.monthUp, optarg, ParseTraff(argv[optind++]));
- break;
- case 503:
- SetArrayItem(stat.monthDown, optarg, ParseTraff(argv[optind++]));
- break;
-
- case 700: //UserData
- ParseAnyString(argv[optind++], &str);
- SetArrayItem(conf.userdata, optarg, str);
- break;
-
- case '?':
- missedOptionArg = true;
- break;
-
- case ':':
- missedOptionArg = true;
- break;
-
- default:
- printf("?? getopt returned character code 0%o ??\n", c);
- }
- }
-
-if (optind < argc)
- {
- printf ("non-option ARGV-elements: ");
- while (optind < argc)
- printf ("%s ", argv[optind++]);
- UsageConf();
- exit(PARAMETER_PARSING_ERR_CODE);
- }
-
-if (missedOptionArg || !CheckParametersSet(&req))
- {
- //printf("Parameter needed\n");
- UsageConf();
- exit(PARAMETER_PARSING_ERR_CODE);
- }
-
-const int rLen = 20000;
-char rstr[rLen];
-memset(rstr, 0, rLen);
-
-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(), req.login.data(), conf, stat);
-}
//-----------------------------------------------------------------------------
int main(int argc, char **argv)
{
+std::string self(basename(argv[0]));
SGCONF::CONFIG config;
+SGCONF::COMMANDS commands;
SGCONF::OPTION_BLOCKS blocks;
blocks.Add("General options")
.Add("c", "config", SGCONF::MakeParamAction(config.configFile, std::string("~/.config/stg/sgconf.conf"), "<config file>"), "override default config file")
.Add("h", "help", SGCONF::MakeFunc0Action(bind0(Method1Adapt(&SGCONF::OPTION_BLOCKS::Help, blocks), 0)), "\t\tshow this help and exit")
- .Add("help-all", SGCONF::MakeFunc0Action(UsageAll), "\t\tshow full help and exit")
- .Add("v", "version", SGCONF::MakeFunc0Action(Version), "\t\tshow version information and exit");
+ //.Add("help-all", SGCONF::MakeFunc0Action(UsageAll), "\t\tshow full help and exit")
+ .Add("v", "version", SGCONF::MakeFunc0Action(bind0(Func1Adapt(Version), self)), "\t\tshow version information and exit");
SGCONF::OPTION_BLOCK & block = blocks.Add("Connection options")
.Add("s", "server", SGCONF::MakeParamAction(config.server, std::string("localhost"), "<address>"), "\t\thost to connect")
.Add("p", "port", SGCONF::MakeParamAction(config.port, uint16_t(5555), "<port>"), "\t\tport to connect")
+ .Add("local-address", SGCONF::MakeParamAction(config.localAddress, std::string(""), "<address>"), "\tlocal address to bind")
+ .Add("local-port", SGCONF::MakeParamAction(config.localPort, uint16_t(0), "<port>"), "\t\tlocal port to bind")
.Add("u", "username", SGCONF::MakeParamAction(config.userName, std::string("admin"), "<username>"), "\tadministrative login")
.Add("w", "userpass", SGCONF::MakeParamAction(config.userPass, "<password>"), "\tpassword for the administrative login")
.Add("a", "address", SGCONF::MakeParamAction(config, "<connection string>"), "connection params as a single string in format: <login>:<password>@<host>:<port>");
-blocks.Add("Raw XML")
- .Add("r", "raw", SGCONF::MakeFunc1Action(), "\t\tmake raw XML request")
-/*blocks.Add("Admins management options")
- .Add("get-admins", SGCONF::MakeConfAction())
- .Add("get-admin", SGCONF::MakeConfAction())
- .Add("add-admin", SGCONF::MakeConfAction())
- .Add("del-admin", SGCONF::MakeConfAction())
- .Add("chg-admin", SGCONF::MakeConfAction());*/
-
+SGCONF::AppendXMLOptionBlock(commands, blocks);
+SGCONF::AppendAdminsOptionBlock(commands, blocks);
+SGCONF::AppendTariffsOptionBlock(commands, blocks);
+SGCONF::AppendUsersOptionBlock(commands, blocks);
+SGCONF::AppendServicesOptionBlock(commands, blocks);
+SGCONF::AppendCorpsOptionBlock(commands, blocks);
SGCONF::PARSER_STATE state(false, argc, argv);
}
config = configOverride;
+
+std::cerr << "Config: " << config.Serialize() << std::endl;
+return commands.Execute(config) ? 0 : -1;
}
catch (const std::exception& ex)
{
std::cerr << ex.what() << "\n";
return -1;
}
-
-std::cerr << "Config: " << config.Serialize() << std::endl;
-
-return 0;
-
-if (argc < 2)
- {
- Usage();
- return 1;
- }
-
-if (argc <= 2)
- {
- UsageConf();
- exit(PARAMETER_PARSING_ERR_CODE);
- }
-
-if (strcmp(argv[1], "get") == 0)
- {
- //printf("get\n");
- return mainGet(argc - 1, argv + 1);
- }
-else if (strcmp(argv[1], "set") == 0)
- {
- //printf("set\n");
- if (mainSet(argc - 1, argv + 1) )
- return 0;
- return -1;
- }
-else
- {
- UsageConf();
- exit(PARAMETER_PARSING_ERR_CODE);
- }
-return UNKNOWN_ERR_CODE;
}
//-----------------------------------------------------------------------------
namespace
{
-void Usage()
-{
-UsageImpl(false);
-}
-
-void UsageAll()
-{
-UsageImpl(true);
-}
-
-void UsageImpl(bool full)
-{
-std::cout << "sgconf is the Stargazer management utility.\n\n"
- << "Usage:\n"
- << "\tsgconf [options]\n\n"
- << "General options:\n"
- << "\t-c, --config <config file>\t\toverride default config file (default: \"~/.config/stg/sgconf.conf\")\n"
- << "\t-h, --help\t\t\t\tshow this help and exit\n"
- << "\t--help-all\t\t\t\tshow full help and exit\n"
- << "\t-v, --version\t\t\t\tshow version information and exit\n\n";
-UsageConnection();
-UsageAdmins(full);
-UsageTariffs(full);
-UsageUsers(full);
-UsageServices(full);
-UsageCorporations(full);
-}
-//-----------------------------------------------------------------------------
-void UsageConnection()
-{
-std::cout << "Connection options:\n"
- << "\t-s, --server <address>\t\t\thost to connect (ip or domain name, default: \"localhost\")\n"
- << "\t-p, --port <port>\t\t\tport to connect (default: \"5555\")\n"
- << "\t-u, --username <username>\t\tadministrative login (default: \"admin\")\n"
- << "\t-w, --userpass <password>\t\tpassword for administrative login\n"
- << "\t-a, --address <connection string>\tconnection params as a single string in format: <login>:<password>@<host>:<port>\n\n";
-}
-//-----------------------------------------------------------------------------
-void UsageAdmins(bool full)
-{
-std::cout << "Admins management options:\n"
- << "\t--get-admins\t\t\t\tget a list of admins (subsequent options will define what to show)\n";
-if (full)
- std::cout << "\t\t--login\t\t\t\tshow admin's login\n"
- << "\t\t--priv\t\t\t\tshow admin's priviledges\n\n";
-std::cout << "\t--get-admin\t\t\t\tget the information about admin\n";
-if (full)
- std::cout << "\t\t--login <login>\t\t\tlogin of the admin to show\n"
- << "\t\t--priv\t\t\t\tshow admin's priviledges\n\n";
-std::cout << "\t--add-admin\t\t\t\tadd a new admin\n";
-if (full)
- std::cout << "\t\t--login <login>\t\t\tlogin of the admin to add\n"
- << "\t\t--password <password>\t\tpassword of the admin to add\n"
- << "\t\t--priv <priv number>\t\tpriviledges of the admin to add\n\n";
-std::cout << "\t--del-admin\t\t\t\tdelete an existing admin\n";
-if (full)
- std::cout << "\t\t--login <login>\t\t\tlogin of the admin to delete\n\n";
-std::cout << "\t--chg-admin\t\t\t\tchange an existing admin\n";
-if (full)
- std::cout << "\t\t--login <login>\t\t\tlogin of the admin to change\n"
- << "\t\t--priv <priv number>\t\tnew priviledges\n\n";
-}
-//-----------------------------------------------------------------------------
-void UsageTariffs(bool full)
+/*void UsageTariffs(bool full)
{
std::cout << "Tariffs management options:\n"
<< "\t--get-tariffs\t\t\t\tget a list of tariffs (subsequent options will define what to show)\n";
std::cout << "\t\t--name <name>\t\t\tname of the corporation to change\n"
<< "\t\t--add-cash <amount>[:<message>]\tadd cash to the corporation's account and optional comment message\n"
<< "\t\t--set-cash <cash>[:<message>]\tnew corporation's cash and optional comment message\n\n";
-}
-
-void Version()
-{
-std::cout << "sgconf, version: 2.0.0-alpha.\n";
-}
+}*/
} // namespace anonymous
if (!m_action)
throw ERROR("Option is not defined.");
std::string indent(level, '\t');
-std::cout << indent << "\t";
+std::cout << indent;
if (!m_shortName.empty())
std::cout << "-" << m_shortName << ", ";
std::cout << "--" << m_longName << " " << m_action->ParamDescription()
<< "\t" << m_description << m_action->DefaultDescription() << "\n";
-m_action->Suboptions().Help(level + 1);
+m_action->Suboptions().Help(level);
}
bool OPTION::Check(const char * arg) const
return false;
if (*arg == '-')
+{
return m_longName == arg + 1;
+}
return m_shortName == arg;
}
-PARSER_STATE OPTION::Parse(int argc, char ** argv)
+PARSER_STATE OPTION::Parse(int argc, char ** argv, void * data)
{
if (!m_action)
throw ERROR("Option is not defined.");
try
{
- return m_action->Parse(argc, argv);
+ return m_action->Parse(argc, argv, data);
}
catch (const ACTION::ERROR & ex)
{
if (m_longName.empty())
throw ERROR("-" + m_shortName + ": " + ex.what());
else
- throw ERROR("--" + m_longName + ", -" + m_shortName + ": " + ex.what());
+ throw m_shortName.empty() ? ERROR("--" + m_longName + ": " + ex.what())
+ : ERROR("--" + m_longName + ", -" + m_shortName + ": " + ex.what());
}
}
{
if (m_options.empty())
return;
-std::cout << m_description << ":\n";
+if (!m_description.empty())
+ std::cout << m_description << ":\n";
std::for_each(m_options.begin(),
m_options.end(),
std::bind2nd(std::mem_fun_ref(&OPTION::Help), level + 1));
}
-PARSER_STATE OPTION_BLOCK::Parse(int argc, char ** argv)
+PARSER_STATE OPTION_BLOCK::Parse(int argc, char ** argv, void * data)
{
PARSER_STATE state(false, argc, argv);
+if (state.argc == 0)
+ return state;
while (state.argc > 0 && !state.stop)
{
std::vector<OPTION>::iterator it = std::find_if(m_options.begin(), m_options.end(), std::bind2nd(std::mem_fun_ref(&OPTION::Check), *state.argv));
if (it != m_options.end())
- state = it->Parse(--state.argc, ++state.argv);
+ state = it->Parse(--state.argc, ++state.argv, data);
else
break;
++it;
{
PARSER_STATE state(false, argc, argv);
std::list<OPTION_BLOCK>::iterator it(m_blocks.begin());
-while (!state.stop && it != m_blocks.end())
+while (state.argc > 0 && !state.stop && it != m_blocks.end())
{
state = it->Parse(state.argc, state.argv);
++it;
OPTION & operator=(const OPTION & rhs);
void Help(size_t level = 0) const;
- PARSER_STATE Parse(int argc, char ** argv);
+ PARSER_STATE Parse(int argc, char ** argv, void * data);
void ParseValue(const std::string & value);
bool Check(const char * arg) const;
const std::string & Name() const { return m_longName; }
void Help(size_t level) const;
- PARSER_STATE Parse(int argc, char ** argv);
+ PARSER_STATE Parse(int argc, char ** argv, void * data = NULL);
void ParseFile(const std::string & filePath);
class ERROR : public std::runtime_error
public:
OPTION_BLOCK & Add(const std::string & description)
{ m_blocks.push_back(OPTION_BLOCK(description)); return m_blocks.back(); }
+ void Add(const OPTION_BLOCK & block) { m_blocks.push_back(block); }
void Help(size_t level) const;
PARSER_STATE Parse(int argc, char ** argv);
+++ /dev/null
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/*
- * Date: 27.10.2002
- */
-
-/*
- * Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- */
-
- /*
- $Author: faust $
- $Revision: 1.14 $
- $Date: 2009/06/08 10:02:28 $
- */
-
-#ifndef request_h
-#define request_h
-
-#include <string>
-
-#include "stg/resetable.h"
-#include "stg/const.h"
-#include "stg/os_int.h"
-
-#define TARIFF_NOW (0)
-#define TARIFF_DEL (1)
-#define TARIFF_REC (2)
-
-using namespace std;
-//-----------------------------------------------------------------------------
-struct REQUEST
-{
-
-REQUEST()
- : chgTariff(false),
- createUser(false),
- deleteUser(false),
- authBy(false)
-{
- for (int i = 0; i < DIR_NUM; i++)
- {
- sessionUpload[i].reset();
- sessionDownload[i].reset();
- monthUpload[i].reset();
- monthDownload[i].reset();
- }
-
- for (int i = 0; i < USERDATA_NUM; i++)
- userData[i].reset();
-}
-
-RESETABLE<string> server;
-RESETABLE<short> port;
-RESETABLE<string> admLogin;
-RESETABLE<string> admPasswd;
-RESETABLE<string> login;
-
-RESETABLE<string> tariff;
-int chgTariff;
-
-RESETABLE<double> cash;
-RESETABLE<double> setCash;
-string message;
-bool createUser;
-bool deleteUser;
-bool authBy;
-
-RESETABLE<string> usrMsg;
-RESETABLE<double> credit;
-RESETABLE<time_t> creditExpire;
-RESETABLE<string> usrPasswd;
-RESETABLE<bool> down;
-RESETABLE<bool> passive;
-RESETABLE<bool> disableDetailStat;
-RESETABLE<bool> alwaysOnline;
-RESETABLE<double> prepaidTraff;
-
-RESETABLE<int64_t> sessionUpload[DIR_NUM];
-RESETABLE<int64_t> sessionDownload[DIR_NUM];
-
-RESETABLE<int64_t> monthUpload[DIR_NUM];
-RESETABLE<int64_t> monthDownload[DIR_NUM];
-
-RESETABLE<string> userData[USERDATA_NUM];
-
-RESETABLE<string> note;
-RESETABLE<string> name;
-RESETABLE<string> address;
-RESETABLE<string> email;
-RESETABLE<string> phone;
-RESETABLE<string> group;
-RESETABLE<string> ips; // IP-address of user
-};
-//-----------------------------------------------------------------------------
-
-#endif
-
-
--- /dev/null
+#include "services.h"
+
+#include "api_action.h"
+#include "options.h"
+#include "config.h"
+#include "utils.h"
+
+#include "stg/servconf.h"
+#include "stg/servconf_types.h"
+#include "stg/service_conf.h"
+#include "stg/common.h"
+
+#include <iostream>
+#include <string>
+#include <map>
+
+namespace
+{
+
+std::string Indent(size_t level, bool dash = false)
+{
+if (level == 0)
+ return "";
+return dash ? std::string(level * 4 - 2, ' ') + "- " : std::string(level * 4, ' ');
+}
+
+void PrintService(const STG::GET_SERVICE::INFO & info, size_t level = 0)
+{
+std::cout << Indent(level, true) << "name: " << info.name << "\n"
+ << Indent(level) << "cost: " << info.cost << "\n"
+ << Indent(level) << "payment day: " << info.payDay << "\n"
+ << Indent(level) << "comment: " << info.comment << "\n";
+}
+
+std::vector<SGCONF::API_ACTION::PARAM> GetServiceParams()
+{
+std::vector<SGCONF::API_ACTION::PARAM> params;
+params.push_back(SGCONF::API_ACTION::PARAM("cost", "<cost>", "\tcost of the service"));
+params.push_back(SGCONF::API_ACTION::PARAM("pay-day", "<month day>", "payment day"));
+params.push_back(SGCONF::API_ACTION::PARAM("comment", "<text>", "comment"));
+return params;
+}
+
+void SimpleCallback(bool result,
+ const std::string & reason,
+ void * /*data*/)
+{
+if (!result)
+ {
+ std::cerr << "Operation failed. Reason: '" << reason << "'." << std::endl;
+ return;
+ }
+std::cout << "Success.\n";
+}
+
+void GetServicesCallback(bool result,
+ const std::string & reason,
+ const std::vector<STG::GET_SERVICE::INFO> & info,
+ void * /*data*/)
+{
+if (!result)
+ {
+ std::cerr << "Failed to get service list. Reason: '" << reason << "'." << std::endl;
+ return;
+ }
+std::cout << "Services:\n";
+for (size_t i = 0; i < info.size(); ++i)
+ PrintService(info[i], 1);
+}
+
+void GetServiceCallback(bool result,
+ const std::string & reason,
+ const STG::GET_SERVICE::INFO & info,
+ void * /*data*/)
+{
+if (!result)
+ {
+ std::cerr << "Failed to get service. Reason: '" << reason << "'." << std::endl;
+ return;
+ }
+PrintService(info);
+}
+
+bool GetServicesFunction(const SGCONF::CONFIG & config,
+ const std::string & /*arg*/,
+ const std::map<std::string, std::string> & /*options*/)
+{
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.GetServices(GetServicesCallback, NULL) == STG::st_ok;
+}
+
+bool GetServiceFunction(const SGCONF::CONFIG & config,
+ const std::string & arg,
+ const std::map<std::string, std::string> & /*options*/)
+{
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.GetService(arg, GetServiceCallback, NULL) == STG::st_ok;
+}
+
+bool DelServiceFunction(const SGCONF::CONFIG & config,
+ const std::string & arg,
+ const std::map<std::string, std::string> & /*options*/)
+{
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.DelService(arg, SimpleCallback, NULL) == STG::st_ok;
+}
+
+bool AddServiceFunction(const SGCONF::CONFIG & config,
+ const std::string & arg,
+ const std::map<std::string, std::string> & options)
+{
+SERVICE_CONF_RES conf;
+conf.name = arg;
+SGCONF::MaybeSet(options, "cost", conf.cost);
+SGCONF::MaybeSet(options, "pay-day", conf.payDay);
+SGCONF::MaybeSet(options, "comment", conf.comment);
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.AddService(arg, conf, SimpleCallback, NULL) == STG::st_ok;
+}
+
+bool ChgServiceFunction(const SGCONF::CONFIG & config,
+ const std::string & arg,
+ const std::map<std::string, std::string> & options)
+{
+SERVICE_CONF_RES conf;
+conf.name = arg;
+SGCONF::MaybeSet(options, "cost", conf.cost);
+SGCONF::MaybeSet(options, "pay-day", conf.payDay);
+SGCONF::MaybeSet(options, "comment", conf.comment);
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.ChgService(conf, SimpleCallback, NULL) == STG::st_ok;
+}
+
+} // namespace anonymous
+
+void SGCONF::AppendServicesOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks)
+{
+std::vector<API_ACTION::PARAM> params(GetServiceParams());
+blocks.Add("Service management options")
+ .Add("get-services", SGCONF::MakeAPIAction(commands, GetServicesFunction), "\tget service list")
+ .Add("get-service", SGCONF::MakeAPIAction(commands, "<name>", GetServiceFunction), "get service")
+ .Add("add-service", SGCONF::MakeAPIAction(commands, "<name>", params, AddServiceFunction), "add service")
+ .Add("del-service", SGCONF::MakeAPIAction(commands, "<name>", DelServiceFunction), "delete service")
+ .Add("chg-service", SGCONF::MakeAPIAction(commands, "<name>", params, ChgServiceFunction), "change service");
+}
--- /dev/null
+#ifndef __STG_SGCONF_SERVICES_H__
+#define __STG_SGCONF_SERVICES_H__
+
+namespace SGCONF
+{
+
+class OPTION_BLOCKS;
+class COMMANDS;
+
+void AppendServicesOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks);
+
+} // namespace SGCONF
+
+#endif
+++ /dev/null
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/*
- * Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- */
-
- /*
- $Author: nobunaga $
- $Revision: 1.2 $
- $Date: 2008/05/11 08:15:08 $
- */
-
-
-
-#ifndef STG_ERROR_CODES_H
-#define STG_ERROR_CODES_H
-
-#ifndef ENODATA
-#define ENODATA 61
-#endif
-
-#ifndef EBADMSG
-#define EBADMSG 74
-#endif
-
-#define NETWORK_ERR_CODE (1)
-#define LOGIN_OR_PASS_ERR_CODE (2)
-#define USER_NOT_FOUND_ERR_CODE (3)
-#define TARIFF_NOT_FOUND_ERR_CODE (4)
-#define PARAMETER_PARSING_ERR_CODE (5)
-#define UNKNOWN_ERR_CODE (6)
-#define ICONV_ERR_CODE (7)
-
-
-#endif
-
-
+++ /dev/null
-#!/bin/bash
-
-LD_LIBRARY_PATH=../../lib ./sgconf get -s localhost -p5555 -aadmin -w123456 $*
-
+++ /dev/null
-#!/bin/bash
-
-LD_LIBRARY_PATH=../../lib ./sgconf set -s localhost -p5555 -aadmin -w123456 $*
-
+++ /dev/null
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/*
- * Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- */
-
- /*
- $Author: faust $
- $Revision: 1.3 $
- $Date: 2009/06/22 15:57:49 $
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <string.h>
-#include <iconv.h>
-#include <string>
-#include <list>
-#include <errno.h>
-
-#include "stg/common.h"
-#include "stg/netunit.h"
-#include "request.h"
-#include "common_sg.h"
-#include "sg_error_codes.h"
-
-using namespace std;
-
-time_t stgTime;
-
-int ParseReplyGet(void * data, list<string> * ans);
-int ParseReplySet(void * data, list<string> * ans);
-
-struct option long_options_get[] = {
-{"server", 1, 0, 's'}, //Server
-{"port", 1, 0, 'p'}, //Port
-{"admin", 1, 0, 'a'}, //Admin
-{"admin_pass", 1, 0, 'w'}, //passWord
-{"user", 1, 0, 'u'}, //User
-{"addcash", 0, 0, 'c'}, //Add Cash
-//{"setcash", 0, 0, 'v'}, //Set Cash
-{"credit", 0, 0, 'r'}, //cRedit
-{"tariff", 0, 0, 't'}, //Tariff
-{"message", 0, 0, 'm'}, //message
-{"password", 0, 0, 'o'}, //password
-{"down", 0, 0, 'd'}, //down
-{"passive", 0, 0, 'i'}, //passive
-{"u0", 0, 0, 500}, //U0
-{"u1", 0, 0, 501}, //U1
-{"u2", 0, 0, 502}, //U2
-{"u3", 0, 0, 503}, //U3
-{"u4", 0, 0, 504}, //U4
-{"u5", 0, 0, 505}, //U5
-{"u6", 0, 0, 506}, //U6
-{"u7", 0, 0, 507}, //U7
-{"u8", 0, 0, 508}, //U8
-{"u9", 0, 0, 509}, //U9
-{"d0", 0, 0, 600}, //D0
-{"d1", 0, 0, 601}, //D1
-{"d2", 0, 0, 602}, //D2
-{"d3", 0, 0, 603}, //D3
-{"d4", 0, 0, 604}, //D4
-{"d5", 0, 0, 605}, //D5
-{"d6", 0, 0, 606}, //D6
-{"d7", 0, 0, 607}, //D7
-{"d8", 0, 0, 608}, //D8
-{"d9", 0, 0, 609}, //D9
-
-{"ud0", 0, 0, 700}, //UserData0
-{"ud1", 0, 0, 701}, //UserData1
-{"ud2", 0, 0, 702}, //UserData2
-{"ud3", 0, 0, 703}, //UserData3
-{"ud4", 0, 0, 704}, //UserData4
-{"ud5", 0, 0, 705}, //UserData5
-{"ud6", 0, 0, 706}, //UserData6
-{"ud7", 0, 0, 707}, //UserData7
-{"ud8", 0, 0, 708}, //UserData8
-{"ud9", 0, 0, 709}, //UserData9
-
-{"prepaid", 0, 0, 'e'}, //prepaid traff
-{"create", 0, 0, 'n'}, //create
-{"delete", 0, 0, 'l'}, //delete
-
-{"note", 0, 0, 'N'}, //Note
-{"name", 0, 0, 'A'}, //nAme
-{"address", 0, 0, 'D'}, //aDdress
-{"email", 0, 0, 'L'}, //emaiL
-{"phone", 0, 0, 'P'}, //phone
-{"group", 0, 0, 'G'}, //Group
-
-{0, 0, 0, 0}};
-
-struct option long_options_set[] = {
-{"server", 1, 0, 's'}, //Server
-{"port", 1, 0, 'p'}, //Port
-{"admin", 1, 0, 'a'}, //Admin
-{"admin_pass", 1, 0, 'w'}, //passWord
-{"user", 1, 0, 'u'}, //User
-{"addcash", 1, 0, 'c'}, //Add Cash
-{"setcash", 1, 0, 'v'}, //Set Cash
-{"credit", 1, 0, 'r'}, //cRedit
-{"tariff", 1, 0, 't'}, //Tariff
-{"message", 1, 0, 'm'}, //message
-{"password", 1, 0, 'o'}, //password
-{"down", 1, 0, 'd'}, //down
-{"passive", 1, 0, 'i'}, //passive
-{"u0", 1, 0, 500}, //U0
-{"u1", 1, 0, 501}, //U1
-{"u2", 1, 0, 502}, //U2
-{"u3", 1, 0, 503}, //U3
-{"u4", 1, 0, 504}, //U4
-{"u5", 1, 0, 505}, //U5
-{"u6", 1, 0, 506}, //U6
-{"u7", 1, 0, 507}, //U7
-{"u8", 1, 0, 508}, //U8
-{"u9", 1, 0, 509}, //U9
-{"d0", 1, 0, 600}, //D0
-{"d1", 1, 0, 601}, //D1
-{"d2", 1, 0, 602}, //D2
-{"d3", 1, 0, 603}, //D3
-{"d4", 1, 0, 604}, //D4
-{"d5", 1, 0, 605}, //D5
-{"d6", 1, 0, 606}, //D6
-{"d7", 1, 0, 607}, //D7
-{"d8", 1, 0, 608}, //D8
-{"d9", 1, 0, 609}, //D9
-
-{"ud0", 1, 0, 700}, //UserData
-{"ud1", 1, 0, 701}, //UserData1
-{"ud2", 1, 0, 702}, //UserData2
-{"ud3", 1, 0, 703}, //UserData3
-{"ud4", 1, 0, 704}, //UserData4
-{"ud5", 1, 0, 705}, //UserData5
-{"ud6", 1, 0, 706}, //UserData6
-{"ud7", 1, 0, 707}, //UserData7
-{"ud8", 1, 0, 708}, //UserData8
-{"ud9", 1, 0, 709}, //UserData9
-
-{"prepaid", 1, 0, 'e'}, //prepaid traff
-{"create", 1, 0, 'n'}, //create
-{"delete", 1, 0, 'l'}, //delete
-
-{"note", 1, 0, 'N'}, //Note
-{"name", 1, 0, 'A'}, //nAme
-{"address", 1, 0, 'D'}, //aDdress
-{"email", 1, 0, 'L'}, //emaiL
-{"phone", 1, 0, 'P'}, //phone
-{"group", 1, 0, 'G'}, //Group
-
-{0, 0, 0, 0}};
-
-//-----------------------------------------------------------------------------
-void CreateRequestGet(REQUEST * req, char * r)
-{
-string r1;
-r1 = "<GetUser login=\"" + req->login.const_data() + "\"/>\n";
-strcpy(r, r1.c_str());
-}
-//-----------------------------------------------------------------------------
-double ParseCash(const char * c, string * message)
-{
-//-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)
- {
- *message = msg + 1;
- str[msg - str] = 0;
- }
-else
- *message = "";
-
-if (strtodouble2(str, cash) != 0)
- {
- printf("Incorrect cash value %s\n", c);
- exit(PARAMETER_PARSING_ERR_CODE);
- }
-
-delete[] str;
-return cash;
-}
-//-----------------------------------------------------------------------------
-double ParseCredit(const char * c)
-{
-double credit;
-if (strtodouble2(c, credit) != 0)
- {
- printf("Incorrect credit value %s\n", c);
- exit(PARAMETER_PARSING_ERR_CODE);
- }
-
-return credit;
-}
-//-----------------------------------------------------------------------------
-double ParsePrepaidTraffic(const char * c)
-{
-double credit;
-if (strtodouble2(c, credit) != 0)
- {
- printf("Incorrect prepaid traffic value %s\n", c);
- exit(PARAMETER_PARSING_ERR_CODE);
- }
-
-return credit;
-}
-//-----------------------------------------------------------------------------
-int64_t ParseTraff(const char * c)
-{
-int64_t traff;
-if (str2x(c, traff) != 0)
- {
- printf("Incorrect credit value %s\n", c);
- exit(PARAMETER_PARSING_ERR_CODE);
- }
-
-return traff;
-}
-//-----------------------------------------------------------------------------
-bool ParseDownPassive(const char * dp)
-{
-if (!(dp[1] == 0 && (dp[0] == '1' || dp[0] == '0')))
- {
- printf("Incorrect value %s\n", dp);
- exit(PARAMETER_PARSING_ERR_CODE);
- }
-
-return dp[0] - '0';
-}
-//-----------------------------------------------------------------------------
-string ParseTariff(const char * t, int &chgType)
-{
-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)
- {
- 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);
- }
-
-ss = s;
-delete[] s;
-return ss;
-}
-//-----------------------------------------------------------------------------
-void ParseAnyString(const char * c, string * msg)
-{
-iconv_t cd;
-char * ob = new char[strlen(c) + 1];
-char * ib = new char[strlen(c) + 1];
-
-strcpy(ib, c);
-
-char * outbuf = ob;
-char * inbuf = ib;
-
-setlocale(LC_ALL, "");
-
-char charsetF[255];
-strncpy(charsetF, nl_langinfo(CODESET), 255);
-
-char * charsetT = "koi8-ru";
-
-size_t nconv = 1;
-
-size_t insize = strlen(ib);
-size_t outsize = strlen(ib);
-
-insize = strlen(c);
-
-cd = iconv_open(charsetT, charsetF);
-if (cd == (iconv_t) -1)
- {
- if (errno == EINVAL)
- {
- printf("Warning: iconv from %s to %s failed\n", charsetF, charsetT);
- *msg = c;
- return;
- }
- else
- printf("error iconv_open\n");
-
- exit(ICONV_ERR_CODE);
- }
-
-nconv = iconv (cd, &inbuf, &insize, &outbuf, &outsize);
-//printf("nconv=%d outsize=%d\n", nconv, outsize);
-if (nconv == (size_t) -1)
- {
- if (errno != EINVAL)
- {
- printf("iconv error\n");
- exit(ICONV_ERR_CODE);
- }
- }
-
-*outbuf = L'\0';
-
-iconv_close(cd);
-*msg = ob;
-
-delete[] ob;
-delete[] ib;
-}
-//-----------------------------------------------------------------------------
-void CreateRequestSet(REQUEST * req, char * r)
-{
-const int strLen = 10024;
-char str[strLen];
-memset(str, 0, strLen);
-
-r[0] = 0;
-
-if (!req->usrMsg.res_empty())
- {
- int len = req->usrMsg.const_data().length() * 2 + 1;
- char * msg = new char[len];
- memset(msg, 0, len);
- Encode12(msg, req->usrMsg.const_data().c_str(), req->usrMsg.const_data().length());
-
- sprintf(str, "<Message login=\"%s\" msgver=\"1\" msgtype=\"1\" repeat=\"0\" repeatperiod=\"0\" showtime=\"0\" text=\"%s\"/>", req->login.const_data().c_str(), msg);
- //sprintf(str, "<message login=\"%s\" priority=\"0\" text=\"%s\"/>\n", req->login, msg);
- strcat(r, str);
-
- delete[] msg;
- return;
- }
-
-if (req->deleteUser)
- {
- sprintf(str, "<DelUser login=\"%s\"/>", req->login.const_data().c_str());
- strcat(r, str);
- //printf("%s\n", r);
- return;
- }
-
-if (req->createUser)
- {
- sprintf(str, "<AddUser> <login value=\"%s\"/> </AddUser>", req->login.const_data().c_str());
- strcat(r, str);
- //printf("%s\n", r);
- return;
- }
-
-strcat(r, "<SetUser>\n");
-sprintf(str, "<login value=\"%s\"/>\n", req->login.const_data().c_str());
-strcat(r, str);
-if (!req->credit.res_empty())
- {
- sprintf(str, "<credit value=\"%f\"/>\n", req->credit.const_data());
- strcat(r, str);
- }
-
-if (!req->prepaidTraff.res_empty())
- {
- sprintf(str, "<FreeMb value=\"%f\"/>\n", req->prepaidTraff.const_data());
- strcat(r, str);
- }
-
-if (!req->cash.res_empty())
- {
- int len = req->message.length() * 2 + 1;
- char * msg = new char[len];
- memset(msg, 0, len);
-
- Encode12(msg, req->message.c_str(), req->message.length());
- sprintf(str, "<cash add=\"%f\" msg=\"%s\"/>\n", req->cash.const_data(), msg);
- strcat(r, str);
- delete[] msg;
- }
-
-if (!req->setCash.res_empty())
- {
- int len = req->message.length() * 2 + 1;
- char * msg = new char[len];
- memset(msg, 0, len);
- Encode12(msg, req->message.c_str(), req->message.length());
- sprintf(str, "<cash set=\"%f\" msg=\"%s\"/>\n", req->setCash.const_data(), msg);
- strcat(r, str);
- delete[] msg;
- }
-
-if (!req->usrPasswd.res_empty())
- {
- sprintf(str, "<password value=\"%s\" />\n", req->usrPasswd.const_data().c_str());
- strcat(r, str);
- }
-
-if (!req->down.res_empty())
- {
- sprintf(str, "<down value=\"%d\" />\n", req->down.const_data());
- strcat(r, str);
- }
-
-if (!req->passive.res_empty())
- {
- sprintf(str, "<passive value=\"%d\" />\n", req->passive.const_data());
- strcat(r, str);
- }
-
-int uPresent = false;
-int dPresent = false;
-for (int i = 0; i < DIR_NUM; i++)
- {
- if (!req->u[i].res_empty())
- {
- if (!uPresent && !dPresent)
- {
- sprintf(str, "<traff ");
- strcat(r, str);
- uPresent = true;
- }
-
- stringstream ss;
- ss << req->u[i].const_data();
- //sprintf(str, "MU%d=\"%lld\" ", i, req->u[i].const_data());
- sprintf(str, "MU%d=\"%s\" ", i, ss.str().c_str());
- strcat(r, str);
- }
- if (!req->d[i].res_empty())
- {
- if (!uPresent && !dPresent)
- {
- sprintf(str, "<traff ");
- strcat(r, str);
- dPresent = true;
- }
-
- stringstream ss;
- ss << req->d[i].const_data();
- sprintf(str, "MD%d=\"%s\" ", i, ss.str().c_str());
- strcat(r, str);
- }
- }
-if (uPresent || dPresent)
- {
- strcat(r, "/>");
- }
-
-//printf("%s\n", r);
-
-if (!req->tariff.res_empty())
- {
- switch (req->chgTariff)
- {
- case TARIFF_NOW:
- sprintf(str, "<tariff now=\"%s\"/>\n", req->tariff.const_data().c_str());
- strcat(r, str);
- break;
- case TARIFF_REC:
- sprintf(str, "<tariff recalc=\"%s\"/>\n", req->tariff.const_data().c_str());
- strcat(r, str);
- break;
- case TARIFF_DEL:
- sprintf(str, "<tariff delayed=\"%s\"/>\n", req->tariff.const_data().c_str());
- strcat(r, str);
- break;
- }
-
- }
-
-if (!req->note.res_empty())
- {
- int len = req->note.const_data().length() * 2 + 1;
- char * note = new char[len];
- memset(note, 0, len);
-
- Encode12(note, req->note.const_data().c_str(), req->note.const_data().length());
-
- sprintf(str, "<note value=\"%s\"/>", note);
- strcat(r, str);
- delete[] note;
- }
-
-if (!req->name.res_empty())
- {
- int len = req->note.const_data().length() * 2 + 1;
- char * name = new char[len];
- memset(name, 0, len);
-
- Encode12(name, req->name.const_data().c_str(), req->name.const_data().length());
-
- sprintf(str, "<name value=\"%s\"/>", name);
- strcat(r, str);
- delete[] name;
- }
-
-if (!req->address.res_empty())
- {
- int len = req->note.const_data().length() * 2 + 1;
- char * address = new char[len];
- memset(address, 0, len);
-
- Encode12(address, req->address.const_data().c_str(), req->address.const_data().length());
-
- sprintf(str, "<address value=\"%s\"/>", address);
- strcat(r, str);
- delete[] address;
- }
-
-if (!req->email.res_empty())
- {
- int len = req->note.const_data().length() * 2 + 1;
- char * email = new char[len];
- memset(email, 0, len);
-
- Encode12(email, req->email.const_data().c_str(), req->email.const_data().length());
-
- sprintf(str, "<email value=\"%s\"/>", email);
- strcat(r, str);
- delete[] email;
- }
-
-if (!req->phone.res_empty())
- {
- int len = req->note.const_data().length() * 2 + 1;
- char * phone = new char[len];
- memset(phone, 0, len);
-
- Encode12(phone, req->phone.const_data().c_str(), req->phone.const_data().length());
-
- sprintf(str, "<phone value=\"%s\"/>", phone);
- strcat(r, str);
- delete[] phone;
- }
-
-if (!req->group.res_empty())
- {
- int len = req->note.const_data().length() * 2 + 1;
- char * group = new char[len];
- memset(group, 0, len);
-
- Encode12(group, req->group.const_data().c_str(), req->group.const_data().length());
-
- sprintf(str, "<group value=\"%s\"/>", group);
- strcat(r, str);
- delete[] group;
- }
-
-for (int i = 0; i < USERDATA_NUM; i++)
- {
- if (!req->ud[i].res_empty())
- {
- int len = req->ud[i].const_data().length() * 2 + 1;
- char * ud = new char[len];
- memset(ud, 0, len);
-
- Encode12(ud, req->ud[i].const_data().c_str(), req->ud[i].const_data().length());
-
- sprintf(str, "<userdata%d value=\"%s\"/>", i, ud);
- strcat(r, str);
- delete[] ud;
- }
- }
-
-strcat(r, "</SetUser>\n");
-}
-//-----------------------------------------------------------------------------
-int CheckParameters(REQUEST * req)
-{
-int u = false;
-int d = false;
-int ud = false;
-int a = !req->admLogin.res_empty()
- && !req->admPasswd.res_empty()
- && !req->server.res_empty()
- && !req->port.res_empty()
- && !req->login.res_empty();
-
-int b = !req->cash.res_empty()
- || !req->setCash.res_empty()
- || !req->credit.res_empty()
- || !req->prepaidTraff.res_empty()
- || !req->tariff.res_empty()
- || !req->usrMsg.res_empty()
- || !req->usrPasswd.res_empty()
-
- || !req->note.res_empty()
- || !req->name.res_empty()
- || !req->address.res_empty()
- || !req->email.res_empty()
- || !req->phone.res_empty()
- || !req->group.res_empty();
-
-for (int i = 0; i < DIR_NUM; i++)
- {
- if (req->u[i].res_empty())
- {
- u = true;
- break;
- }
- }
-
-for (int i = 0; i < DIR_NUM; i++)
- {
- if (req->d[i].res_empty())
- {
- d = true;
- break;
- }
- }
-
-for (int i = 0; i < DIR_NUM; i++)
- {
- if (req->ud[i].res_empty())
- {
- ud = true;
- break;
- }
- }
-
-
-//printf("a=%d, b=%d, u=%d, d=%d ud=%d\n", a, b, u, d, ud);
-return a && (b || u || d || ud);
-}
-//-----------------------------------------------------------------------------
-int CheckParametersGet(REQUEST * req)
-{
-return CheckParameters(req);
-}
-//-----------------------------------------------------------------------------
-int CheckParametersSet(REQUEST * req)
-{
-return CheckParameters(req);
-}
-//-----------------------------------------------------------------------------
-int mainGet(int argc, char **argv)
-{
-int c;
-REQUEST req;
-RESETABLE<string> t1;
-
-char * short_options_get = "s:p:a:w:u:crtmodieNADLPG";
-int option_index = -1;
-
-while (1)
- {
- option_index = -1;
- c = getopt_long(argc, argv, short_options_get, long_options_get, &option_index);
- if (c == -1)
- break;
-
- switch (c)
- {
- case 's': //server
- req.server = optarg;
- break;
-
- case 'p': //port
- req.port = ParseServerPort(optarg);
- //req.portReq = 1;
- break;
-
- case 'a': //admin
- req.admLogin = ParseAdminLogin(optarg);
- break;
-
- case 'w': //admin password
- req.admPasswd = ParsePassword(optarg);
- break;
-
- case 'o': //change user password
- req.usrPasswd = ParsePassword(optarg);
- break;
-
- case 'u': //user
- req.login = ParseUser(optarg);
- break;
-
- case 'c': //get cash
- req.cash = 1;
- break;
-
- case 'r': //credit
- req.credit = 1;
- break;
-
- case 'd': //down
- req.down = 1;
- break;
-
- case 'i': //passive
- req.passive = 1;
- break;
-
- case 't': //tariff
- req.tariff = " ";
- break;
-
- case 'e': //Prepaid Traffic
- req.prepaidTraff = 1;
- break;
-
- case 'N': //Note
- req.note = " ";
- break;
-
- case 'A': //nAme
- req.name = " ";
- break;
-
- case 'D': //aDdress
- req.address =" ";
- break;
-
- case 'L': //emaiL
- req.email = " ";
- break;
-
- case 'P': //phone
- req.phone = " ";
- break;
-
- case 'G': //Group
- req.group = " ";
- break;
-
- case 500: //U
- case 501:
- case 502:
- case 503:
- case 504:
- case 505:
- case 506:
- case 507:
- case 508:
- case 509:
- //printf("U%d\n", c - 500);
- req.u[c - 500] = 1;
- break;
-
- case 600: //D
- case 601:
- case 602:
- case 603:
- case 604:
- case 605:
- case 606:
- case 607:
- case 608:
- case 609:
- //printf("D%d\n", c - 600);
- req.d[c - 600] = 1;
- break;
-
- case 700: //UserData
- case 701:
- case 702:
- case 703:
- case 704:
- case 705:
- case 706:
- case 707:
- case 708:
- case 709:
- //printf("UD%d\n", c - 700);
- req.ud[c - 700] = " ";
- break;
-
- case '?':
- //printf ("Unknown option \n");
- break;
-
- default:
- printf ("?? getopt returned character code 0%o ??\n", c);
- }
- }
-
-if (optind < argc)
- {
- printf ("non-option ARGV-elements: ");
- while (optind < argc)
- printf ("%s ", argv[optind++]);
- UsageInfo();
- exit(PARAMETER_PARSING_ERR_CODE);
- }
-
-if (CheckParametersGet(&req) == 0)
- {
- //printf("Parameter needed\n");
- UsageInfo();
- exit(PARAMETER_PARSING_ERR_CODE);
- }
-
-
-const int rLen = 20000;
-char rstr[rLen];
-memset(rstr, 0, rLen);
-
-CreateRequestGet(&req, rstr);
-Process(req.server, req.port, req.admLogin, req.admPasswd, rstr, ParseReplyGet);
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int mainSet(int argc, char **argv)
-{
-string str;
-
-int c;
-REQUEST req;
-
-RESETABLE<string> t1;
-
-char * short_options_set = "s:p:a:w:u:c:r:t:m:o:d:i:e:v:nlN:A:D:L:P:G:";
-
-while (1)
- {
- int option_index = -1;
-
- c = getopt_long(argc, argv, short_options_set, long_options_set, &option_index);
- if (c == -1)
- break;
-
- switch (c)
- {
- case 's': //server
- req.server = optarg;
- break;
-
- case 'p': //port
- req.port = ParseServerPort(optarg);
- //req.portReq = 1;
- break;
-
- case 'a': //admin
- req.admLogin = ParseAdminLogin(optarg);
- break;
-
- case 'w': //admin password
- req.admPasswd = ParsePassword(optarg);
- break;
-
- case 'o': //change user password
- req.usrPasswd = ParsePassword(optarg);
- break;
-
- case 'u': //user
- req.login = ParseUser(optarg);
- break;
-
- case 'c': //add cash
- req.cash = ParseCash(optarg, &req.message);
- break;
-
- case 'v': //set cash
- req.setCash = ParseCash(optarg, &req.message);
- break;
-
- case 'r': //credit
- req.credit = ParseCredit(optarg);
- break;
-
- case 'd': //down
- req.down = ParseDownPassive(optarg);
- break;
-
- case 'i': //passive
- req.passive = ParseDownPassive(optarg);
- break;
-
- case 't': //tariff
- req.tariff = ParseTariff(optarg, req.chgTariff);
- break;
-
- case 'm': //message
- //ParseMessage(optarg, &req.usrMsg);
- req.usrMsg = optarg;
- break;
-
- case 'e': //Prepaid Traffic
- req.prepaidTraff = ParsePrepaidTraffic(optarg);
- break;
-
- case 'n': //Create User
- req.createUser = true;
- break;
-
- case 'l': //Delete User
- req.deleteUser = true;
- break;
-
- case 'N': //Note
- ParseAnyString(optarg, &str);
- req.note = str;
- break;
-
- case 'A': //nAme
- ParseAnyString(optarg, &str);
- req.name = str;
- break;
-
- case 'D': //aDdress
- ParseAnyString(optarg, &str);
- req.address = str;
- break;
-
- case 'L': //emaiL
- ParseAnyString(optarg, &str);
- req.email = str;
- break;
-
- case 'P': //phone
- ParseAnyString(optarg, &str);
- req.phone = str;
- break;
-
- case 'G': //Group
- ParseAnyString(optarg, &str);
- req.group = str;
- break;
-
- case 500: //U
- case 501:
- case 502:
- case 503:
- case 504:
- case 505:
- case 506:
- case 507:
- case 508:
- case 509:
- //printf("U%d\n", c - 500);
- req.u[c - 500] = ParseTraff(optarg);
- break;
-
- case 600: //D
- case 601:
- case 602:
- case 603:
- case 604:
- case 605:
- case 606:
- case 607:
- case 608:
- case 609:
- //printf("D%d\n", c - 600);
- req.d[c - 600] = ParseTraff(optarg);
- break;
-
- case 700: //UserData
- case 701:
- case 702:
- case 703:
- case 704:
- case 705:
- case 706:
- case 707:
- case 708:
- case 709:
- ParseAnyString(optarg, &str);
- //printf("UD%d\n", c - 700);
- req.ud[c - 700] = str;
- break;
-
- case '?':
- //printf ("Unknown option \n");
- break;
-
- default:
- printf ("?? getopt returned character code 0%o ??\n", c);
- }
- }
-
-if (optind < argc)
- {
- printf ("non-option ARGV-elements: ");
- while (optind < argc)
- printf ("%s ", argv[optind++]);
- UsageConf();
- exit(PARAMETER_PARSING_ERR_CODE);
- }
-
-if (CheckParametersSet(&req) == 0)
- {
- //printf("Parameter needed\n");
- UsageConf();
- exit(PARAMETER_PARSING_ERR_CODE);
- }
-
-const int rLen = 20000;
-char rstr[rLen];
-memset(rstr, 0, rLen);
-
-CreateRequestGet(&req, rstr);
-Process(req.server, req.port, req.admLogin, req.admPasswd, rstr, ParseReplySet);
-//Process(&req);
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int main(int argc, char **argv)
-{
-if (argc <= 2)
- {
- UsageConf();
- exit(PARAMETER_PARSING_ERR_CODE);
- }
-
-if (strcmp(argv[1], "get"))
- {
- return mainGet(argc - 1, argv + 1);
- }
-else if (strcmp(argv[1], "set"))
- {
- return mainGet(argc - 1, argv + 1);
- }
-else
- {
- UsageConf();
- exit(PARAMETER_PARSING_ERR_CODE);
- }
-return UNKNOWN_ERR_CODE;
-}
-//-----------------------------------------------------------------------------
-
--- /dev/null
+#include "tariffs.h"
+
+#include "api_action.h"
+#include "options.h"
+#include "config.h"
+#include "utils.h"
+
+#include "stg/servconf.h"
+#include "stg/servconf_types.h"
+#include "stg/tariff_conf.h"
+#include "stg/common.h"
+#include "stg/os_int.h"
+
+#include <iostream>
+#include <algorithm>
+#include <sstream>
+#include <string>
+#include <map>
+#include <cassert>
+
+namespace
+{
+
+std::string Indent(size_t level, bool dash = false)
+{
+if (level == 0)
+ return "";
+return dash ? std::string(level * 4 - 2, ' ') + "- " : std::string(level * 4, ' ');
+}
+
+std::string PeriodToString(TARIFF::PERIOD period)
+{
+switch (period)
+ {
+ case TARIFF::DAY:
+ return "daily";
+ case TARIFF::MONTH:
+ return "monthly";
+ }
+return "unknown";
+}
+
+std::string TraffTypeToString(int traffType)
+{
+switch (traffType)
+ {
+ case TRAFF_UP:
+ return "upload";
+ case TRAFF_DOWN:
+ return "download";
+ case TRAFF_UP_DOWN:
+ return "upload + download";
+ case TRAFF_MAX:
+ return "max(upload, download)";
+ }
+return "unknown";
+}
+
+void ConvPeriod(const std::string & value, RESETABLE<TARIFF::PERIOD> & res)
+{
+std::string lowered = ToLower(value);
+if (lowered == "daily")
+ res = TARIFF::DAY;
+else if (lowered == "monthly")
+ res = TARIFF::MONTH;
+else
+ throw SGCONF::ACTION::ERROR("Period should be 'daily' or 'monthly'. Got: '" + value + "'");
+}
+
+void ConvTraffType(const std::string & value, RESETABLE<int> & res)
+{
+std::string lowered = ToLower(value);
+lowered.erase(std::remove(lowered.begin(), lowered.end(), ' '), lowered.end());
+if (lowered == "upload")
+ res = TRAFF_UP;
+else if (lowered == "download")
+ res = TRAFF_DOWN;
+else if (lowered == "upload+download")
+ res = TRAFF_UP_DOWN;
+else if (lowered.substr(0, 3) == "max")
+ res = TRAFF_MAX;
+else
+ throw SGCONF::ACTION::ERROR("Traff type should be 'upload', 'download', 'upload + download' or 'max'. Got: '" + value + "'");
+}
+
+DIRPRICE_DATA_RES ConvTimeSpan(const std::string & value)
+{
+size_t dashPos = value.find_first_of('-');
+if (dashPos == std::string::npos)
+ throw SGCONF::ACTION::ERROR("Time span should be in format 'hh:mm-hh:mm'. Got: '" + value + "'");
+size_t fromColon = value.find_first_of(':');
+if (fromColon == std::string::npos || fromColon > dashPos)
+ throw SGCONF::ACTION::ERROR("Time span should be in format 'hh:mm-hh:mm'. Got: '" + value + "'");
+size_t toColon = value.find_first_of(':', dashPos);
+if (toColon == std::string::npos)
+ throw SGCONF::ACTION::ERROR("Time span should be in format 'hh:mm-hh:mm'. Got: '" + value + "'");
+DIRPRICE_DATA_RES res;
+res.hDay = FromString<int>(value.substr(0, fromColon));
+if (res.hDay.data() < 0 || res.hDay.data() > 23)
+ throw SGCONF::ACTION::ERROR("Invalid 'from' hours. Got: '" + value.substr(0, fromColon) + "'");
+res.mDay = FromString<int>(value.substr(fromColon + 1, dashPos - fromColon - 1));
+if (res.mDay.data() < 0 || res.mDay.data() > 59)
+ throw SGCONF::ACTION::ERROR("Invalid 'from' minutes. Got: '" + value.substr(fromColon + 1, dashPos - fromColon - 1) + "'");
+res.hNight = FromString<int>(value.substr(dashPos + 1, toColon - dashPos - 1));
+if (res.hNight.data() < 0 || res.hNight.data() > 23)
+ throw SGCONF::ACTION::ERROR("Invalid 'to' hours. Got: '" + value.substr(dashPos + 1, toColon - dashPos - 1) + "'");
+res.mNight = FromString<int>(value.substr(toColon + 1, value.length() - toColon));
+if (res.mNight.data() < 0 || res.mNight.data() > 59)
+ throw SGCONF::ACTION::ERROR("Invalid 'to' minutes. Got: '" + value.substr(toColon + 1, value.length() - toColon) + "'");
+return res;
+}
+
+void Splice(std::vector<DIRPRICE_DATA_RES> & lhs, const std::vector<DIRPRICE_DATA_RES> & rhs)
+{
+for (size_t i = 0; i < lhs.size() && i < rhs.size(); ++i)
+ lhs[i].Splice(rhs[i]);
+}
+
+void ConvTimes(std::string value, std::vector<DIRPRICE_DATA_RES> & res)
+{
+value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
+Splice(res, Split<std::vector<DIRPRICE_DATA_RES> >(value, ',', ConvTimeSpan));
+}
+
+struct ConvPrice : public std::unary_function<std::string, DIRPRICE_DATA_RES>
+{
+ typedef RESETABLE<double> (DIRPRICE_DATA_RES::* MemPtr);
+ ConvPrice(MemPtr before, MemPtr after)
+ : m_before(before), m_after(after)
+ {}
+
+ DIRPRICE_DATA_RES operator()(const std::string & value)
+ {
+ DIRPRICE_DATA_RES res;
+ size_t slashPos = value.find_first_of('/');
+ if (slashPos == std::string::npos)
+ {
+ double price = 0;
+ if (str2x(value, price) < 0)
+ throw SGCONF::ACTION::ERROR("Price should be a floating point number. Got: '" + value + "'");
+ (res.*m_before) = (res.*m_after) = price;
+ res.noDiscount = true;
+ }
+ else
+ {
+ double price = 0;
+ if (str2x(value.substr(0, slashPos), price) < 0)
+ throw SGCONF::ACTION::ERROR("Price should be a floating point number. Got: '" + value.substr(0, slashPos) + "'");
+ (res.*m_before) = price;
+ if (str2x(value.substr(slashPos + 1, value.length() - slashPos), price) < 0)
+ throw SGCONF::ACTION::ERROR("Price should be a floating point number. Got: '" + value.substr(slashPos + 1, value.length() - slashPos) + "'");
+ (res.*m_after) = price;
+ res.noDiscount = false;
+ }
+ return res;
+ }
+
+ MemPtr m_before;
+ MemPtr m_after;
+};
+
+void ConvDayPrices(std::string value, std::vector<DIRPRICE_DATA_RES> & res)
+{
+value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
+Splice(res, Split<std::vector<DIRPRICE_DATA_RES> >(value, ',', ConvPrice(&DIRPRICE_DATA_RES::priceDayA, &DIRPRICE_DATA_RES::priceDayB)));
+}
+
+void ConvNightPrices(std::string value, std::vector<DIRPRICE_DATA_RES> & res)
+{
+value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
+Splice(res, Split<std::vector<DIRPRICE_DATA_RES> >(value, ',', ConvPrice(&DIRPRICE_DATA_RES::priceNightA, &DIRPRICE_DATA_RES::priceNightB)));
+}
+
+DIRPRICE_DATA_RES ConvThreshold(std::string value)
+{
+DIRPRICE_DATA_RES res;
+double threshold = 0;
+if (str2x(value, threshold) < 0)
+ throw SGCONF::ACTION::ERROR("Threshold should be a floating point value. Got: '" + value + "'");
+res.threshold = threshold;
+return res;
+}
+
+void ConvThresholds(std::string value, std::vector<DIRPRICE_DATA_RES> & res)
+{
+value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
+Splice(res, Split<std::vector<DIRPRICE_DATA_RES> >(value, ',', ConvThreshold));
+}
+
+std::string TimeToString(int h, int m)
+{
+std::ostringstream stream;
+stream << (h < 10 ? "0" : "") << h << ":"
+ << (m < 10 ? "0" : "") << m;
+return stream.str();
+}
+
+void PrintDirPriceData(size_t dir, const DIRPRICE_DATA & data, size_t level)
+{
+std::string night = TimeToString(data.hNight, data.mNight);
+std::string day = TimeToString(data.hDay, data.mDay);
+std::cout << Indent(level, true) << "dir: " << dir << "\n"
+ << Indent(level) << "'" << night << "' - '" << day << "': " << data.priceDayA << "/" << data.priceDayB << "\n"
+ << Indent(level) << "'" << day << "' - '" << night << "': " << data.priceNightA << "/" << data.priceNightB << "\n"
+ << Indent(level) << "threshold: " << data.threshold << "\n"
+ << Indent(level) << "single price: " << (data.singlePrice ? "yes" : "no") << "\n"
+ << Indent(level) << "discount: " << (data.noDiscount ? "no" : "yes") << "\n"; // Attention!
+}
+
+void PrintTariffConf(const TARIFF_CONF & conf, size_t level)
+{
+std::cout << Indent(level, true) << "name: " << conf.name << "\n"
+ << Indent(level) << "fee: " << conf.fee << "\n"
+ << Indent(level) << "free mb: " << conf.free << "\n"
+ << Indent(level) << "passive cost: " << conf.passiveCost << "\n"
+ << Indent(level) << "traff type: " << TraffTypeToString(conf.traffType) << "\n"
+ << Indent(level) << "period: " << PeriodToString(conf.period) << "\n";
+}
+
+void PrintTariff(const STG::GET_TARIFF::INFO & info, size_t level = 0)
+{
+PrintTariffConf(info.tariffConf, level);
+std::cout << Indent(level) << "dir prices:\n";
+for (size_t i = 0; i < info.dirPrice.size(); ++i)
+ PrintDirPriceData(i, info.dirPrice[i], level + 1);
+}
+
+std::vector<SGCONF::API_ACTION::PARAM> GetTariffParams()
+{
+std::vector<SGCONF::API_ACTION::PARAM> params;
+params.push_back(SGCONF::API_ACTION::PARAM("fee", "<fee>", "\t\ttariff fee"));
+params.push_back(SGCONF::API_ACTION::PARAM("free", "<free mb>", "\tprepaid traffic"));
+params.push_back(SGCONF::API_ACTION::PARAM("passive-cost", "<cost>", "\tpassive cost"));
+params.push_back(SGCONF::API_ACTION::PARAM("traff-type", "<type>", "\ttraffic type (up, down, up+down, max)"));
+params.push_back(SGCONF::API_ACTION::PARAM("period", "<period>", "\ttarification period (daily, monthly)"));
+params.push_back(SGCONF::API_ACTION::PARAM("times", "<hh:mm-hh:mm, ...>", "coma-separated day time-spans for each direction"));
+params.push_back(SGCONF::API_ACTION::PARAM("day-prices", "<price/price, ...>", "coma-separated day prices for each direction"));
+params.push_back(SGCONF::API_ACTION::PARAM("night-prices", "<price/price, ...>", "coma-separated night prices for each direction"));
+params.push_back(SGCONF::API_ACTION::PARAM("thresholds", "<threshold, ...>", "coma-separated thresholds for each direction"));
+return params;
+}
+
+void SimpleCallback(bool result,
+ const std::string & reason,
+ void * /*data*/)
+{
+if (!result)
+ {
+ std::cerr << "Operation failed. Reason: '" << reason << "'." << std::endl;
+ return;
+ }
+std::cout << "Success.\n";
+}
+
+void GetTariffsCallback(bool result,
+ const std::string & reason,
+ const std::vector<STG::GET_TARIFF::INFO> & info,
+ void * /*data*/)
+{
+if (!result)
+ {
+ std::cerr << "Failed to get tariff list. Reason: '" << reason << "'." << std::endl;
+ return;
+ }
+std::cout << "Tariffs:\n";
+for (size_t i = 0; i < info.size(); ++i)
+ PrintTariff(info[i], 1);
+}
+
+void GetTariffCallback(bool result,
+ const std::string & reason,
+ const std::vector<STG::GET_TARIFF::INFO> & info,
+ void * data)
+{
+assert(data != NULL && "Expecting pointer to std::string with the tariff's name.");
+const std::string & name = *static_cast<const std::string *>(data);
+if (!result)
+ {
+ std::cerr << "Failed to get tariff. Reason: '" << reason << "'." << std::endl;
+ return;
+ }
+for (size_t i = 0; i < info.size(); ++i)
+ if (info[i].tariffConf.name == name)
+ PrintTariff(info[i]);
+}
+
+bool GetTariffsFunction(const SGCONF::CONFIG & config,
+ const std::string & /*arg*/,
+ const std::map<std::string, std::string> & /*options*/)
+{
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.GetTariffs(GetTariffsCallback, NULL) == STG::st_ok;
+}
+
+bool GetTariffFunction(const SGCONF::CONFIG & config,
+ const std::string & arg,
+ const std::map<std::string, std::string> & /*options*/)
+{
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+// STG currently doesn't support <GetTariff name="..."/>.
+// So get a list of tariffs and filter it. 'data' param holds a pointer to 'name'.
+std::string name(arg);
+return proto.GetTariffs(GetTariffCallback, &name) == STG::st_ok;
+}
+
+bool DelTariffFunction(const SGCONF::CONFIG & config,
+ const std::string & arg,
+ const std::map<std::string, std::string> & /*options*/)
+{
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.DelTariff(arg, SimpleCallback, NULL) == STG::st_ok;
+}
+
+bool AddTariffFunction(const SGCONF::CONFIG & config,
+ const std::string & arg,
+ const std::map<std::string, std::string> & options)
+{
+TARIFF_DATA_RES conf;
+conf.tariffConf.name = arg;
+SGCONF::MaybeSet(options, "fee", conf.tariffConf.fee);
+SGCONF::MaybeSet(options, "free", conf.tariffConf.free);
+SGCONF::MaybeSet(options, "passive-cost", conf.tariffConf.passiveCost);
+SGCONF::MaybeSet(options, "traff-type", conf.tariffConf.traffType, ConvTraffType);
+SGCONF::MaybeSet(options, "period", conf.tariffConf.period, ConvPeriod);
+SGCONF::MaybeSet(options, "times", conf.dirPrice, ConvTimes);
+SGCONF::MaybeSet(options, "day-prices", conf.dirPrice, ConvDayPrices);
+SGCONF::MaybeSet(options, "night-prices", conf.dirPrice, ConvNightPrices);
+SGCONF::MaybeSet(options, "thresholds", conf.dirPrice, ConvThresholds);
+for (size_t i = 0; i < conf.dirPrice.size(); ++i)
+ {
+ if (!conf.dirPrice[i].priceDayA.empty() &&
+ !conf.dirPrice[i].priceNightA.empty() &&
+ !conf.dirPrice[i].priceDayB.empty() &&
+ !conf.dirPrice[i].priceNightB.empty())
+ conf.dirPrice[i].singlePrice = conf.dirPrice[i].priceDayA.data() == conf.dirPrice[i].priceNightA.data() &&
+ conf.dirPrice[i].priceDayB.data() == conf.dirPrice[i].priceNightB.data();
+ }
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.AddTariff(arg, conf, SimpleCallback, NULL) == STG::st_ok;
+}
+
+bool ChgTariffFunction(const SGCONF::CONFIG & config,
+ const std::string & arg,
+ const std::map<std::string, std::string> & options)
+{
+TARIFF_DATA_RES conf;
+conf.tariffConf.name = arg;
+SGCONF::MaybeSet(options, "fee", conf.tariffConf.fee);
+SGCONF::MaybeSet(options, "free", conf.tariffConf.free);
+SGCONF::MaybeSet(options, "passive-cost", conf.tariffConf.passiveCost);
+SGCONF::MaybeSet(options, "traff-type", conf.tariffConf.traffType, ConvTraffType);
+SGCONF::MaybeSet(options, "period", conf.tariffConf.period, ConvPeriod);
+SGCONF::MaybeSet(options, "times", conf.dirPrice, ConvTimes);
+SGCONF::MaybeSet(options, "day-prices", conf.dirPrice, ConvDayPrices);
+SGCONF::MaybeSet(options, "night-prices", conf.dirPrice, ConvNightPrices);
+SGCONF::MaybeSet(options, "thresholds", conf.dirPrice, ConvThresholds);
+for (size_t i = 0; i < conf.dirPrice.size(); ++i)
+ {
+ if (!conf.dirPrice[i].priceDayA.empty() &&
+ !conf.dirPrice[i].priceNightA.empty() &&
+ !conf.dirPrice[i].priceDayB.empty() &&
+ !conf.dirPrice[i].priceNightB.empty())
+ conf.dirPrice[i].singlePrice = conf.dirPrice[i].priceDayA.data() == conf.dirPrice[i].priceNightA.data() &&
+ conf.dirPrice[i].priceDayB.data() == conf.dirPrice[i].priceNightB.data();
+ }
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.ChgTariff(conf, SimpleCallback, NULL) == STG::st_ok;
+}
+
+} // namespace anonymous
+
+void SGCONF::AppendTariffsOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks)
+{
+std::vector<API_ACTION::PARAM> params(GetTariffParams());
+blocks.Add("Tariff management options")
+ .Add("get-tariffs", SGCONF::MakeAPIAction(commands, GetTariffsFunction), "\tget tariff list")
+ .Add("get-tariff", SGCONF::MakeAPIAction(commands, "<name>", GetTariffFunction), "get tariff")
+ .Add("add-tariff", SGCONF::MakeAPIAction(commands, "<name>", params, AddTariffFunction), "add tariff")
+ .Add("del-tariff", SGCONF::MakeAPIAction(commands, "<name>", DelTariffFunction), "delete tariff")
+ .Add("chg-tariff", SGCONF::MakeAPIAction(commands, "<name>", params, ChgTariffFunction), "change tariff");
+}
--- /dev/null
+#ifndef __STG_SGCONF_TARIFFS_H__
+#define __STG_SGCONF_TARIFFS_H__
+
+namespace SGCONF
+{
+
+class OPTION_BLOCKS;
+class COMMANDS;
+
+void AppendTariffsOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks);
+
+} // namespace SGCONF
+
+#endif
--- /dev/null
+#include "users.h"
+
+#include "api_action.h"
+#include "options.h"
+#include "config.h"
+#include "utils.h"
+
+#include "stg/servconf.h"
+#include "stg/servconf_types.h"
+#include "stg/user_conf.h"
+#include "stg/user_stat.h"
+#include "stg/user_ips.h"
+#include "stg/common.h"
+
+#include <iostream>
+#include <algorithm>
+#include <string>
+#include <map>
+
+namespace
+{
+
+std::string Indent(size_t level, bool dash = false)
+{
+if (level == 0)
+ return "";
+return dash ? std::string(level * 4 - 2, ' ') + "- " : std::string(level * 4, ' ');
+}
+
+void PrintUser(const STG::GET_USER::INFO & info, size_t level = 0)
+{
+std::cout << Indent(level, true) << "login: " << info.login << "\n"
+ << Indent(level) << "password: " << info.password << "\n"
+ << Indent(level) << "cash: " << info.cash << "\n"
+ << Indent(level) << "credit: " << info.credit << "\n"
+ << Indent(level) << "credit expire: " << TimeToString(info.creditExpire) << "\n"
+ << Indent(level) << "last cash add: " << info.lastCashAdd << "\n"
+ << Indent(level) << "last cash add time: " << TimeToString(info.lastCashAddTime) << "\n"
+ << Indent(level) << "prepaid traffic: " << info.prepaidTraff << "\n"
+ << Indent(level) << "disabled: " << (info.disabled ? "t" : "f") << "\n"
+ << Indent(level) << "passive: " << (info.passive ? "t" : "f") << "\n"
+ << Indent(level) << "disabled detail stat: " << (info.disableDetailStat ? "t" : "f") << "\n"
+ << Indent(level) << "connected: " << (info.connected ? "t" : "f") << "\n"
+ << Indent(level) << "always on-line: " << (info.alwaysOnline ? "t" : "f") << "\n"
+ << Indent(level) << "IP: " << inet_ntostring(info.ip) << "\n"
+ << Indent(level) << "IPs: " << info.ips << "\n"
+ << Indent(level) << "tariff: " << info.tariff << "\n"
+ << Indent(level) << "group: " << info.group << "\n"
+ << Indent(level) << "note: " << info.note << "\n"
+ << Indent(level) << "email: " << info.email << "\n"
+ << Indent(level) << "name: " << info.name << "\n"
+ << Indent(level) << "address: " << info.address << "\n"
+ << Indent(level) << "phone: " << info.phone << "\n"
+ << Indent(level) << "corporation: " << info.corp << "\n"
+ << Indent(level) << "last ping time: " << TimeToString(info.pingTime) << "\n"
+ << Indent(level) << "last activity time: " << TimeToString(info.lastActivityTime) << "\n"
+ << Indent(level) << "traffic:\n";
+for (size_t i = 0; i < DIR_NUM; ++i)
+ {
+ std::cout << Indent(level + 1, true) << "dir: " << i << "\n"
+ << Indent(level + 1) << "session upload: " << info.stat.su[i] << "\n"
+ << Indent(level + 1) << "session download: " << info.stat.sd[i] << "\n"
+ << Indent(level + 1) << "month upload: " << info.stat.mu[i] << "\n"
+ << Indent(level + 1) << "month download: " << info.stat.md[i] << "\n";
+ }
+std::cout << Indent(level) << "user data:\n";
+for (size_t i = 0; i < USERDATA_NUM; ++i)
+ std::cout << Indent(level + 1, true) << "user data " << i << ": " << info.userData[i] << "\n";
+if (!info.services.empty())
+ {
+ std::cout << Indent(level) << "services:\n";
+ for (size_t i = 0; i < info.services.size(); ++i)
+ std::cout << Indent(level + 1, true) << info.services[i] << "\n";
+ }
+if (!info.authBy.empty())
+ {
+ std::cout << Indent(level) << "auth by:\n";
+ for (size_t i = 0; i < info.authBy.size(); ++i)
+ std::cout << Indent(level + 1, true) << info.authBy[i] << "\n";
+ }
+}
+
+std::vector<SGCONF::API_ACTION::PARAM> GetUserParams()
+{
+std::vector<SGCONF::API_ACTION::PARAM> params;
+params.push_back(SGCONF::API_ACTION::PARAM("password", "<password>", "\tuser's password"));
+params.push_back(SGCONF::API_ACTION::PARAM("cash-add", "<cash[:message]>", "cash to add (with optional comment)"));
+params.push_back(SGCONF::API_ACTION::PARAM("cash-set", "<cash[:message]>", "cash to set (with optional comment)"));
+params.push_back(SGCONF::API_ACTION::PARAM("credit", "<amount>", "\tuser's credit"));
+params.push_back(SGCONF::API_ACTION::PARAM("credit-expire", "<date>", "\tcredit expiration"));
+params.push_back(SGCONF::API_ACTION::PARAM("free", "<free mb>", "\tprepaid traffic"));
+params.push_back(SGCONF::API_ACTION::PARAM("disabled", "<flag>", "\tdisable user (y|n)"));
+params.push_back(SGCONF::API_ACTION::PARAM("passive", "<flag>", "\tmake user passive (y|n)"));
+params.push_back(SGCONF::API_ACTION::PARAM("disable-detail-stat", "<flag>", "disable detail stat (y|n)"));
+params.push_back(SGCONF::API_ACTION::PARAM("always-online", "<flag>", "\tmake user always online (y|n)"));
+params.push_back(SGCONF::API_ACTION::PARAM("ips", "<ips>", "\t\tcoma-separated list of ips"));
+params.push_back(SGCONF::API_ACTION::PARAM("tariff", "<tariff name>", "\tcurrent tariff"));
+params.push_back(SGCONF::API_ACTION::PARAM("next-tariff", "<tariff name>", "tariff starting from the next month"));
+params.push_back(SGCONF::API_ACTION::PARAM("group", "<group>", "\t\tuser's group"));
+params.push_back(SGCONF::API_ACTION::PARAM("note", "<note>", "\t\tuser's note"));
+params.push_back(SGCONF::API_ACTION::PARAM("email", "<email>", "\t\tuser's email"));
+params.push_back(SGCONF::API_ACTION::PARAM("name", "<real name>", "\tuser's real name"));
+params.push_back(SGCONF::API_ACTION::PARAM("address", "<address>", "\tuser's postal address"));
+params.push_back(SGCONF::API_ACTION::PARAM("phone", "<phone>", "\t\tuser's phone number"));
+params.push_back(SGCONF::API_ACTION::PARAM("corp", "<corp name>", "\tcorporation name"));
+params.push_back(SGCONF::API_ACTION::PARAM("session-traffic", "<up/dn, ...>", "coma-separated session upload and download"));
+params.push_back(SGCONF::API_ACTION::PARAM("month-traffic", "<up/dn, ...>", "coma-separated month upload and download"));
+params.push_back(SGCONF::API_ACTION::PARAM("user-data", "<value, ...>", "coma-separated user data values"));
+return params;
+}
+
+std::vector<SGCONF::API_ACTION::PARAM> GetCheckParams()
+{
+std::vector<SGCONF::API_ACTION::PARAM> params;
+params.push_back(SGCONF::API_ACTION::PARAM("password", "<password>", "\tuser's password"));
+return params;
+}
+
+std::vector<SGCONF::API_ACTION::PARAM> GetMessageParams()
+{
+std::vector<SGCONF::API_ACTION::PARAM> params;
+params.push_back(SGCONF::API_ACTION::PARAM("logins", "<login, ...>", "\tlist of logins to send a message"));
+params.push_back(SGCONF::API_ACTION::PARAM("text", "<text>", "\t\tmessage text"));
+return params;
+}
+
+void ConvBool(const std::string & value, RESETABLE<int> & res)
+{
+res = !value.empty() && value[0] == 'y';
+}
+
+void Splice(std::vector<RESETABLE<std::string> > & lhs, const std::vector<RESETABLE<std::string> > & rhs)
+{
+for (size_t i = 0; i < lhs.size() && i < rhs.size(); ++i)
+ lhs[i].splice(rhs[i]);
+}
+
+RESETABLE<std::string> ConvString(const std::string & value)
+{
+return value;
+}
+
+void ConvStringList(std::string value, std::vector<RESETABLE<std::string> > & res)
+{
+Splice(res, Split<std::vector<RESETABLE<std::string> > >(value, ',', ConvString));
+}
+
+void ConvServices(std::string value, RESETABLE<std::vector<std::string> > & res)
+{
+value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
+res = Split<std::vector<std::string> >(value, ',');
+}
+
+void ConvCreditExpire(const std::string & value, RESETABLE<time_t> & res)
+{
+struct tm brokenTime;
+if (stg_strptime(value.c_str(), "%Y-%m-%d %H:%M:%S", &brokenTime) == NULL)
+ throw SGCONF::ACTION::ERROR("Credit expiration should be in format 'YYYY-MM-DD HH:MM:SS'. Got: '" + value + "'");
+res = stg_timegm(&brokenTime);
+}
+
+void ConvIPs(const std::string & value, RESETABLE<USER_IPS> & res)
+{
+res = StrToIPS(value);
+}
+
+struct TRAFF
+{
+ uint64_t up;
+ uint64_t down;
+};
+
+TRAFF ConvTraff(const std::string & value)
+{
+TRAFF res;
+size_t slashPos = value.find_first_of('/');
+if (slashPos == std::string::npos)
+ throw SGCONF::ACTION::ERROR("Traffic record should be in format 'upload/download'. Got: '" + value + "'");
+
+if (str2x(value.substr(0, slashPos), res.up) < 0)
+ throw SGCONF::ACTION::ERROR("Traffic value should be an integer. Got: '" + value.substr(0, slashPos) + "'");
+if (str2x(value.substr(slashPos + 1, value.length() - slashPos), res.down) < 0)
+ throw SGCONF::ACTION::ERROR("Traffic value should be an integer. Got: '" + value.substr(slashPos + 1, value.length() - slashPos) + "'");
+return res;
+}
+
+void ConvSessionTraff(std::string value, USER_STAT_RES & res)
+{
+value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
+std::vector<TRAFF> traff(Split<std::vector<TRAFF> >(value, ',', ConvTraff));
+if (traff.size() != DIR_NUM)
+ throw SGCONF::ACTION::ERROR("There should be prcisely " + x2str(DIR_NUM) + " records of session traffic.");
+for (size_t i = 0; i < DIR_NUM; ++i)
+ {
+ res.sessionUp[i] = traff[i].up;
+ res.sessionDown[i] = traff[i].down;
+ }
+}
+
+void ConvMonthTraff(std::string value, USER_STAT_RES & res)
+{
+value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
+std::vector<TRAFF> traff(Split<std::vector<TRAFF> >(value, ',', ConvTraff));
+if (traff.size() != DIR_NUM)
+ throw SGCONF::ACTION::ERROR("There should be prcisely " + x2str(DIR_NUM) + " records of month traffic.");
+for (size_t i = 0; i < DIR_NUM; ++i)
+ {
+ res.monthUp[i] = traff[i].up;
+ res.monthDown[i] = traff[i].down;
+ }
+}
+
+void ConvCashInfo(const std::string & value, RESETABLE<CASH_INFO> & res)
+{
+CASH_INFO info;
+size_t pos = value.find_first_of(':');
+if (pos == std::string::npos)
+ {
+ if (str2x(value, info.first) < 0)
+ throw SGCONF::ACTION::ERROR("Cash should be a double value. Got: '" + value + "'");
+ }
+else
+ {
+ if (str2x(value.substr(0, pos), info.first) < 0)
+ throw SGCONF::ACTION::ERROR("Cash should be a double value. Got: '" + value + "'");
+ info.second = value.substr(pos + 1);
+ }
+res = info;
+}
+
+void SimpleCallback(bool result,
+ const std::string & reason,
+ void * /*data*/)
+{
+if (!result)
+ {
+ std::cerr << "Operation failed. Reason: '" << reason << "'." << std::endl;
+ return;
+ }
+std::cout << "Success.\n";
+}
+
+void GetUsersCallback(bool result,
+ const std::string & reason,
+ const std::vector<STG::GET_USER::INFO> & info,
+ void * /*data*/)
+{
+if (!result)
+ {
+ std::cerr << "Failed to get user list. Reason: '" << reason << "'." << std::endl;
+ return;
+ }
+std::cout << "Users:\n";
+for (size_t i = 0; i < info.size(); ++i)
+ PrintUser(info[i], 1);
+}
+
+void GetUserCallback(bool result,
+ const std::string & reason,
+ const STG::GET_USER::INFO & info,
+ void * /*data*/)
+{
+if (!result)
+ {
+ std::cerr << "Failed to get user. Reason: '" << reason << "'." << std::endl;
+ return;
+ }
+PrintUser(info);
+}
+
+void AuthByCallback(bool result,
+ const std::string & reason,
+ const std::vector<std::string> & info,
+ void * /*data*/)
+{
+if (!result)
+ {
+ std::cerr << "Failed to get authorizer list. Reason: '" << reason << "'." << std::endl;
+ return;
+ }
+std::cout << "Authorized by:\n";
+for (size_t i = 0; i < info.size(); ++i)
+ std::cout << Indent(1, true) << info[i] << "\n";
+}
+
+bool GetUsersFunction(const SGCONF::CONFIG & config,
+ const std::string & /*arg*/,
+ const std::map<std::string, std::string> & /*options*/)
+{
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.GetUsers(GetUsersCallback, NULL) == STG::st_ok;
+}
+
+bool GetUserFunction(const SGCONF::CONFIG & config,
+ const std::string & arg,
+ const std::map<std::string, std::string> & /*options*/)
+{
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.GetUser(arg, GetUserCallback, NULL) == STG::st_ok;
+}
+
+bool DelUserFunction(const SGCONF::CONFIG & config,
+ const std::string & arg,
+ const std::map<std::string, std::string> & /*options*/)
+{
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.DelUser(arg, SimpleCallback, NULL) == STG::st_ok;
+}
+
+bool AddUserFunction(const SGCONF::CONFIG & config,
+ const std::string & arg,
+ const std::map<std::string, std::string> & options)
+{
+USER_CONF_RES conf;
+SGCONF::MaybeSet(options, "password", conf.password);
+SGCONF::MaybeSet(options, "passive", conf.passive, ConvBool);
+SGCONF::MaybeSet(options, "disabled", conf.disabled, ConvBool);
+SGCONF::MaybeSet(options, "disable-detail-stat", conf.disabledDetailStat, ConvBool);
+SGCONF::MaybeSet(options, "always-online", conf.alwaysOnline, ConvBool);
+SGCONF::MaybeSet(options, "tariff", conf.tariffName);
+SGCONF::MaybeSet(options, "address", conf.address);
+SGCONF::MaybeSet(options, "phone", conf.phone);
+SGCONF::MaybeSet(options, "email", conf.email);
+SGCONF::MaybeSet(options, "note", conf.note);
+SGCONF::MaybeSet(options, "name", conf.realName);
+SGCONF::MaybeSet(options, "corp", conf.corp);
+SGCONF::MaybeSet(options, "services", conf.services, ConvServices);
+SGCONF::MaybeSet(options, "group", conf.group);
+SGCONF::MaybeSet(options, "credit", conf.credit);
+SGCONF::MaybeSet(options, "next-tariff", conf.nextTariff);
+SGCONF::MaybeSet(options, "user-data", conf.userdata, ConvStringList);
+SGCONF::MaybeSet(options, "credit-expire", conf.creditExpire, ConvCreditExpire);
+SGCONF::MaybeSet(options, "ips", conf.ips, ConvIPs);
+USER_STAT_RES stat;
+SGCONF::MaybeSet(options, "cash-set", stat.cashSet, ConvCashInfo);
+SGCONF::MaybeSet(options, "free", stat.freeMb);
+SGCONF::MaybeSet(options, "session-traffic", stat, ConvSessionTraff);
+SGCONF::MaybeSet(options, "month-traffic", stat, ConvMonthTraff);
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.AddUser(arg, conf, stat, SimpleCallback, NULL) == STG::st_ok;
+}
+
+bool ChgUserFunction(const SGCONF::CONFIG & config,
+ const std::string & arg,
+ const std::map<std::string, std::string> & options)
+{
+USER_CONF_RES conf;
+SGCONF::MaybeSet(options, "password", conf.password);
+SGCONF::MaybeSet(options, "passive", conf.passive, ConvBool);
+SGCONF::MaybeSet(options, "disabled", conf.disabled, ConvBool);
+SGCONF::MaybeSet(options, "disable-detail-stat", conf.disabledDetailStat, ConvBool);
+SGCONF::MaybeSet(options, "always-online", conf.alwaysOnline, ConvBool);
+SGCONF::MaybeSet(options, "tariff", conf.tariffName);
+SGCONF::MaybeSet(options, "address", conf.address);
+SGCONF::MaybeSet(options, "phone", conf.phone);
+SGCONF::MaybeSet(options, "email", conf.email);
+SGCONF::MaybeSet(options, "note", conf.note);
+SGCONF::MaybeSet(options, "name", conf.realName);
+SGCONF::MaybeSet(options, "corp", conf.corp);
+SGCONF::MaybeSet(options, "services", conf.services, ConvServices);
+SGCONF::MaybeSet(options, "group", conf.group);
+SGCONF::MaybeSet(options, "credit", conf.credit);
+SGCONF::MaybeSet(options, "next-tariff", conf.nextTariff);
+SGCONF::MaybeSet(options, "user-data", conf.userdata, ConvStringList);
+SGCONF::MaybeSet(options, "credit-expire", conf.creditExpire, ConvCreditExpire);
+SGCONF::MaybeSet(options, "ips", conf.ips, ConvIPs);
+USER_STAT_RES stat;
+SGCONF::MaybeSet(options, "cash-add", stat.cashAdd, ConvCashInfo);
+SGCONF::MaybeSet(options, "cash-set", stat.cashSet, ConvCashInfo);
+SGCONF::MaybeSet(options, "free", stat.freeMb);
+SGCONF::MaybeSet(options, "session-traffic", stat, ConvSessionTraff);
+SGCONF::MaybeSet(options, "month-traffic", stat, ConvMonthTraff);
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.ChgUser(arg, conf, stat, SimpleCallback, NULL) == STG::st_ok;
+}
+
+bool CheckUserFunction(const SGCONF::CONFIG & config,
+ const std::string & arg,
+ const std::map<std::string, std::string> & options)
+{
+std::map<std::string, std::string>::const_iterator it(options.find("password"));
+if (it == options.end())
+ throw SGCONF::ACTION::ERROR("Password is not specified.");
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.CheckUser(arg, it->second, SimpleCallback, NULL) == STG::st_ok;
+}
+
+bool SendMessageFunction(const SGCONF::CONFIG & config,
+ const std::string & /*arg*/,
+ const std::map<std::string, std::string> & options)
+{
+std::map<std::string, std::string>::const_iterator it(options.find("logins"));
+if (it == options.end())
+ throw SGCONF::ACTION::ERROR("Logins are not specified.");
+std::string logins = it->second;
+for (size_t i = 0; i < logins.length(); ++i)
+ if (logins[i] == ',')
+ logins[i] = ':';
+it = options.find("text");
+if (it == options.end())
+ throw SGCONF::ACTION::ERROR("Message text is not specified.");
+std::string text = it->second;
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.SendMessage(logins, text, SimpleCallback, NULL) == STG::st_ok;
+}
+
+bool AuthByFunction(const SGCONF::CONFIG & config,
+ const std::string & arg,
+ const std::map<std::string, std::string> & /*options*/)
+{
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.AuthBy(arg, AuthByCallback, NULL) == STG::st_ok;
+}
+
+} // namespace anonymous
+
+void SGCONF::AppendUsersOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks)
+{
+std::vector<API_ACTION::PARAM> params(GetUserParams());
+blocks.Add("User management options")
+ .Add("get-users", SGCONF::MakeAPIAction(commands, GetUsersFunction), "\tget user list")
+ .Add("get-user", SGCONF::MakeAPIAction(commands, "<login>", GetUserFunction), "get user")
+ .Add("add-user", SGCONF::MakeAPIAction(commands, "<login>", params, AddUserFunction), "add user")
+ .Add("del-user", SGCONF::MakeAPIAction(commands, "<login>", DelUserFunction), "delete user")
+ .Add("chg-user", SGCONF::MakeAPIAction(commands, "<login>", params, ChgUserFunction), "change user")
+ .Add("check-user", SGCONF::MakeAPIAction(commands, "<login>", GetCheckParams(), CheckUserFunction), "check user existance and credentials")
+ .Add("send-message", SGCONF::MakeAPIAction(commands, GetMessageParams(), SendMessageFunction), "send message")
+ .Add("auth-by", SGCONF::MakeAPIAction(commands, "<login>", AuthByFunction), "a list of authorizers user authorized by");
+}
--- /dev/null
+#ifndef __STG_SGCONF_USERS_H__
+#define __STG_SGCONF_USERS_H__
+
+namespace SGCONF
+{
+
+class OPTION_BLOCKS;
+class COMMANDS;
+
+void AppendUsersOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks);
+
+}
+
+#endif
--- /dev/null
+#ifndef __STG_SGCONF_UTILS_H__
+#define __STG_SGCONF_UTILS_H__
+
+#include "stg/common.h"
+#include "stg/resetable.h"
+
+#include <string>
+#include <map>
+
+namespace SGCONF
+{
+
+template <typename T>
+inline
+void MaybeSet(const std::map<std::string, std::string> & options, const std::string & name, RESETABLE<T> & res)
+{
+std::map<std::string, std::string>::const_iterator it(options.find(name));
+if (it == options.end())
+ return;
+T value;
+if (str2x(it->second, value) < 0)
+ return;
+res = value;
+}
+
+template <typename T, typename F>
+inline
+void MaybeSet(const std::map<std::string, std::string> & options, const std::string & name, T & res, F conv)
+{
+std::map<std::string, std::string>::const_iterator it(options.find(name));
+if (it == options.end())
+ return;
+conv(it->second, res);
+}
+
+template <>
+inline
+void MaybeSet<std::string>(const std::map<std::string, std::string> & options, const std::string & name, RESETABLE<std::string> & res)
+{
+std::map<std::string, std::string>::const_iterator it(options.find(name));
+if (it == options.end())
+ return;
+res = it->second;
+}
+
+} // namespace SGCONF
+
+#endif
+++ /dev/null
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/*
- * Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- */
-
- /*
- $Author: faust $
- $Revision: 1.3 $
- $Date: 2009/08/05 09:29:35 $
- */
-
-
-#ifndef VERSION_SG_H
-#define VERSION_SG_H
-
-#define VERSION_SG "1.08.9"
-
-#endif
-
-
#include "xml.h"
+#include "api_action.h"
+#include "options.h"
+#include "config.h"
+
+#include "stg/servconf.h"
+
+#include <iostream>
+#include <string>
+#include <map>
+
#include <expat.h>
namespace
size_t level;
};
-std::string Indent(size_t size)
+std::string Indent(size_t level)
{
return std::string(level * 4, ' ');
}
{
ParserState * state = static_cast<ParserState *>(data);
if (el != NULL)
- std::cout << Indent(state->level) << "<" << el << PrintAttrs(attr) << ">\n";
+ std::cout << Indent(state->level) << "<" << el << PrintAttr(attr) << ">\n";
++state->level;
}
void End(void * data, const char * el)
{
ParserState * state = static_cast<ParserState *>(data);
+--state->level;
if (el != NULL)
std::cout << Indent(state->level) << "</" << el << ">\n";
---state->level;
}
-}
-
-void SGCONF::PrintXML(const std::string& xml)
+void PrintXML(const std::string& xml)
{
ParserState state = { 0 };
XML_SetUserData(parser, &state);
if (XML_Parse(parser, xml.c_str(), xml.length(), true) == XML_STATUS_ERROR)
- std::cerr << "XML parse error at line " << XML_GetCurrentLineNumber(sc->parser)
- << ": '" << XML_ErrorString(XML_GetErrorCode(sc->parser)) << "'"
+ std::cerr << "XML parse error at line " << XML_GetCurrentLineNumber(parser)
+ << ": '" << XML_ErrorString(XML_GetErrorCode(parser)) << "'"
<< std::endl;
XML_ParserFree(parser);
}
+
+void RawXMLCallback(bool result, const std::string & reason, const std::string & response, void * /*data*/)
+{
+if (!result)
+ {
+ std::cerr << "Failed to get raw XML response. Reason: '" << reason << "'." << std::endl;
+ return;
+ }
+PrintXML(response);
+}
+
+bool RawXMLFunction(const SGCONF::CONFIG & config,
+ const std::string & arg,
+ const std::map<std::string, std::string> & /*options*/)
+{
+STG::SERVCONF proto(config.server.data(),
+ config.port.data(),
+ config.localAddress.data(),
+ config.localPort.data(),
+ config.userName.data(),
+ config.userPass.data());
+return proto.RawXML(arg, RawXMLCallback, NULL) == STG::st_ok;
+}
+
+}
+
+void SGCONF::AppendXMLOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks)
+{
+blocks.Add("Raw XML")
+ .Add("r", "raw", SGCONF::MakeAPIAction(commands, "<xml>", RawXMLFunction), "\tmake raw XML request");
+}
#ifndef __STG_SGCONF_XML_H__
#define __STG_SGCONF_XML_H__
-#include <string>
-
namespace SGCONF
{
-void PrintXML(const std::string& xml);
+class OPTION_BLOCKS;
+class COMMANDS;
+
+void AppendXMLOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks);
}
case $release in
4) OS=bsd;;
5) OS=bsd5;;
- 6) OS=bsd5;;
+ 6) OS=bsd5;;
7) OS=bsd7;;
- 8) OS=bsd7;;
- 9) OS=bsd7;;
- *) OS=unknown;;
+ *) OS=bsd7;;
esac
MAKE="gmake"
fi
if [ "$OS" = "unknown" ]
-then
+then
printf "#############################################################################\n"
printf "# Sorry, but sgconf currently supported by Linux, FreeBSD 4.x, 5.x, 6.x #\n"
printf "#############################################################################\n"
printf "#############################################################################\n"
STG_LIBS="conffiles.lib
- crypto.lib
- common.lib
- srvconf.lib"
+ crypto.lib
+ common.lib
+ srvconf.lib"
if [ "$OS" = "linux" ]
then
5) OS=bsd5;;
6) OS=bsd5;;
7) OS=bsd7;;
- 8) OS=bsd7;;
- 9) OS=bsd7;;
- *) OS=unknown;;
+ *) OS=bsd7;;
esac
MAKE="gmake"
fi
if [ "$OS" = "unknown" ]
-then
+then
printf "#############################################################################\n"
printf "# Sorry, but sgconv currently supported by Linux, FreeBSD 4.x, 5.x, 6.x #\n"
printf "#############################################################################\n"
printf " Building sgconv for $sys $release\n"
printf "#############################################################################\n"
-STG_LIBS="logger.lib
+STG_LIBS="logger.lib
locker.lib
- crypto.lib
- common.lib
- conffiles.lib
- dotconfpp.lib"
+ crypto.lib
+ common.lib
+ conffiles.lib
+ dotconfpp.lib"
PLUGINS="store/files"
5) OS=bsd5;;
6) OS=bsd5;;
7) OS=bsd7;;
- 8) OS=bsd7;;
- 9) OS=bsd7;;
- *) OS=unknown;;
+ *) OS=bsd7;;
esac
ETC_DIR="./inst/freebsd/etc/stargazer"
MAKE="gmake"
fi
if [ "$OS" = "unknown" ]
-then
+then
printf "#############################################################################\n"
printf "# Sorry, but stargazer currently supported by Linux, FreeBSD 4.x, 5.x, 6.x #\n"
printf "#############################################################################\n"
printf " Building STG 2.4 for $sys $release\n"
printf "#############################################################################\n"
-STG_LIBS="logger.lib
+STG_LIBS="logger.lib
locker.lib
- crypto.lib
- common.lib
- scriptexecuter.lib
- conffiles.lib
- pinger.lib
- dotconfpp.lib
+ crypto.lib
+ common.lib
+ scriptexecuter.lib
+ conffiles.lib
+ pinger.lib
+ dotconfpp.lib
smux.lib"
PLUGINS="authorization/ao
fi
fi
+printf "Checking for -lpcap... "
+$CC $CFLAGS $LDFLAGS build_check.c -lpcap -o fake > /dev/null 2> /dev/null
+if [ $? != 0 ]
+then
+ CHECK_PCAP=no
+ printf "no\n"
+else
+ CHECK_PCAP=yes
+ printf "yes\n"
+fi
+rm -f fake
+
+printf "Checking for -lnfnetlink "
+$CC $CFLAGS $LDFLAGS build_check.c -lnfnetlink -o fake > /dev/null 2> /dev/null
+if [ $? != 0 ]
+then
+ CHECK_NFNETLINK=no
+ printf "no\n"
+else
+ CHECK_NFNETLINK=yes
+ printf "yes\n"
+fi
+rm -f fake
+
+printf "Checking for -lnetfilter_queue "
+$CC $CFLAGS $LDFLAGS build_check.c -lnetfilter_queue -o fake > /dev/null 2> /dev/null
+if [ $? != 0 ]
+then
+ CHECK_NFQ=no
+ printf "no\n"
+else
+ CHECK_NFQ=yes
+ printf "yes\n"
+fi
+rm -f fake
+
if [ "$OS" = "linux" ]
then
printf "Checking for linux/netfilter_ipv4/ip_queue.h... "
configuration/rpcconfig"
fi
+if [ "$CHECK_PCAP" = "yes" ]
+then
+ PLUGINS="$PLUGINS
+ capture/pcap"
+fi
+
+if [ "$CHECK_NFNETLINK" = "yes" -a "$CHECK_NFQ" = "yes" ]
+then
+ PLUGINS="$PLUGINS
+ capture/nfqueue"
+ NFQ_LIBS="-lnfnetlink -lnetfilter_queue"
+fi
+
printf "OS=$OS\n" > $CONFFILE
printf "STG_TIME=yes\n" >> $CONFFILE
printf "DEBUG=$DEBUG\n" >> $CONFFILE
printf "CHECK_MYSQLCLIENT=$CHECK_MYSQLCLIENT\n" >> $CONFFILE
printf "CHECK_PQ=$CHECK_PQ\n" >> $CONFFILE
printf "CHECK_XMLRPC=$CHECK_XMLRPC\n" >> $CONFFILE
+printf "CHECK_PCAP=$CHECK_PCAP\n" >> $CONFFILE
+printf "CHECK_NFNETLINK=$CHECK_NFNETLINK\n" >> $CONFFILE
+printf "CHECK_NFQ=$CHECK_NFQ\n" >> $CONFFILE
printf "DEFS=$DEFS\n" >> $CONFFILE
+printf "NFQ_LIBS=$NFQ_LIBS\n" >> $CONFFILE
printf "STG_LIBS=" >> $CONFFILE
for lib in $STG_LIBS
do
uint16_t len);
std::string DEBUG_CAP::GetVersion() const
{
-return "Debug_cap v.0.01a";
+return "cap_debug v.0.01a";
}
//-----------------------------------------------------------------------------
DEBUG_CAP::DEBUG_CAP()
#include <vector>
-#include "stg/common.h"
+#include "stg/common.h"
#include "stg/raw_ip_packet.h"
#include "stg/traffcounter.h"
#include "stg/plugin_creator.h"
runningUDP = false;
CloseUDP();
errorStr = "Cannot create UDP thread";
- logger("Cannot create UDP thread.");
+ logger("Cannot create UDP thread.");
printfd(__FILE__, "Error: Cannot create UDP thread\n");
return -1;
}
{
runningTCP = false;
CloseTCP();
- logger("Cannot create TCP thread.");
+ logger("Cannot create TCP thread.");
errorStr = "Cannot create TCP thread";
printfd(__FILE__, "Error: Cannot create TCP thread\n");
return -1;
if (pthread_kill(tidUDP, SIGUSR1))
{
errorStr = "Error sending signal to UDP thread";
- logger("Error sending sugnal to UDP thread.");
+ logger("Error sending sugnal to UDP thread.");
printfd(__FILE__, "Error: Error sending signal to UDP thread\n");
return -1;
}
if (pthread_kill(tidTCP, SIGUSR1))
{
errorStr = "Error sending signal to TCP thread";
- logger("Error sending signal to TCP thread.");
+ logger("Error sending signal to TCP thread.");
printfd(__FILE__, "Error: Error sending signal to TCP thread\n");
return -1;
}
printfd(__FILE__, "TCP thread NOT stopped\n");
- logger("Cannot stop TCP thread.");
+ logger("Cannot stop TCP thread.");
}
}
return 0;
break;
if (res < 0)
- {
- cap->logger("recvfrom error: %s", strerror(errno));
- continue;
- }
+ {
+ cap->logger("recvfrom error: %s", strerror(errno));
+ continue;
+ }
if (res == 0) // EOF
{
if (sd <= 0)
{
if (sd < 0)
- cap->logger("accept error: %s", strerror(errno));
+ cap->logger("accept error: %s", strerror(errno));
continue;
}
#include "stg/module_settings.h"
#include "stg/logger.h"
-#define VERSION "CAP_NF v. 0.4"
+#define VERSION "cap_nf v. 0.4"
#define START_POS 40
#define STOP_POS 40
//-----------------------------------------------------------------------------
std::string DIVERT_CAP::GetVersion() const
{
-return "Divert_cap v.1.0";
+return "cap_divert v.1.0";
}
//-----------------------------------------------------------------------------
DIVERT_CAP::DIVERT_CAP()
if (pthread_kill(thread, SIGINT))
{
errorStr = "Cannot kill thread.";
- logger("Cannot send signal to thread.");
+ logger("Cannot send signal to thread.");
printfd(__FILE__, "Cannot kill thread\n");
return -1;
}
*iface = cddiv.iface;
if (!disableForwarding)
- {
+ {
if (sendto(cddiv.sock, buf, bytes, 0, (struct sockaddr*)&divertaddr, divertaddrSize) < 0)
- logger("sendto error: %s", strerror(errno));
- }
+ logger("sendto error: %s", strerror(errno));
+ }
}
else
{
//-----------------------------------------------------------------------------
std::string BPF_CAP::GetVersion() const
{
-return "bpf_cap v.1.0";
+return "cap_bpf v.1.0";
}
//-----------------------------------------------------------------------------
BPF_CAP::BPF_CAP()
capSock(-1),
settings(),
traffCnt(NULL),
- logger(GetPluginLogger(GetStgLogger(), "cap_ether"))
+ logger(GetPluginLogger(GetStgLogger(), "cap_bpf"))
{
}
//-----------------------------------------------------------------------------
if (pthread_kill(thread, SIGINT))
{
errorStr = "Cannot kill thread.";
- logger("Cannot send signal to thread.");
+ logger("Cannot send signal to thread.");
printfd(__FILE__, "Cannot kill thread\n");
return -1;
}
bd->r = read(bd->fd, bd->buffer, BUFF_LEN);
if (bd->r < 0)
{
- logger("read error: %s", strerror(errno));
+ logger("read error: %s", strerror(errno));
struct timespec ts = {0, 20000000};
nanosleep(&ts, NULL);
return -1;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
std::string ETHER_CAP::GetVersion() const
{
-return "Ether_cap v.1.2";
+return "cap_ether v.1.2";
}
//-----------------------------------------------------------------------------
ETHER_CAP::ETHER_CAP()
if (pthread_kill(thread, SIGUSR1))
{
errorStr = "Cannot kill thread.";
- logger("Cannot send signal to thread.");
+ logger("Cannot send signal to thread.");
return -1;
}
for (int i = 0; i < 25 && isRunning; ++i)
if (isRunning)
{
errorStr = "ETHER_CAP not stopped.";
- logger("Cannot stop thread.");
+ logger("Cannot stop thread.");
printfd(__FILE__, "Cannot stop thread\n");
return -1;
}
//-----------------------------------------------------------------------------
std::string IPQ_CAP::GetVersion() const
{
-return "ipq_cap v.1.2";
+return "cap_ipq v.1.2";
}
//-----------------------------------------------------------------------------
IPQ_CAP::IPQ_CAP()
--- /dev/null
+include ../../../../../Makefile.conf
+
+PROG = mod_cap_nfqueue.so
+
+SRCS = ./nfqueue.cpp
+
+LIBS += $(NFQ_LIBS) $(LIB_THREAD)
+
+STGLIBS = common \
+ logger
+
+include ../../Makefile.in
+
--- /dev/null
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+* Author : Maxim Mamontov <faust@stargazer.dp.ua>
+*/
+
+#include "nfqueue.h"
+
+#include "stg/traffcounter.h"
+#include "stg/plugin_creator.h"
+#include "stg/common.h"
+#include "stg/raw_ip_packet.h"
+
+extern "C" {
+
+#include <linux/netfilter.h> /* Defines verdicts (NF_ACCEPT, etc) */
+#include <libnetfilter_queue/libnetfilter_queue.h>
+
+}
+
+#include <cerrno>
+#include <csignal>
+
+#include <arpa/inet.h> // ntohl
+
+#include <unistd.h> // read
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+namespace
+{
+
+PLUGIN_CREATOR<NFQ_CAP> ncc;
+
+int Callback(struct nfq_q_handle * queueHandle, struct nfgenmsg * /*msg*/,
+ struct nfq_data * nfqData, void *data)
+{
+int id = 0;
+
+struct nfqnl_msg_packet_hdr * packetHeader = nfq_get_msg_packet_hdr(nfqData);
+if (packetHeader == NULL)
+ return 0;
+
+id = ntohl(packetHeader->packet_id);
+
+unsigned char * payload = NULL;
+
+if (nfq_get_payload(nfqData, &payload) < 0 || payload == NULL)
+ return id;
+
+RAW_PACKET packet;
+
+memcpy(&packet.rawPacket, payload, sizeof(packet.rawPacket));
+
+NFQ_CAP * cap = static_cast<NFQ_CAP *>(data);
+
+cap->Process(packet);
+
+return nfq_set_verdict(queueHandle, id, NF_ACCEPT, 0, NULL);
+}
+
+}
+
+extern "C" PLUGIN * GetPlugin();
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+PLUGIN * GetPlugin()
+{
+return ncc.GetPlugin();
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+std::string NFQ_CAP::GetVersion() const
+{
+return "cap_nfqueue v.1.0";
+}
+//-----------------------------------------------------------------------------
+NFQ_CAP::NFQ_CAP()
+ : errorStr(),
+ thread(),
+ nonstop(false),
+ isRunning(false),
+ queueNumber(0),
+ traffCnt(NULL),
+ logger(GetPluginLogger(GetStgLogger(), "cap_nfqueue"))
+{
+}
+//-----------------------------------------------------------------------------
+int NFQ_CAP::ParseSettings()
+{
+for (size_t i = 0; i < settings.moduleParams.size(); i++)
+ if (settings.moduleParams[i].param == "queueNumber")
+ if (str2x(settings.moduleParams[i].param, queueNumber) < 0)
+ {
+ errorStr = "Queue number should be a number. Got: '" + settings.moduleParams[i].param + "'";
+ logger(errorStr);
+ return -1;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int NFQ_CAP::Start()
+{
+if (isRunning)
+ return 0;
+
+nfqHandle = nfq_open();
+if (nfqHandle == NULL)
+ {
+ errorStr = "Failed to initialize netfilter queue.";
+ logger(errorStr);
+ return -1;
+ }
+
+if (nfq_unbind_pf(nfqHandle, AF_INET) < 0)
+ {
+ errorStr = "Failed to unbind netfilter queue from IP handling.";
+ logger(errorStr);
+ return -1;
+ }
+
+if (nfq_bind_pf(nfqHandle, AF_INET) < 0)
+ {
+ errorStr = "Failed to bind netfilter queue to IP handling.";
+ logger(errorStr);
+ return -1;
+ }
+
+queueHandle = nfq_create_queue(nfqHandle, queueNumber, &Callback, this);
+if (queueHandle == NULL)
+ {
+ errorStr = "Failed to create queue " + x2str(queueNumber) + ".";
+ logger(errorStr);
+ return -1;
+ }
+
+if (nfq_set_mode(queueHandle, NFQNL_COPY_PACKET, 0xffFF) < 0)
+ {
+ errorStr = "Failed to set queue " + x2str(queueNumber) + " mode.";
+ logger(errorStr);
+ return -1;
+ }
+
+nonstop = true;
+
+if (pthread_create(&thread, NULL, Run, this))
+ {
+ errorStr = "Cannot create thread.";
+ logger("Cannot create thread.");
+ printfd(__FILE__, "Cannot create thread\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int NFQ_CAP::Stop()
+{
+if (!isRunning)
+ return 0;
+
+nonstop = false;
+
+//5 seconds to thread stops itself
+for (int i = 0; i < 25 && isRunning; i++)
+ {
+ struct timespec ts = {0, 200000000};
+ nanosleep(&ts, NULL);
+ }
+//after 5 seconds waiting thread still running. now killing it
+if (isRunning)
+ {
+ if (pthread_kill(thread, SIGUSR1))
+ {
+ errorStr = "Cannot kill thread.";
+ logger("Cannot send signal to thread.");
+ return -1;
+ }
+ for (int i = 0; i < 25 && isRunning; ++i)
+ {
+ struct timespec ts = {0, 200000000};
+ nanosleep(&ts, NULL);
+ }
+ if (isRunning)
+ {
+ errorStr = "NFQ_CAP not stopped.";
+ logger("Cannot stop thread.");
+ printfd(__FILE__, "Cannot stop thread\n");
+ return -1;
+ }
+ }
+
+pthread_join(thread, NULL);
+
+nfq_destroy_queue(queueHandle);
+nfq_close(nfqHandle);
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+void * NFQ_CAP::Run(void * d)
+{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+NFQ_CAP * dc = static_cast<NFQ_CAP *>(d);
+dc->isRunning = true;
+
+int fd = nfq_fd(dc->nfqHandle);
+char buf[4096];
+
+while (dc->nonstop)
+ {
+ if (!WaitPackets(fd))
+ continue;
+
+ int rv = read(fd, buf, sizeof(buf));
+ if (rv < 0)
+ {
+ dc->errorStr = std::string("Read error: ") + strerror(errno);
+ dc->logger(dc->errorStr);
+ break;
+ }
+ nfq_handle_packet(dc->nfqHandle, buf, rv);
+ }
+
+dc->isRunning = false;
+return NULL;
+}
+//-----------------------------------------------------------------------------
+void NFQ_CAP::Process(const RAW_PACKET & packet)
+{
+traffCnt->Process(packet);
+}
--- /dev/null
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+* Author : Maxim Mamontov <faust@stargazer.dp.ua>
+*/
+
+#ifndef NFQ_CAP_H
+#define NFQ_CAP_H
+
+#include "stg/plugin.h"
+#include "stg/module_settings.h"
+#include "stg/logger.h"
+
+#include <string>
+#include <vector>
+
+#include <pthread.h>
+
+class USERS;
+class TARIFFS;
+class ADMINS;
+class TRAFFCOUNTER;
+class SETTINGS;
+class RAW_PACKET;
+
+class TRAFFCOUNTER;
+
+struct nfq_handle;
+struct nfq_q_handle;
+
+class NFQ_CAP : public PLUGIN {
+public:
+ NFQ_CAP();
+ virtual ~NFQ_CAP() {}
+
+ void SetTraffcounter(TRAFFCOUNTER * tc) { traffCnt = tc; }
+
+ int Start();
+ int Stop();
+ int Reload() { return 0; }
+ bool IsRunning() { return isRunning; }
+
+ void SetSettings(const MODULE_SETTINGS & s) { settings = s; }
+ int ParseSettings();
+
+ const std::string & GetStrError() const { return errorStr; }
+ std::string GetVersion() const;
+ uint16_t GetStartPosition() const { return 40; }
+ uint16_t GetStopPosition() const { return 40; }
+
+ void Process(const RAW_PACKET & packet);
+
+private:
+ NFQ_CAP(const NFQ_CAP & rvalue);
+ NFQ_CAP & operator=(const NFQ_CAP & rvalue);
+
+ static void * Run(void *);
+
+ mutable std::string errorStr;
+
+ pthread_t thread;
+ bool nonstop;
+ bool isRunning;
+ MODULE_SETTINGS settings;
+
+ size_t queueNumber;
+
+ struct nfq_handle * nfqHandle;
+ struct nfq_q_handle * queueHandle;
+
+ TRAFFCOUNTER * traffCnt;
+
+ PLUGIN_LOGGER logger;
+};
+//-----------------------------------------------------------------------------
+
+#endif
--- /dev/null
+include ../../../../../Makefile.conf
+
+PROG = mod_cap_pcap.so
+
+SRCS = ./pcap_cap.cpp
+
+LIBS += -lpcap $(LIB_THREAD)
+
+STGLIBS = common \
+ logger
+
+include ../../Makefile.in
+
--- /dev/null
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+* Author : Maxim Mamontov <faust@stargazer.dp.ua>
+*/
+
+#include "pcap_cap.h"
+
+#include "stg/traffcounter.h"
+#include "stg/plugin_creator.h"
+#include "stg/common.h"
+#include "stg/raw_ip_packet.h"
+
+#include <signal.h>
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+namespace
+{
+PLUGIN_CREATOR<PCAP_CAP> pcc;
+
+const size_t SNAP_LEN = 1518;
+const size_t ETHER_ADDR_LEN = 6;
+
+struct ETH
+{
+u_char ether_dhost[ETHER_ADDR_LEN]; /* destination host address */
+u_char ether_shost[ETHER_ADDR_LEN]; /* source host address */
+u_short ether_type; /* IP? ARP? RARP? etc */
+};
+
+}
+
+extern "C" PLUGIN * GetPlugin();
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+PLUGIN * GetPlugin()
+{
+return pcc.GetPlugin();
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+std::string PCAP_CAP::GetVersion() const
+{
+return "pcap_cap v.1.0";
+}
+//-----------------------------------------------------------------------------
+PCAP_CAP::PCAP_CAP()
+ : errorStr(),
+ thread(),
+ nonstop(false),
+ isRunning(false),
+ traffCnt(NULL),
+ logger(GetPluginLogger(GetStgLogger(), "pcap_cap"))
+{
+}
+//-----------------------------------------------------------------------------
+int PCAP_CAP::ParseSettings()
+{
+devices.erase(devices.begin(), devices.end());
+
+if (settings.moduleParams.empty())
+ {
+ devices.push_back(DEV());
+ logger("Defaulting to pseudo-device 'any'.");
+ return 0;
+ }
+
+for (size_t i = 0; i < settings.moduleParams.size(); i++)
+ if (settings.moduleParams[i].param == "interfaces")
+ for (size_t j = 0; j < settings.moduleParams[i].value.size(); j++)
+ devices.push_back(DEV(settings.moduleParams[i].value[j]));
+
+for (size_t i = 0; i < settings.moduleParams.size(); i++)
+ if (settings.moduleParams[i].param == "filters")
+ for (size_t j = 0; j < settings.moduleParams[i].value.size(); j++)
+ if (j < devices.size())
+ devices[j].filterExpression = settings.moduleParams[i].value[j];
+
+if (devices.empty())
+ {
+ devices.push_back(DEV());
+ logger("Defaulting to pseudo-device 'all'.");
+ return 0;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int PCAP_CAP::Start()
+{
+if (isRunning)
+ return 0;
+
+DEV_MAP::iterator it(devices.begin());
+while (it != devices.end())
+ {
+ bpf_u_int32 mask;
+ bpf_u_int32 net;
+ char errbuf[PCAP_ERRBUF_SIZE];
+
+ /* get network number and mask associated with capture device */
+ if (pcap_lookupnet(it->device.c_str(), &net, &mask, errbuf) == -1)
+ {
+ errorStr = "Couldn't get netmask for device " + it->device + ": " + errbuf;
+ logger(errorStr);
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+
+ /* open capture device */
+ it->handle = pcap_open_live(it->device.c_str(), SNAP_LEN, 1, 1000, errbuf);
+ if (it->handle == NULL)
+ {
+ errorStr = "Couldn't open device " + it->device + ": " + errbuf;
+ logger(errorStr);
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+
+ if (pcap_setnonblock(it->handle, true, errbuf) == -1)
+ {
+ errorStr = "Couldn't put device " + it->device + " into non-blocking mode: " + errbuf;
+ logger(errorStr);
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+
+ /* make sure we're capturing on an Ethernet device [2] */
+ if (pcap_datalink(it->handle) != DLT_EN10MB)
+ {
+ errorStr = it->device + " is not an Ethernet";
+ logger(errorStr);
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+
+ /* compile the filter expression */
+ if (pcap_compile(it->handle, &it->filter, it->filterExpression.c_str(), 0, net) == -1)
+ {
+ errorStr = "Couldn't parse filter " + it->filterExpression + ": " + pcap_geterr(it->handle);
+ logger(errorStr);
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+
+ /* apply the compiled filter */
+ if (pcap_setfilter(it->handle, &it->filter) == -1)
+ {
+ errorStr = "Couldn't install filter " + it->filterExpression + ": " + pcap_geterr(it->handle);
+ logger(errorStr);
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+
+ it->fd = pcap_get_selectable_fd(it->handle);
+ if (it->fd == -1)
+ {
+ errorStr = "Couldn't get a file descriptor for " + it->device + ": " + pcap_geterr(it->handle);
+ logger(errorStr);
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+
+ ++it;
+ }
+
+nonstop = true;
+
+if (pthread_create(&thread, NULL, Run, this))
+ {
+ errorStr = "Cannot create thread.";
+ logger("Cannot create thread.");
+ printfd(__FILE__, "Cannot create thread\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int PCAP_CAP::Stop()
+{
+if (!isRunning)
+ return 0;
+
+nonstop = false;
+
+//5 seconds to thread stops itself
+for (int i = 0; i < 25 && isRunning; i++)
+ {
+ struct timespec ts = {0, 200000000};
+ nanosleep(&ts, NULL);
+ }
+//after 5 seconds waiting thread still running. now killing it
+if (isRunning)
+ {
+ if (pthread_kill(thread, SIGUSR1))
+ {
+ errorStr = "Cannot kill thread.";
+ logger("Cannot send signal to thread.");
+ return -1;
+ }
+ for (int i = 0; i < 25 && isRunning; ++i)
+ {
+ struct timespec ts = {0, 200000000};
+ nanosleep(&ts, NULL);
+ }
+ if (isRunning)
+ {
+ errorStr = "PCAP_CAP not stopped.";
+ logger("Cannot stop thread.");
+ printfd(__FILE__, "Cannot stop thread\n");
+ return -1;
+ }
+ }
+
+pthread_join(thread, NULL);
+
+for (DEV_MAP::iterator it(devices.begin()); it != devices.end(); ++it)
+ {
+ pcap_freecode(&it->filter);
+ pcap_close(it->handle);
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+void * PCAP_CAP::Run(void * d)
+{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+PCAP_CAP * dc = static_cast<PCAP_CAP *>(d);
+dc->isRunning = true;
+
+fd_set fds;
+FD_ZERO(&fds);
+int maxFd = 0;
+for (DEV_MAP::const_iterator it(dc->devices.begin()); it != dc->devices.end(); ++it)
+ {
+ FD_SET(it->fd, &fds);
+ maxFd = std::max(maxFd, it->fd);
+ }
+
+while (dc->nonstop)
+ {
+ fd_set rfds = fds;
+ struct timeval tv = {0, 500000};
+
+ if (select(maxFd + 1, &rfds, NULL, NULL, &tv) > 0)
+ dc->TryRead(rfds);
+ }
+
+dc->isRunning = false;
+return NULL;
+}
+
+void PCAP_CAP::TryRead(const fd_set & set)
+{
+for (DEV_MAP::const_iterator it(devices.begin()); it != devices.end(); ++it)
+ if (FD_ISSET(it->fd, &set))
+ TryReadDev(*it);
+}
+
+void PCAP_CAP::TryReadDev(const DEV & dev)
+{
+struct pcap_pkthdr * header;
+const u_char * packet;
+if (pcap_next_ex(dev.handle, &header, &packet) == -1)
+ {
+ printfd(__FILE__, "Failed to read data from '%s': %s\n", dev.device.c_str(), pcap_geterr(dev.handle));
+ return;
+ }
+
+const ETH * eth = reinterpret_cast<const ETH *>(packet);
+if (eth->ether_type != 0x8)
+ return;
+
+RAW_PACKET ip;
+memcpy(&ip.rawPacket, packet + 14, sizeof(ip.rawPacket));
+traffCnt->Process(ip);
+}
--- /dev/null
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+* Author : Maxim Mamontov <faust@stargazer.dp.ua>
+*/
+
+#ifndef PCAP_CAP_H
+#define PCAP_CAP_H
+
+#include "stg/plugin.h"
+#include "stg/module_settings.h"
+#include "stg/logger.h"
+
+#include <string>
+#include <vector>
+
+#include <pcap.h>
+#include <pthread.h>
+#include <sys/select.h>
+
+class USERS;
+class TARIFFS;
+class ADMINS;
+class TRAFFCOUNTER;
+class SETTINGS;
+
+class TRAFFCOUNTER;
+
+struct DEV
+{
+ DEV() : device("any"), filterExpression("ip"), handle(NULL), fd(-1) {}
+ DEV(const std::string & d) : device(d), filterExpression("ip"), handle(NULL), fd(-1) {}
+ DEV(const std::string & d, const std::string & f)
+ : device(d), filterExpression(f), handle(NULL), fd(-1) {}
+
+ std::string device;
+ std::string filterExpression;
+ pcap_t * handle;
+ struct bpf_program filter;
+ int fd;
+};
+
+typedef std::vector<DEV> DEV_MAP;
+
+class PCAP_CAP : public PLUGIN {
+public:
+ PCAP_CAP();
+ virtual ~PCAP_CAP() {}
+
+ void SetTraffcounter(TRAFFCOUNTER * tc) { traffCnt = tc; }
+
+ int Start();
+ int Stop();
+ int Reload() { return 0; }
+ bool IsRunning() { return isRunning; }
+
+ void SetSettings(const MODULE_SETTINGS & s) { settings = s; }
+ int ParseSettings();
+
+ const std::string & GetStrError() const { return errorStr; }
+ std::string GetVersion() const;
+ uint16_t GetStartPosition() const { return 40; }
+ uint16_t GetStopPosition() const { return 40; }
+
+private:
+ PCAP_CAP(const PCAP_CAP & rvalue);
+ PCAP_CAP & operator=(const PCAP_CAP & rvalue);
+
+ void TryRead(const fd_set & set);
+ void TryReadDev(const DEV & dev);
+
+ static void * Run(void *);
+
+ mutable std::string errorStr;
+
+ pthread_t thread;
+ bool nonstop;
+ bool isRunning;
+ MODULE_SETTINGS settings;
+ DEV_MAP devices;
+
+ TRAFFCOUNTER * traffCnt;
+
+ PLUGIN_LOGGER logger;
+};
+//-----------------------------------------------------------------------------
+
+#endif
virtual ~BASE_PARSER() {}
virtual int ParseStart(void *data, const char *el, const char **attr) = 0;
virtual int ParseEnd(void *data, const char *el) = 0;
+ virtual void Reset() { answerList->clear(); depth = 0; }
void SetAnswerList(std::list<std::string> * ansList) { answerList = ansList; }
void SetCurrAdmin(ADMIN & cua) { currAdmin = &cua; }
std::string & GetStrError() { return strError; }
- void Reset() { answerList->clear(); depth = 0; }
protected:
BASE_PARSER(const BASE_PARSER & rvalue);
PQclear(result);
-if (SaveUserServices(uid, conf.service))
+if (SaveUserServices(uid, conf.services))
{
printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to save user's services'\n");
if (RollbackTransaction())
for (int i = 0; i < tuples; ++i)
{
- conf->service.push_back(PQgetvalue(result, i, 0));
+ conf->services.push_back(PQgetvalue(result, i, 0));
}
PQclear(result);
return result;
}
//-----------------------------------------------------------------------------
+std::string TimeToString(time_t time)
+{
+struct tm brokenTime;
+
+brokenTime.tm_wday = 0;
+brokenTime.tm_yday = 0;
+brokenTime.tm_isdst = 0;
+
+gmtime_r(&time, &brokenTime);
+
+char buf[32];
+strftime(buf, 32, "%Y-%m-%d %H:%M:%S", &brokenTime);
+
+return buf;
+}
+//-----------------------------------------------------------------------------
int ParseTariffTimeStr(const char * str, int &h1, int &m1, int &h2, int &m2)
{
char hs1[10], ms1[10], hs2[10], ms2[10];
const std::string & x2str(double x, std::string & s)
{
char buf[256];
-s = snprintf(buf, sizeof(buf), "%f", x);
+snprintf(buf, sizeof(buf), "%f", x);
+s = buf;
return s;
}
//---------------------------------------------------------------------------
#include <ctime>
#endif
#include <string>
+#include <sstream>
#include "stg/os_int.h"
#include "stg/const.h"
int Min8(int a);
std::string inet_ntostring(uint32_t);
uint32_t inet_strington(const std::string & value);
+std::string TimeToString(time_t time);
int strprintf(std::string * str, const char * fmt, ...);
int ParseTariffTimeStr(const char * str, int &h1, int &m1, int &h2, int &m2);
uint32_t CalcMask(uint32_t msk);
std::string ToLower(const std::string & value);
std::string ToUpper(const std::string & value);
-std::string IconvString(const std::string & source, const std::string & from, const std::string & to);
+template <typename C, typename F>
+inline
+C Split(const std::string & value, char delim, F conv)
+{
+C res;
+size_t startPos = 0;
+size_t pos = value.find_first_of(delim);
+while (pos != std::string::npos)
+ {
+ res.push_back(conv(value.substr(startPos, pos - startPos)));
+ startPos = pos + 1;
+ pos = value.find_first_of(delim, pos + 1);
+ }
+res.push_back(conv(value.substr(startPos, pos - startPos)));
+return res;
+}
+
+template <typename T>
+inline
+T FromString(const std::string & value)
+{
+T res;
+std::istringstream stream(value);
+stream >> res;
+return res;
+}
+
+template <>
+inline
+std::string FromString<std::string>(const std::string & value)
+{
+return value;
+}
+
+template <typename C>
+inline
+C Split(const std::string & value, char delim)
+{
+ return Split<C>(value, delim, FromString<typename C::value_type>);
+}
+
+std::string IconvString(const std::string & source, const std::string & from, const std::string & to);
int ParseInt(const std::string & str, int * val);
int ParseUnsigned(const std::string & str, unsigned * val);
//-----------------------------------------------------------------------------
int str2x(const std::string & str, int32_t & x);
int str2x(const std::string & str, uint32_t & x);
+inline
+int str2x(const std::string & str, double & x) { return strtodouble2(str.c_str(), x); }
#ifndef WIN32
int str2x(const std::string & str, int64_t & x);
int str2x(const std::string & str, uint64_t & x);
~STG_LOGGER();
void SetLogFileName(const std::string & fn);
void operator()(const char * fmt, ...) const;
+ void operator()(const std::string & line) const { LogString(line.c_str()); }
private:
STG_LOGGER();
STG_LOGGER & operator=(const STG_LOGGER & rvalue);
const char * LogDate(time_t t) const;
+ void LogString(const char * str) const;
std::string fileName;
mutable pthread_mutex_t mutex;
public:
PLUGIN_LOGGER(const PLUGIN_LOGGER & rhs);
void operator()(const char * fmt, ...) const;
+ void operator()(const std::string & line) const;
private:
PLUGIN_LOGGER(const STG_LOGGER & logger, const std::string & pn);
vsnprintf(buff, sizeof(buff), fmt, vl);
va_end(vl);
-FILE * f;
+LogString(buff);
+}
+//-----------------------------------------------------------------------------
+const char * STG_LOGGER::LogDate(time_t t) const
+{
+static char s[32];
+if (t == 0)
+ t = time(NULL);
+
+struct tm * tt = localtime(&t);
+
+snprintf(s, 32, "%d-%s%d-%s%d %s%d:%s%d:%s%d",
+ tt->tm_year + 1900,
+ tt->tm_mon + 1 < 10 ? "0" : "", tt->tm_mon + 1,
+ tt->tm_mday < 10 ? "0" : "", tt->tm_mday,
+ tt->tm_hour < 10 ? "0" : "", tt->tm_hour,
+ tt->tm_min < 10 ? "0" : "", tt->tm_min,
+ tt->tm_sec < 10 ? "0" : "", tt->tm_sec);
+
+return s;
+}
+//-----------------------------------------------------------------------------
+void STG_LOGGER::LogString(const char * str) const
+{
if (!fileName.empty())
{
- f = fopen(fileName.c_str(), "at");
+ FILE * f = fopen(fileName.c_str(), "at");
if (f)
{
#ifdef STG_TIME
fprintf(f, "%s", LogDate(time(NULL)));
#endif
fprintf(f, " -- ");
- fprintf(f, "%s", buff);
+ fprintf(f, "%s", str);
fprintf(f, "\n");
fclose(f);
}
else
{
openlog("stg", LOG_NDELAY, LOG_USER);
- syslog(LOG_CRIT, "%s", buff);
+ syslog(LOG_CRIT, "%s", str);
closelog();
}
}
else
{
openlog("stg", LOG_NDELAY, LOG_USER);
- syslog(LOG_CRIT, "%s", buff);
+ syslog(LOG_CRIT, "%s", str);
closelog();
}
}
//-----------------------------------------------------------------------------
-const char * STG_LOGGER::LogDate(time_t t) const
-{
-static char s[32];
-if (t == 0)
- t = time(NULL);
-
-struct tm * tt = localtime(&t);
-
-snprintf(s, 32, "%d-%s%d-%s%d %s%d:%s%d:%s%d",
- tt->tm_year + 1900,
- tt->tm_mon + 1 < 10 ? "0" : "", tt->tm_mon + 1,
- tt->tm_mday < 10 ? "0" : "", tt->tm_mday,
- tt->tm_hour < 10 ? "0" : "", tt->tm_hour,
- tt->tm_min < 10 ? "0" : "", tt->tm_min,
- tt->tm_sec < 10 ? "0" : "", tt->tm_sec);
-
-return s;
-}
-//-----------------------------------------------------------------------------
PLUGIN_LOGGER::PLUGIN_LOGGER(const STG_LOGGER & logger, const std::string & pn)
: STG_LOGGER(),
pluginName(pn)
STG_LOGGER::operator()("[%s] %s", pluginName.c_str(), buff);
}
//-----------------------------------------------------------------------------
+void PLUGIN_LOGGER::operator()(const std::string & line) const
+{
+STG_LOGGER::operator()("[%s] %s", pluginName.c_str(), line.c_str());
+}
+//-----------------------------------------------------------------------------
PLUGIN_LOGGER GetPluginLogger(const STG_LOGGER & logger, const std::string & pluginName)
{
return PLUGIN_LOGGER(logger, pluginName);
public:
SERVCONF(const std::string & server, uint16_t port,
const std::string & login, const std::string & password);
+ SERVCONF(const std::string & server, uint16_t port,
+ const std::string & localAddress, uint16_t localPort,
+ const std::string & login, const std::string & password);
~SERVCONF();
int ServerInfo(SERVER_INFO::CALLBACK f, void * data);
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 AddUser(const std::string & login,
+ const USER_CONF_RES & conf,
+ const USER_STAT_RES & stat,
+ SIMPLE::CALLBACK f, void * data);
int AuthBy(const std::string & login, AUTH_BY::CALLBACK f, void * data);
int SendMessage(const std::string & login, const std::string & text, SIMPLE::CALLBACK f, void * data);
int CheckUser(const std::string & login, const std::string & password, SIMPLE::CALLBACK f, void * data);
#ifndef __STG_STGLIBS_SRVCONF_TYPES_H__
#define __STG_STGLIBS_SRVCONF_TYPES_H__
+#include "stg/array.h"
#include "stg/const.h" // DIR_NUM
#include "stg/os_int.h" // uint32_t, etc...
int usersNum;
std::string uname;
int dirNum;
- std::string dirName[DIR_NUM];
+ ARRAY<std::string, DIR_NUM> dirName;
};
typedef void (* CALLBACK)(bool result, const std::string & reason, const INFO & info, void * data);
struct STAT
{
- long long su[DIR_NUM];
- long long sd[DIR_NUM];
- long long mu[DIR_NUM];
- long long md[DIR_NUM];
- double freeMb;
+ ARRAY<long long, DIR_NUM> su;
+ ARRAY<long long, DIR_NUM> sd;
+ ARRAY<long long, DIR_NUM> mu;
+ ARRAY<long long, DIR_NUM> md;
};
struct INFO
double cash;
double credit;
time_t creditExpire;
- double lastCash;
+ double lastCashAdd;
+ double lastCashAddTime;
+ time_t lastTimeCash;
double prepaidTraff;
- int down;
+ int disabled;
int passive;
int disableDetailStat;
int connected;
std::string name;
std::string address;
std::string phone;
+ std::string corp;
STAT stat;
- std::string userData[USERDATA_NUM];
+ time_t pingTime;
+ time_t lastActivityTime;
+ ARRAY<std::string, USERDATA_NUM> userData;
+ std::vector<std::string> services;
+ std::vector<std::string> authBy;
};
typedef void (* CALLBACK)(bool result, const std::string & reason, const INFO & info, void * data);
#define RECV_DATA_ANSWER_ERROR "Recv data answer error!"
#define UNKNOWN_ERROR "Unknown error!"
#define CONNECT_FAILED "Connect failed!"
+#define BIND_FAILED "Bind failed!"
#define INCORRECT_LOGIN "Incorrect login!"
#define INCORRECT_HEADER "Incorrect header!"
#define SEND_LOGIN_ERROR "Send login error!"
{
}
//---------------------------------------------------------------------------
+NETTRANSACT::NETTRANSACT(const std::string & s, uint16_t p,
+ const std::string & la, uint16_t lp,
+ const std::string & l, const std::string & pwd)
+ : server(s),
+ port(p),
+ localAddress(la),
+ localPort(lp),
+ login(l),
+ password(pwd),
+ outerSocket(-1)
+{
+}
+//---------------------------------------------------------------------------
int NETTRANSACT::Connect()
{
outerSocket = socket(PF_INET, SOCK_STREAM, 0);
return st_conn_fail;
}
+if (!localAddress.empty())
+ {
+ if (localPort == 0)
+ localPort = port;
+
+ unsigned long ip = inet_addr(localAddress.c_str());
+
+ if (ip == INADDR_NONE)
+ {
+ struct hostent * phe = gethostbyname(localAddress.c_str());
+ if (phe == NULL)
+ {
+ errorMsg = "DNS error.\nCan not reslove " + localAddress;
+ return st_dns_err;
+ }
+
+ struct hostent he;
+ memcpy(&he, phe, sizeof(he));
+ ip = *((long *)he.h_addr_list[0]);
+ }
+
+ struct sockaddr_in localAddr;
+ memset(&localAddr, 0, sizeof(localAddr));
+ localAddr.sin_family = AF_INET;
+ localAddr.sin_port = htons(localPort);
+ localAddr.sin_addr.s_addr = ip;
+
+ if (bind(outerSocket, (struct sockaddr *)&localAddr, sizeof(localAddr)) < 0)
+ {
+ errorMsg = BIND_FAILED;
+ close(outerSocket);
+ return st_conn_fail;
+ }
+ }
+
struct sockaddr_in outerAddr;
memset(&outerAddr, 0, sizeof(outerAddr));
NETTRANSACT(const std::string & server, uint16_t port,
const std::string & login, const std::string & password);
+ NETTRANSACT(const std::string & server, uint16_t port,
+ const std::string & localAddress, uint16_t localPort,
+ const std::string & login, const std::string & password);
int Transact(const std::string & request, CALLBACK f, void * data);
const std::string & GetError() const { return errorMsg; }
std::string server;
uint16_t port;
+ std::string localAddress;
+ uint16_t localPort;
std::string login;
std::string password;
int outerSocket;
using namespace STG;
-AUTH_BY::PARSER::PARSER(CALLBACK f, void * d)
+AUTH_BY::PARSER::PARSER(CALLBACK f, void * d, const std::string & e)
: callback(f),
data(d),
+ encoding(e),
depth(0),
parsingAnswer(false)
{
class PARSER: public STG::PARSER
{
public:
- PARSER(CALLBACK f, void * data);
+ PARSER(CALLBACK f, void * data, const std::string & encoding);
int ParseStart(const char * el, const char ** attr);
void ParseEnd(const char * el);
+ void Failure(const std::string & reason) { callback(false, reason, info, data); }
private:
CALLBACK callback;
void * data;
+ std::string encoding;
int depth;
bool parsingAnswer;
INFO info;
#ifndef __STG_STGLIBS_SRVCONF_PARSER_H__
#define __STG_STGLIBS_SRVCONF_PARSER_H__
+#include <string>
+
namespace STG
{
{
public:
virtual ~PARSER() {}
- virtual int ParseStart(const char *el, const char **attr) = 0;
- virtual void ParseEnd(const char *el) = 0;
+ virtual int ParseStart(const char * el, const char ** attr) = 0;
+ virtual void ParseEnd(const char * el) = 0;
+ virtual void Failure(const std::string & reason) = 0;
};
} // namespace STG
using namespace STG;
-std::string CHG_ADMIN::Serialize(const ADMIN_CONF_RES & conf)
+std::string CHG_ADMIN::Serialize(const ADMIN_CONF_RES & conf, const std::string & /*encoding*/)
{
std::string params;
if (!conf.login.empty())
namespace CHG_ADMIN
{
-std::string Serialize(const ADMIN_CONF_RES & conf);
+std::string Serialize(const ADMIN_CONF_RES & conf, const std::string & encoding);
} // namespace CHG_ADMIN
} // namespace STG
using namespace STG;
-std::string CHG_CORP::Serialize(const CORP_CONF_RES & conf)
+std::string CHG_CORP::Serialize(const CORP_CONF_RES & conf, const std::string & /*encoding*/)
{
std::ostringstream stream;
namespace CHG_CORP
{
-std::string Serialize(const CORP_CONF_RES & conf);
+std::string Serialize(const CORP_CONF_RES & conf, const std::string & encoding);
} // namespace CHG_CORP
} // namespace STG
using namespace STG;
-std::string CHG_SERVICE::Serialize(const SERVICE_CONF_RES & conf)
+std::string CHG_SERVICE::Serialize(const SERVICE_CONF_RES & conf, const std::string & /*encoding*/)
{
std::ostringstream stream;
appendResetable(stream, "name", conf.name);
-appendResetable(stream, "comment", conf.comment);
+appendResetable(stream, "comment", MaybeEncode(conf.comment));
appendResetable(stream, "cost", conf.cost);
appendResetable(stream, "payDay", conf.payDay);
namespace CHG_SERVICE
{
-std::string Serialize(const SERVICE_CONF_RES & conf);
+std::string Serialize(const SERVICE_CONF_RES & conf, const std::string & encoding);
} // namespace CHG_SERVICE
} // namespace STG
} // namespace anonymous
-std::string CHG_TARIFF::Serialize(const TARIFF_DATA_RES & data)
+std::string CHG_TARIFF::Serialize(const TARIFF_DATA_RES & data, const std::string & /*encoding*/)
{
std::ostringstream stream;
case TRAFF_MAX: stream << "<traffType value=\"max\"/>"; break;
}
+if (!data.tariffConf.period.empty())
+ switch (data.tariffConf.period.data())
+ {
+ case TARIFF::DAY: stream << "<period value=\"day\"/>"; break;
+ case TARIFF::MONTH: stream << "<period value=\"month\"/>"; break;
+ }
+
for (size_t i = 0; i < DIR_NUM; ++i)
if (!data.dirPrice[i].hDay.empty() &&
!data.dirPrice[i].mDay.empty() &&
namespace CHG_TARIFF
{
-std::string Serialize(const TARIFF_DATA_RES & data);
+std::string Serialize(const TARIFF_DATA_RES & data, const std::string & encoding);
} // namespace CHG_TARIFF
} // namespace STG
#include "stg/user_conf.h"
#include "stg/user_stat.h"
+#include "stg/common.h"
#include <sstream>
+#include <iostream>
#include <strings.h>
using namespace STG;
-CHG_USER::PARSER::PARSER(SIMPLE::CALLBACK f, void * d)
+CHG_USER::PARSER::PARSER(SIMPLE::CALLBACK f, void * d, const std::string & e)
: callback(f),
data(d),
+ encoding(e),
depth(0)
{
}
callback(false, "Invalid response.", data);
}
-std::string CHG_USER::Serialize(const USER_CONF_RES & conf, const USER_STAT_RES & stat)
+std::string CHG_USER::Serialize(const USER_CONF_RES & conf, const USER_STAT_RES & stat, const std::string & encoding)
{
std::ostringstream stream;
if (!conf.nextTariff.empty())
stream << "<tariff delayed=\"" << conf.nextTariff.data() << "\"/>";
else if (!conf.tariffName.empty())
- stream << "<tariff now=\"" << conf.nextTariff.data() << "\"/>";
+ stream << "<tariff now=\"" << conf.tariffName.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);
+appendResetable(stream, "note", MaybeEncode(MaybeIconv(conf.note, encoding, "koi8-ru")));
+appendResetable(stream, "name", MaybeEncode(MaybeIconv(conf.realName, encoding, "koi8-ru"))); // TODO: name -> realName
+appendResetable(stream, "address", MaybeEncode(MaybeIconv(conf.address, encoding, "koi8-ru")));
+appendResetable(stream, "email", MaybeEncode(MaybeIconv(conf.email, encoding, "koi8-ru")));
+appendResetable(stream, "phone", MaybeEncode(MaybeIconv(conf.phone, encoding, "cp1251")));
+appendResetable(stream, "group", MaybeEncode(MaybeIconv(conf.group, encoding, "koi8-ru")));
+appendResetable(stream, "corp", conf.corp);
for (size_t i = 0; i < conf.userdata.size(); ++i)
- appendResetable(stream, "userdata", i, conf.userdata[i]);
+ appendResetable(stream, "userdata", i, MaybeEncode(MaybeIconv(conf.userdata[i], encoding, "koi8-ru")));
+
+if (!conf.services.empty())
+ {
+ stream << "<services>";
+ for (size_t i = 0; i < conf.services.data().size(); ++i)
+ stream << "<service name=\"" << conf.services.data()[i] << "\"/>";
+ stream << "</services>";
+ }
// Stat
if (!stat.cashAdd.empty())
- stream << "<cash add=\"" << stat.cashAdd.data().first << "\" msg=\"" << stat.cashAdd.data().second << "\"/>";
+ stream << "<cash add=\"" << stat.cashAdd.data().first << "\" msg=\"" << IconvString(Encode12str(stat.cashAdd.data().second), encoding, "koi8-ru") << "\"/>";
else if (!stat.cashSet.empty())
- stream << "<cash set=\"" << stat.cashAdd.data().first << "\" msg=\"" << stat.cashAdd.data().second << "\"/>";
+ stream << "<cash set=\"" << stat.cashSet.data().first << "\" msg=\"" << IconvString(Encode12str(stat.cashSet.data().second), encoding, "koi8-ru") << "\"/>";
appendResetable(stream, "freeMb", stat.freeMb);
if (!traffData.empty())
stream << "<traff" << traffData << "/>";
+std::cerr << stream.str() << "\n";
return stream.str();
}
class PARSER: public STG::PARSER
{
public:
- PARSER(SIMPLE::CALLBACK f, void * data);
+ PARSER(SIMPLE::CALLBACK f, void * data, const std::string & encoding);
int ParseStart(const char * el, const char ** attr);
void ParseEnd(const char * el);
+ void Failure(const std::string & reason) { callback(false, reason, data); }
private:
SIMPLE::CALLBACK callback;
void * data;
+ std::string encoding;
int depth;
void ParseAnswer(const char * el, const char ** attr);
};
-std::string Serialize(const USER_CONF_RES & conf, const USER_STAT_RES & stat);
+std::string Serialize(const USER_CONF_RES & conf, const USER_STAT_RES & stat, const std::string & encoding);
} // namespace CHG_USER
} // namespace STG
template <>
inline
-bool GetValue<PRIV>(const char ** attr, PRIV & value)
+bool GetValue<PRIV>(const char ** attr, PRIV & value, const std::string & attrName)
{
uint32_t priv;
-if (!GetValue(attr, priv))
+if (!GetValue(attr, priv, attrName))
return false;
value = priv;
return true;
} // namespace STG
-GET_ADMIN::PARSER::PARSER(CALLBACK f, void * d)
+GET_ADMIN::PARSER::PARSER(CALLBACK f, void * d, const std::string & e)
: callback(f),
data(d),
+ encoding(e),
depth(0),
parsingAnswer(false)
{
if (depth == 1)
ParseAdmin(el, attr);
-if (depth == 2 && parsingAnswer)
- ParseAdminParams(el, attr);
+/*if (depth == 2 && parsingAnswer)
+ ParseAdminParams(el, attr);*/
return 0;
}
error = "Admin not found.";
}
else
+ {
parsingAnswer = true;
+ for (const char ** pos = attr; *pos != NULL; pos = pos + 2)
+ if (!TryParse(propertyParsers, ToLower(*pos), pos, *pos))
+ {
+ error = std::string("Invalid parameter '") + *pos + "'.";
+ break;
+ }
+ }
}
else
parsingAnswer = true;
}
}
//-----------------------------------------------------------------------------
-void GET_ADMIN::PARSER::ParseAdminParams(const char * el, const char ** attr)
+/*void GET_ADMIN::PARSER::ParseAdminParams(const char * el, const char ** attr)
{
if (!TryParse(propertyParsers, ToLower(el), attr))
error = "Invalid parameter.";
-}
+}*/
public:
typedef GET_ADMIN::INFO INFO;
- PARSER(CALLBACK f, void * data);
+ PARSER(CALLBACK f, void * data, const std::string & encoding);
virtual ~PARSER();
int ParseStart(const char * el, const char ** attr);
void ParseEnd(const char * el);
+ void Failure(const std::string & reason) { callback(false, reason, info, data); }
private:
PROPERTY_PARSERS propertyParsers;
CALLBACK callback;
void * data;
+ std::string encoding;
INFO info;
int depth;
bool parsingAnswer;
std::string error;
void ParseAdmin(const char * el, const char ** attr);
- void ParseAdminParams(const char * el, const char ** attr);
+ //void ParseAdminParams(const char * el, const char ** attr);
};
} // namespace GET_ADMIN
public:
typedef std::vector<typename ELEMENT_PARSER::INFO> INFO;
typedef void (* CALLBACK)(bool result, const std::string & reason, const INFO & info, void * data);
- PARSER(const std::string & t, CALLBACK f, void * d)
- : tag(t), callback(f), data(d),
- elementParser(&PARSER<ELEMENT_PARSER>::ElementCallback, this),
+ PARSER(const std::string & t, CALLBACK f, void * d, const std::string & e)
+ : tag(t), callback(f), data(d), encoding(e),
+ elementParser(&PARSER<ELEMENT_PARSER>::ElementCallback, this, e),
depth(0), parsingAnswer(false)
{}
int ParseStart(const char * el, const char ** attr)
parsingAnswer = false;
}
}
+ void Failure(const std::string & reason) { callback(false, reason, info, data); }
private:
std::string tag;
CALLBACK callback;
void * data;
+ std::string encoding;
ELEMENT_PARSER elementParser;
INFO info;
int depth;
using namespace STG;
-GET_CORP::PARSER::PARSER(CALLBACK f, void * d)
+GET_CORP::PARSER::PARSER(CALLBACK f, void * d, const std::string & e)
: callback(f),
data(d),
+ encoding(e),
depth(0),
parsingAnswer(false)
{
//-----------------------------------------------------------------------------
void GET_CORP::PARSER::ParseCorpParams(const char * el, const char ** attr)
{
-if (!TryParse(propertyParsers, ToLower(el), attr))
+if (!TryParse(propertyParsers, ToLower(el), attr, encoding))
error = "Invalid parameter.";
}
public:
typedef GET_CORP::INFO INFO;
- PARSER(CALLBACK f, void * data);
+ PARSER(CALLBACK f, void * data, const std::string & encoding);
virtual ~PARSER();
int ParseStart(const char * el, const char ** attr);
void ParseEnd(const char * el);
+ void Failure(const std::string & reason) { callback(false, reason, info, data); }
private:
PROPERTY_PARSERS propertyParsers;
CALLBACK callback;
void * data;
INFO info;
+ std::string encoding;
int depth;
bool parsingAnswer;
std::string error;
using namespace STG;
-GET_SERVICE::PARSER::PARSER(CALLBACK f, void * d)
+GET_SERVICE::PARSER::PARSER(CALLBACK f, void * d, const std::string & e)
: callback(f),
data(d),
+ encoding(e),
depth(0),
parsingAnswer(false)
{
AddParser(propertyParsers, "name", info.name);
- AddParser(propertyParsers, "comment", info.comment);
+ AddParser(propertyParsers, "comment", info.comment, GetEncodedValue);
AddParser(propertyParsers, "cost", info.cost);
AddParser(propertyParsers, "payDay", info.payDay);
}
//-----------------------------------------------------------------------------
void GET_SERVICE::PARSER::ParseServiceParams(const char * el, const char ** attr)
{
-if (!TryParse(propertyParsers, ToLower(el), attr))
+if (!TryParse(propertyParsers, ToLower(el), attr, encoding))
error = "Invalid parameter.";
}
{
public:
typedef GET_SERVICE::INFO INFO;
- PARSER(CALLBACK f, void * data);
+ PARSER(CALLBACK f, void * data, const std::string & encoding);
virtual ~PARSER();
int ParseStart(const char * el, const char ** attr);
void ParseEnd(const char * el);
+ void Failure(const std::string & reason) { callback(false, reason, info, data); }
private:
PROPERTY_PARSERS propertyParsers;
CALLBACK callback;
void * data;
INFO info;
+ std::string encoding;
int depth;
bool parsingAnswer;
std::string error;
public:
typedef bool (* FUNC)(const char **, A &, T A::value_type:: *);
AOS_PARSER(A & a, T A::value_type:: * fld, FUNC f) : array(a), field(fld), func(f) {}
- virtual bool Parse(const char ** attr) { return func(attr, array, field); }
+ virtual bool Parse(const char ** attr, const std::string & /*attrName*/, const std::string & /*fromEncoding*/) { return func(attr, array, field); }
private:
A & array;
T A::value_type:: * field;
parsers.insert(std::make_pair(ToLower(name), new AOS_PARSER<A, T>(array, field, func)));
}
-bool GetTimeSpan(const char ** attr, DIRPRICE_DATA & value)
+bool GetTimeSpan(const char ** attr, DIRPRICE_DATA & value, const std::string & attrName)
{
int hb = 0;
int mb = 0;
int he = 0;
int me = 0;
-if (CheckValue(attr))
+if (CheckValue(attr, attrName))
if (ParseTariffTimeStr(attr[1], hb, mb, he, me) == 0)
{
value.hDay = hb;
}
template <typename T>
-bool GetTraffType(const char ** attr, T & value)
+bool GetTraffType(const char ** attr, T & value, const std::string & attrName)
{
-if (!CheckValue(attr))
+if (!CheckValue(attr, attrName))
return false;
std::string type(attr[1]);
if (type == "up")
return true;
}
+template <typename T>
+bool GetPeriod(const char ** attr, T & value, const std::string & attrName)
+{
+if (!CheckValue(attr, attrName))
+ return false;
+std::string type(attr[1]);
+if (type == "day")
+ value = TARIFF::DAY;
+else if (type == "month")
+ value = TARIFF::MONTH;
+else
+ return false;
+return true;
+}
+
template <typename A, typename T>
bool GetSlashedValue(const char ** attr, A & array, T A::value_type:: * field)
{
-if (!CheckValue(attr))
+if (!CheckValue(attr, "value"))
return false;
const char * start = attr[1];
size_t item = 0;
} // namespace anonymous
-GET_TARIFF::PARSER::PARSER(CALLBACK f, void * d)
+GET_TARIFF::PARSER::PARSER(CALLBACK f, void * d, const std::string & e)
: callback(f),
data(d),
+ encoding(e),
depth(0),
parsingAnswer(false)
{
AddParser(propertyParsers, "passiveCost", info.tariffConf.passiveCost);
AddParser(propertyParsers, "free", info.tariffConf.free);
AddParser(propertyParsers, "traffType", info.tariffConf.traffType, GetTraffType);
+ AddParser(propertyParsers, "period", info.tariffConf.period, GetPeriod);
for (size_t i = 0; i < DIR_NUM; ++i)
AddParser(propertyParsers, "time" + unsigned2str(i), info.dirPrice[i], GetTimeSpan);
AddAOSParser(propertyParsers, "priceDayA", info.dirPrice, &DIRPRICE_DATA::priceDayA, GetSlashedValue);
error = "Tariff not found.";
}
else
+ {
parsingAnswer = true;
+ if (strcasecmp(attr[0], "name") == 0)
+ info.tariffConf.name = attr[1];
+ }
}
else
parsingAnswer = true;
//-----------------------------------------------------------------------------
void GET_TARIFF::PARSER::ParseTariffParams(const char * el, const char ** attr)
{
-if (!TryParse(propertyParsers, ToLower(el), attr))
- error = "Invalid parameter.";
+if (!TryParse(propertyParsers, ToLower(el), attr, encoding))
+ error = std::string("Invalid parameter '") + el + "'.";
}
public:
typedef GET_TARIFF::INFO INFO;
- PARSER(CALLBACK f, void * data);
+ PARSER(CALLBACK f, void * data, const std::string & encoding);
virtual ~PARSER();
int ParseStart(const char * el, const char ** attr);
void ParseEnd(const char * el);
+ void Failure(const std::string & reason) { callback(false, reason, info, data); }
private:
PROPERTY_PARSERS propertyParsers;
CALLBACK callback;
void * data;
+ std::string encoding;
INFO info;
int depth;
bool parsingAnswer;
{
template <>
-bool GetValue<GET_USER::STAT>(const char ** attr, GET_USER::STAT & value)
+bool GetValue<GET_USER::STAT>(const char ** attr, GET_USER::STAT & value, const std::string & /*attrName*/)
{
if (!attr)
return false;
}
-GET_USER::PARSER::PARSER(CALLBACK f, void * d)
+GET_USER::PARSER::PARSER(CALLBACK f, void * d, const std::string & e)
: callback(f),
data(d),
+ encoding(e),
depth(0),
parsingAnswer(false)
{
AddParser(propertyParsers, "cash", info.cash);
AddParser(propertyParsers, "credit", info.credit);
AddParser(propertyParsers, "creditExpire", info.creditExpire);
- AddParser(propertyParsers, "lastCash", info.lastCash);
- AddParser(propertyParsers, "prepaidTraff", info.prepaidTraff);
- AddParser(propertyParsers, "down", info.down);
+ AddParser(propertyParsers, "lastCash", info.lastCashAdd);
+ AddParser(propertyParsers, "lastTimeCash", info.lastCashAddTime);
+ AddParser(propertyParsers, "freeMb", info.prepaidTraff);
+ AddParser(propertyParsers, "down", info.disabled);
AddParser(propertyParsers, "passive", info.passive);
AddParser(propertyParsers, "disableDetailStat", info.disableDetailStat);
- AddParser(propertyParsers, "connected", info.connected);
+ AddParser(propertyParsers, "status", info.connected);
AddParser(propertyParsers, "aonline", info.alwaysOnline);
AddParser(propertyParsers, "currIP", info.ip, GetIPValue);
AddParser(propertyParsers, "ip", info.ips);
AddParser(propertyParsers, "tariff", info.tariff);
- AddParser(propertyParsers, "group", info.group, GetEncodedValue);
- AddParser(propertyParsers, "note", info.note, GetEncodedValue);
- AddParser(propertyParsers, "email", info.email, GetEncodedValue);
- AddParser(propertyParsers, "name", info.name, GetEncodedValue);
- AddParser(propertyParsers, "address", info.address, GetEncodedValue);
- AddParser(propertyParsers, "phone", info.phone, GetEncodedValue);
+ AddParser(propertyParsers, "group", info.group, "koi8-ru", GetEncodedValue);
+ AddParser(propertyParsers, "note", info.note, "koi8-ru", GetEncodedValue);
+ AddParser(propertyParsers, "email", info.email, "koi8-ru", GetEncodedValue);
+ AddParser(propertyParsers, "name", info.name, "koi8-ru", GetEncodedValue);
+ AddParser(propertyParsers, "address", info.address, "koi8-ru", GetEncodedValue);
+ AddParser(propertyParsers, "phone", info.phone, "cp1251", GetEncodedValue);
+ AddParser(propertyParsers, "corp", info.corp);
AddParser(propertyParsers, "traff", info.stat);
+ AddParser(propertyParsers, "pingTime", info.pingTime);
+ AddParser(propertyParsers, "lastActivityTime", info.lastActivityTime);
for (size_t i = 0; i < USERDATA_NUM; ++i)
- AddParser(propertyParsers, "userData" + unsigned2str(i), info.userData[i], GetEncodedValue);
+ AddParser(propertyParsers, "userData" + unsigned2str(i), info.userData[i], "koi8-ru", GetEncodedValue);
}
//-----------------------------------------------------------------------------
GET_USER::PARSER::~PARSER()
if (depth == 2 && parsingAnswer)
ParseUserParams(el, attr);
+if (depth == 3 && parsingAnswer)
+ {
+ ParseAuthBy(el, attr);
+ ParseServices(el, attr);
+ }
+
return 0;
}
//-----------------------------------------------------------------------------
else
error = "User not found.";
}
- else
- parsingAnswer = true;
+ else if (strcasecmp(attr[0], "login") == 0 && attr[1])
+ info.login = attr[1];
}
- else
- parsingAnswer = true;
+ parsingAnswer = true;
}
}
//-----------------------------------------------------------------------------
void GET_USER::PARSER::ParseUserParams(const char * el, const char ** attr)
{
-if (!TryParse(propertyParsers, ToLower(el), attr))
+if (strcasecmp(el, "AuthorizedBy") != 0 &&
+ !TryParse(propertyParsers, ToLower(el), attr, encoding))
error = "Invalid parameter.";
+else if (strcasecmp(el, "Services") != 0 &&
+ !TryParse(propertyParsers, ToLower(el), attr, encoding))
+ error = "Invalid parameter.";
+}
+//-----------------------------------------------------------------------------
+void GET_USER::PARSER::ParseAuthBy(const char * el, const char ** attr)
+{
+if (strcasecmp(el, "Auth") == 0 &&
+ attr && attr[0] && attr[1] &&
+ strcasecmp(attr[0], "name") == 0)
+ info.authBy.push_back(attr[1]);
+}
+//-----------------------------------------------------------------------------
+void GET_USER::PARSER::ParseServices(const char * el, const char ** attr)
+{
+if (strcasecmp(el, "Service") == 0 &&
+ attr && attr[0] && attr[1] &&
+ strcasecmp(attr[0], "name") == 0)
+ info.services.push_back(attr[1]);
}
public:
typedef GET_USER::INFO INFO;
- PARSER(CALLBACK f, void * data);
+ PARSER(CALLBACK f, void * data, const std::string & encoding);
virtual ~PARSER();
int ParseStart(const char * el, const char ** attr);
void ParseEnd(const char * el);
+ void Failure(const std::string & reason) { callback(false, reason, info, data); }
private:
PROPERTY_PARSERS propertyParsers;
CALLBACK callback;
void * data;
+ std::string encoding;
INFO info;
int depth;
bool parsingAnswer;
void ParseUser(const char * el, const char ** attr);
void ParseUserParams(const char * el, const char ** attr);
+ void ParseAuthBy(const char * el, const char ** attr);
+ void ParseServices(const char * el, const char ** attr);
};
} // namespace GET_USER
#include <strings.h>
-bool STG::CheckValue(const char ** attr)
+bool STG::CheckValue(const char ** attr, const std::string & attrName)
{
-return attr && attr[0] && attr[1] && strcasecmp(attr[0], "value") == 0;
+return attr && attr[0] && attr[1] && strcasecmp(attr[0], attrName.c_str()) == 0;
}
-bool STG::GetEncodedValue(const char ** attr, std::string & value)
+bool STG::GetEncodedValue(const char ** attr, std::string & value, const std::string & attrName)
{
-if (!CheckValue(attr))
+if (!CheckValue(attr, attrName))
return false;
Decode21str(value, attr[1]);
return true;
}
-bool STG::GetIPValue(const char ** attr, uint32_t & value)
+bool STG::GetIPValue(const char ** attr, uint32_t & value, const std::string & attrName)
{
-if (!CheckValue(attr))
+if (!CheckValue(attr, attrName))
return false;
std::string ip(attr[1]);
value = inet_strington(attr[1]);
return true;
}
-bool STG::TryParse(PROPERTY_PARSERS & parsers, const std::string & name, const char ** attr)
+bool STG::TryParse(PROPERTY_PARSERS & parsers, const std::string & name, const char ** attr, const std::string & toEncoding, const std::string & attrName)
{
PROPERTY_PARSERS::iterator it(parsers.find(name));
if (it != parsers.end())
- return it->second->Parse(attr);
+ return it->second->Parse(attr, attrName, toEncoding);
return true; // Assume that non-existing params are ok.
}
{
public:
virtual ~BASE_PROPERTY_PARSER() {}
- virtual bool Parse(const char ** attr) = 0;
+ virtual bool Parse(const char ** attr, const std::string & attrName, const std::string & fromEncoding) = 0;
};
template <typename T>
class PROPERTY_PARSER : public BASE_PROPERTY_PARSER
{
public:
- typedef bool (* FUNC)(const char **, T &);
+ typedef bool (* FUNC)(const char **, T &, const std::string &);
PROPERTY_PARSER(T & v, FUNC f) : value(v), func(f) {}
- virtual bool Parse(const char ** attr) { return func(attr, value); }
+ PROPERTY_PARSER(T & v, FUNC f, const std::string & e) : value(v), func(f), encoding(e) {}
+ virtual bool Parse(const char ** attr, const std::string & attrName, const std::string & /*fromEncoding*/) { return func(attr, value, attrName); }
private:
T & value;
FUNC func;
+ std::string encoding;
};
+template <>
+inline
+bool PROPERTY_PARSER<std::string>::Parse(const char ** attr, const std::string & attrName, const std::string & toEncoding)
+{
+if (!encoding.empty() && !toEncoding.empty())
+ {
+ std::string tmp;
+ if (!func(attr, tmp, attrName))
+ return false;
+ value = IconvString(tmp, encoding, toEncoding);
+ return true;
+ }
+else
+ return func(attr, value, attrName);
+}
+
typedef std::map<std::string, BASE_PROPERTY_PARSER *> PROPERTY_PARSERS;
-bool CheckValue(const char ** attr);
+bool CheckValue(const char ** attr, const std::string & attrName);
template <typename T>
inline
-bool GetValue(const char ** attr, T & value)
+bool GetValue(const char ** attr, T & value, const std::string & attrName)
{
-if (CheckValue(attr))
+if (CheckValue(attr, attrName))
if (str2x(attr[1], value) < 0)
return false;
return true;
template <>
inline
-bool GetValue<std::string>(const char ** attr, std::string & value)
+bool GetValue<std::string>(const char ** attr, std::string & value, const std::string & attrName)
{
-if (!CheckValue(attr))
+if (!CheckValue(attr, attrName))
return false;
value = attr[1];
return true;
template <>
inline
-bool GetValue<double>(const char ** attr, double & value)
+bool GetValue<double>(const char ** attr, double & value, const std::string & attrName)
{
-if (CheckValue(attr))
+if (CheckValue(attr, attrName))
if (strtodouble2(attr[1], value))
return false;
return true;
}
-bool GetEncodedValue(const char ** attr, std::string & value);
+bool GetEncodedValue(const char ** attr, std::string & value, const std::string & attrName);
-bool GetIPValue(const char ** attr, uint32_t& value);
+bool GetIPValue(const char ** attr, uint32_t& value, const std::string & attrName);
template <typename T>
-void AddParser(PROPERTY_PARSERS & parsers, const std::string & name, T & value, const typename PROPERTY_PARSER<T>::FUNC & func = GetValue<T>);
+inline
+void AddParser(PROPERTY_PARSERS & parsers, const std::string & name, T & value, const typename PROPERTY_PARSER<T>::FUNC & func = GetValue<T>)
+{
+ parsers.insert(std::make_pair(ToLower(name), new PROPERTY_PARSER<T>(value, func)));
+}
template <typename T>
inline
-void AddParser(PROPERTY_PARSERS & parsers, const std::string & name, T & value, const typename PROPERTY_PARSER<T>::FUNC & func)
+void AddParser(PROPERTY_PARSERS & parsers, const std::string & name, T & value, const std::string & toEncoding, const typename PROPERTY_PARSER<T>::FUNC & func = GetValue<T>)
{
- parsers.insert(std::make_pair(ToLower(name), new PROPERTY_PARSER<T>(value, func)));
+ parsers.insert(std::make_pair(ToLower(name), new PROPERTY_PARSER<T>(value, func, toEncoding)));
}
-bool TryParse(PROPERTY_PARSERS & parsers, const std::string & name, const char ** attr);
+bool TryParse(PROPERTY_PARSERS & parsers, const std::string & name, const char ** attr, const std::string & fromEncoding, const std::string & attrName = "value");
} // namespace STG
#define __STG_STGLIBS_SRVCONF_RESETABLE_UTILS_H__
#include "stg/resetable.h"
+#include "stg/common.h"
#include <string>
#include <ostream>
{
template <typename T>
+inline
void appendResetable(std::ostream & stream, const std::string & name, const T & value)
{
if (!value.empty())
}
template <typename T>
+inline
void appendResetable(std::ostream & stream, const std::string & name, size_t suffix, const T & value)
{
if (!value.empty())
stream << "<" << name << suffix << " value=\"" << value.data() << "\"/>";
}
+inline
+RESETABLE<std::string> MaybeEncode(const RESETABLE<std::string> & value)
+{
+RESETABLE<std::string> res;
+if (!value.empty())
+ res = Encode12str(value.data());
+return res;
+}
+
+inline
+RESETABLE<std::string> MaybeIconv(const RESETABLE<std::string> & value, const std::string & fromEncoding, const std::string & toEncoding)
+{
+RESETABLE<std::string> res;
+if (!value.empty())
+ res = IconvString(value.data(), fromEncoding, toEncoding);
+return res;
+}
+
} // namespace STG
#endif
}
-SERVER_INFO::PARSER::PARSER(CALLBACK f, void * d)
+SERVER_INFO::PARSER::PARSER(CALLBACK f, void * d, const std::string & e)
: callback(f),
data(d),
+ encoding(e),
depth(0),
parsingAnswer(false)
{
else
{
if (depth == 2 && parsingAnswer)
- if (!TryParse(propertyParsers, ToLower(el), attr))
+ if (!TryParse(propertyParsers, ToLower(el), attr, encoding))
error = "Invalid parameter.";
}
return 0;
class PARSER: public STG::PARSER
{
public:
- PARSER(CALLBACK f, void * data);
+ PARSER(CALLBACK f, void * data, const std::string & encoding);
int ParseStart(const char * el, const char ** attr);
void ParseEnd(const char * el);
+ void Failure(const std::string & reason) { callback(false, reason, info, data); }
private:
PROPERTY_PARSERS propertyParsers;
CALLBACK callback;
void * data;
+ std::string encoding;
int depth;
bool parsingAnswer;
INFO info;
using namespace STG;
-SIMPLE::PARSER::PARSER(const std::string & t, CALLBACK f, void * d)
+SIMPLE::PARSER::PARSER(const std::string & t, CALLBACK f, void * d, const std::string & e)
: tag(t),
callback(f),
data(d),
+ encoding(e),
depth(0)
{
}
class PARSER: public STG::PARSER
{
public:
- PARSER(const std::string & tag, CALLBACK f, void * data);
+ PARSER(const std::string & tag, CALLBACK f, void * data, const std::string & encoding);
int ParseStart(const char * el, const char ** attr);
void ParseEnd(const char * el);
+ void Failure(const std::string & reason) { callback(false, reason, data); }
private:
std::string tag;
CALLBACK callback;
void * data;
+ std::string encoding;
int depth;
void ParseAnswer(const char * el, const char ** attr);
#include <cstdio>
#include <cstring>
+#include <clocale>
#include <expat.h>
+#include <langinfo.h>
using namespace STG;
public:
IMPL(const std::string & server, uint16_t port,
const std::string & login, const std::string & password);
+ IMPL(const std::string & server, uint16_t port,
+ const std::string & localAddress, uint16_t localPort,
+ const std::string & login, const std::string & password);
~IMPL() { XML_ParserFree(parser); }
const std::string & GetStrError() const;
template <class P, typename C>
int Exec(const std::string & request, C callback, void * data)
{
- P cp(callback, data);
+ P cp(callback, data, encoding);
return ExecImpl(request, cp);
}
template <class P, typename C>
int Exec(const std::string & tag, const std::string & request, C callback, void * data)
{
- P cp(tag, callback, data);
+ P cp(tag, callback, data, encoding);
return ExecImpl(request, cp);
}
+ const std::string & Encoding() const { return encoding; }
+
private:
NETTRANSACT nt;
+ std::string encoding;
std::string errorMsg;
XML_Parser parser;
{
}
+SERVCONF::SERVCONF(const std::string & server, uint16_t port,
+ const std::string & localAddress, uint16_t localPort,
+ const std::string & login, const std::string & password)
+ : pImpl(new IMPL(server, port, localAddress, localPort, login, password))
+{
+}
+
SERVCONF::~SERVCONF()
{
delete pImpl;
int SERVCONF::ChgAdmin(const ADMIN_CONF_RES & conf, SIMPLE::CALLBACK f, void * data)
{
-return pImpl->Exec<SIMPLE::PARSER>("ChgAdmin", "<ChgAdmin" + CHG_ADMIN::Serialize(conf) + "/>", f, data);
+return pImpl->Exec<SIMPLE::PARSER>("ChgAdmin", "<ChgAdmin" + CHG_ADMIN::Serialize(conf, pImpl->Encoding()) + "/>", f, data);
}
int SERVCONF::AddAdmin(const std::string & login,
int res = pImpl->Exec<SIMPLE::PARSER>("AddAdmin", "<AddAdmin login=\"" + login + "\"/>", f, data);
if (res != st_ok)
return res;
-return pImpl->Exec<SIMPLE::PARSER>("ChgAdmin", "<ChgAdmin" + CHG_ADMIN::Serialize(conf) + "/>", f, data);
+return pImpl->Exec<SIMPLE::PARSER>("ChgAdmin", "<ChgAdmin" + CHG_ADMIN::Serialize(conf, pImpl->Encoding()) + "/>", f, data);
}
int SERVCONF::DelAdmin(const std::string & login, SIMPLE::CALLBACK f, void * data)
int SERVCONF::ChgTariff(const TARIFF_DATA_RES & tariffData, SIMPLE::CALLBACK f, void * data)
{
-return pImpl->Exec<SIMPLE::PARSER>("SetTariff", "<SetTariff name=\"" + tariffData.tariffConf.name.data() + "\">" + CHG_TARIFF::Serialize(tariffData) + "</SetTariff>", f, data);
+return pImpl->Exec<SIMPLE::PARSER>("SetTariff", "<SetTariff name=\"" + tariffData.tariffConf.name.data() + "\">" + CHG_TARIFF::Serialize(tariffData, pImpl->Encoding()) + "</SetTariff>", f, data);
}
int SERVCONF::AddTariff(const std::string & name,
int res = pImpl->Exec<SIMPLE::PARSER>("AddTariff", "<AddTariff name=\"" + name + "\"/>", f, data);
if (res != st_ok)
return res;
-return pImpl->Exec<SIMPLE::PARSER>("SetTariff", "<SetTariff name=\"" + name + "\">" + CHG_TARIFF::Serialize(tariffData) + "</SetTariff>", f, data);
+return pImpl->Exec<SIMPLE::PARSER>("SetTariff", "<SetTariff name=\"" + name + "\">" + CHG_TARIFF::Serialize(tariffData, pImpl->Encoding()) + "</SetTariff>", f, data);
}
int SERVCONF::DelTariff(const std::string & name, SIMPLE::CALLBACK f, void * data)
const USER_STAT_RES & stat,
SIMPLE::CALLBACK f, void * data)
{
-return pImpl->Exec<CHG_USER::PARSER>("<SetUser><Login value=\"" + login + "\"/>" + CHG_USER::Serialize(conf, stat) + "</SetUser>", f, data);
+return pImpl->Exec<CHG_USER::PARSER>("<SetUser><Login value=\"" + login + "\"/>" + CHG_USER::Serialize(conf, stat, pImpl->Encoding()) + "</SetUser>", f, data);
}
int SERVCONF::DelUser(const std::string & login, SIMPLE::CALLBACK f, void * data)
return pImpl->Exec<SIMPLE::PARSER>("DelUser", "<DelUser login=\"" + login + "\"/>", f, data);
}
-int SERVCONF::AddUser(const std::string & login, SIMPLE::CALLBACK f, void * data)
+int SERVCONF::AddUser(const std::string & login,
+ const USER_CONF_RES & conf,
+ const USER_STAT_RES & stat,
+ SIMPLE::CALLBACK f, void * data)
{
-return pImpl->Exec<SIMPLE::PARSER>("AddUser", "<AddUser><Login value=\"" + login + "\"/></AddUser>", f, data);
+int res = pImpl->Exec<SIMPLE::PARSER>("AddUser", "<AddUser><Login value=\"" + login + "\"/></AddUser>", f, data);
+if (res != st_ok)
+ return res;
+return pImpl->Exec<CHG_USER::PARSER>("<SetUser><Login value=\"" + login + "\"/>" + CHG_USER::Serialize(conf, stat, pImpl->Encoding()) + "</SetUser>", f, data);
}
int SERVCONF::AuthBy(const std::string & login, AUTH_BY::CALLBACK f, void * data)
int SERVCONF::SendMessage(const std::string & login, const std::string & text, SIMPLE::CALLBACK f, void * data)
{
-return pImpl->Exec<SIMPLE::PARSER>("SendMessage", "<Message login=\"" + login + "\" msgver=\"1\" msgtype=\"1\" repeat=\"0\" repeatperiod=\"0\" showtime=\"0\" text=\"" + Encode12str(text) + "\"/>", f, data);
+return pImpl->Exec<SIMPLE::PARSER>("SendMessageResult", "<Message login=\"" + login + "\" msgver=\"1\" msgtype=\"1\" repeat=\"0\" repeatperiod=\"0\" showtime=\"0\" text=\"" + Encode12str(text) + "\"/>", f, data);
}
int SERVCONF::CheckUser(const std::string & login, const std::string & password, SIMPLE::CALLBACK f, void * data)
int SERVCONF::ChgService(const SERVICE_CONF_RES & conf, SIMPLE::CALLBACK f, void * data)
{
-return pImpl->Exec<SIMPLE::PARSER>("SetService", "<SetService name=\"" + conf.name.data() + "\">" + CHG_SERVICE::Serialize(conf) + "</SetService>", f, data);
+return pImpl->Exec<SIMPLE::PARSER>("SetService", "<SetService name=\"" + conf.name.data() + "\">" + CHG_SERVICE::Serialize(conf, pImpl->Encoding()) + "</SetService>", f, data);
}
int SERVCONF::AddService(const std::string & name,
int res = pImpl->Exec<SIMPLE::PARSER>("AddService", "<AddService name=\"" + name + "\"/>", f, data);
if (res != st_ok)
return res;
-return pImpl->Exec<SIMPLE::PARSER>("SetService", "<SetService name=\"" + name + "\">" + CHG_SERVICE::Serialize(conf) + "</SetService>", f, data);
+return pImpl->Exec<SIMPLE::PARSER>("SetService", "<SetService name=\"" + name + "\">" + CHG_SERVICE::Serialize(conf, pImpl->Encoding()) + "</SetService>", f, data);
}
int SERVCONF::DelService(const std::string & name, SIMPLE::CALLBACK f, void * data)
int SERVCONF::ChgCorp(const CORP_CONF_RES & conf, SIMPLE::CALLBACK f, void * data)
{
-return pImpl->Exec<SIMPLE::PARSER>("SetCorp", "<SetCorp name=\"" + conf.name.data() + "\">" + CHG_CORP::Serialize(conf) + "</SetCorp>", f, data);
+return pImpl->Exec<SIMPLE::PARSER>("SetCorp", "<SetCorp name=\"" + conf.name.data() + "\">" + CHG_CORP::Serialize(conf, pImpl->Encoding()) + "</SetCorp>", f, data);
}
int SERVCONF::AddCorp(const std::string & name,
int res = pImpl->Exec<SIMPLE::PARSER>("AddCorp", "<AddCorp name=\"" + name + "\"/>", f, data);
if (res != st_ok)
return res;
-return pImpl->Exec<SIMPLE::PARSER>("SetCorp", "<SetCorp name=\"" + name + "\">" + CHG_CORP::Serialize(conf) + "</SetCorp>", f, data);
+return pImpl->Exec<SIMPLE::PARSER>("SetCorp", "<SetCorp name=\"" + name + "\">" + CHG_CORP::Serialize(conf, pImpl->Encoding()) + "</SetCorp>", f, data);
}
int SERVCONF::DelCorp(const std::string & name, SIMPLE::CALLBACK f, void * data)
//-----------------------------------------------------------------------------
SERVCONF::IMPL::IMPL(const std::string & server, uint16_t port,
const std::string & login, const std::string & password)
- : nt( server, port, login, password )
+ : nt(server, port, login, password)
+{
+setlocale(LC_ALL, "");
+encoding = nl_langinfo(CODESET);
+parser = XML_ParserCreate(NULL);
+}
+//-----------------------------------------------------------------------------
+SERVCONF::IMPL::IMPL(const std::string & server, uint16_t port,
+ const std::string & localAddress, uint16_t localPort,
+ const std::string & login, const std::string & password)
+ : nt(server, port, localAddress, localPort, login, password)
{
+setlocale(LC_ALL, "");
+encoding = nl_langinfo(CODESET);
parser = XML_ParserCreate(NULL);
}
//-----------------------------------------------------------------------------
if ((ret = nt.Connect()) != st_ok)
{
errorMsg = nt.GetError();
+ cp.Failure(errorMsg);
return ret;
}
if ((ret = nt.Transact(request, ParserRecv, this)) != st_ok)
{
errorMsg = nt.GetError();
+ cp.Failure(errorMsg);
return ret;
}