--- /dev/null
+*.[ao]
+*.so
+*.swp
+*.diff
+*.patch
+CVS*
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.2 2005/10/11 12:18:55 nobunaga Exp $
+###############################################################################
+
+#LIB_NAME = includes
+
+#INCS = *.h
+#include ../Makefile.in
+
+all:
+ echo hi
+
+install:
+ echo install
\ No newline at end of file
--- /dev/null
+ /*
+ $Revision: 1.9 $
+ $Date: 2010/09/10 05:02:08 $
+ $Author: faust $
+ */
+
+#ifndef ADMIN_CONF_H
+#define ADMIN_CONF_H
+
+#include <string>
+
+#include "os_int.h"
+
+#define ADM_LOGIN_LEN (32)
+#define ADM_PASSWD_LEN (32)
+//-----------------------------------------------------------------------------
+struct PRIV
+{
+ PRIV()
+ : userStat(0),
+ userConf(0),
+ userCash(0),
+ userPasswd(0),
+ userAddDel(0),
+ adminChg(0),
+ tariffChg(0)
+ {};
+ PRIV(uint16_t p)
+ : userStat((p & 0x0003) >> 0x00),
+ userConf((p & 0x000C) >> 0x02),
+ userCash((p & 0x0030) >> 0x04),
+ userPasswd((p & 0x00C0) >> 0x06),
+ userAddDel((p & 0x0300) >> 0x08),
+ adminChg((p & 0x0C00) >> 0x0A),
+ tariffChg((p & 0x3000) >> 0x0C)
+ {}
+
+ uint16_t ToInt() const;
+ void FromInt(uint16_t p);
+
+ uint16_t userStat;
+ uint16_t userConf;
+ uint16_t userCash;
+ uint16_t userPasswd;
+ uint16_t userAddDel;
+ uint16_t adminChg;
+ uint16_t tariffChg;
+};
+//-----------------------------------------------------------------------------
+struct ADMIN_CONF
+{
+ ADMIN_CONF()
+ : priv(),
+ login(),
+ password("* NO PASSWORD *")
+ {}
+ ADMIN_CONF(const ADMIN_CONF & rvalue)
+ : priv(rvalue.priv),
+ login(rvalue.login),
+ password(rvalue.password)
+ {}
+ ADMIN_CONF(const PRIV pr, const std::string & l, const std::string & p)
+ : priv(pr),
+ login(l),
+ password(p)
+ {}
+ PRIV priv;
+ std::string login;
+ std::string password;
+};
+//-----------------------------------------------------------------------------
+
+#include "admin_conf.inc.h"
+
+#endif
+
+
--- /dev/null
+ /*
+ $Revision: 1.1 $
+ $Date: 2010/09/10 01:45:24 $
+ $Author: faust $
+ */
+
+#ifndef ADMIN_CONF_INC_H
+#define ADMIN_CONF_INC_H
+
+inline
+uint16_t PRIV::ToInt() const
+{
+uint16_t p = (userStat << 0) |
+ (userConf << 2) |
+ (userCash << 4) |
+ (userPasswd << 6) |
+ (userAddDel << 8) |
+ (adminChg << 10) |
+ (tariffChg << 12);
+return p;
+}
+
+inline
+void PRIV::FromInt(uint16_t p)
+{
+userStat = (p & 0x0003) >> 0x00; // 1+2
+userConf = (p & 0x000C) >> 0x02; // 4+8
+userCash = (p & 0x0030) >> 0x04; // 10+20
+userPasswd = (p & 0x00C0) >> 0x06; // 40+80
+userAddDel = (p & 0x0300) >> 0x08; // 100+200
+adminChg = (p & 0x0C00) >> 0x0A; // 400+800
+tariffChg = (p & 0x3000) >> 0x0C; // 1000+2000
+}
+
+#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>
+ */
+
+ /*
+ $Revision: 1.6 $
+ $Date: 2009/03/18 17:24:57 $
+ */
+
+#ifndef BASE_AUTH_H
+#define BASE_AUTH_H
+
+#include <time.h>
+#include <string>
+
+#include "base_plugin.h"
+#include "stg_message.h"
+
+using namespace std;
+
+//-----------------------------------------------------------------------------
+class BASE_AUTH : public BASE_PLUGIN
+{
+public:
+ virtual ~BASE_AUTH() {};
+ virtual int SendMessage(const STG_MSG & msg, uint32_t ip) const = 0;
+};
+//-----------------------------------------------------------------------------
+#endif
+
+
--- /dev/null
+#ifndef __BASE_DB_H__
+#define __BASE_DB_H__
+
+#include <string>
+#include <vector>
+#include <map>
+
+class BASE_DB {
+public:
+
+ typedef std::map<std::string, std::string> TUPLE;
+ typedef std::vector<TUPLE> TUPLES;
+ typedef std::vector<std::string> COLUMNS;
+
+ BASE_DB() {};
+ BASE_DB(std::string & dbHost,
+ std::string & dbDatabase,
+ std::string & dbUser,
+ std::string & dbPassword)
+ : host(dbHost),
+ database(dbDatabase),
+ user(dbUser),
+ password(dbPassword)
+ {};
+ virtual ~BASE_DB() {};
+
+ void SetHost(const std::string & h) { host = h; };
+ void SetDatabase(const std::string & db) { database = db; };
+ void SetUser(const std::string & u) { user = u; };
+ void SetPassword(const std::string & p) { password = p; };
+
+ const std::string & GetHost() const { return host; };
+ const std::string & GetDatabase() const { return database; };
+ const std::string & GetUser() const { return user; };
+ const std::string & GetPassword() const { return password; };
+
+ const std::string & GetErrorMsg() const { return errorMsg; };
+
+ virtual bool Connect() { return true; };
+ virtual bool Disconnect() { return true; };
+ virtual bool Query(const std::string & q) { return true; };
+ virtual bool Start() { return true; };
+ virtual bool Commit() { return true; };
+ virtual bool Rollback() { return true; };
+
+ int GetTuples() const { return tuples; };
+ int GetColumns() const { return columns; };
+ int GetAffectedRows() const { return affected; };
+
+ virtual TUPLES GetResult() const { return TUPLES(); };
+ virtual TUPLE GetTuple(int n = 0) const { return TUPLE(); };
+ const COLUMNS & GetColumnsNames() const { return cols; };
+
+protected:
+ std::string host;
+ std::string database;
+ std::string user;
+ std::string password;
+
+ std::string errorMsg;
+
+ COLUMNS cols;
+
+ int columns;
+ int tuples;
+ int affected;
+};
+
+extern "C" BASE_DB * CreateDriver();
+extern "C" void DestroyDriver(BASE_DB *);
+
+typedef BASE_DB * (* CreateDriverFn)();
+typedef void (* DestroyDriverFn)(BASE_DB *);
+
+#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>
+ */
+
+/*
+ $Revision: 1.12 $
+ $Date: 2010/03/04 11:53:14 $
+ $Author: faust $
+*/
+
+
+#ifndef BASE_PLUGIN_H
+#define BASE_PLUGIN_H
+
+#include <string>
+#include "base_settings.h"
+#include "noncopyable.h"
+#include "os_int.h"
+
+using namespace std;
+
+class ADMINS;
+class USERS;
+class TARIFFS;
+class TRAFFCOUNTER;
+class SETTINGS;
+class BASE_STORE;
+
+//-----------------------------------------------------------------------------
+class BASE_PLUGIN : private NONCOPYABLE
+{
+public:
+ virtual ~BASE_PLUGIN(){};
+ virtual void SetUsers(USERS * u) = 0;
+ virtual void SetTariffs(TARIFFS * t) = 0;
+ virtual void SetAdmins(ADMINS * a) = 0;
+ virtual void SetTraffcounter(TRAFFCOUNTER * tc) = 0;
+ virtual void SetStore(BASE_STORE * st) = 0;
+ virtual void SetStgSettings(const SETTINGS * s) = 0;
+ virtual void SetSettings(const MODULE_SETTINGS & s) = 0;
+ virtual int ParseSettings() = 0;
+
+ virtual int Start() = 0;
+ virtual int Stop() = 0;
+ virtual int Reload() = 0;
+ virtual bool IsRunning() = 0;
+ virtual const string & GetStrError() const = 0;
+ virtual const string GetVersion() const = 0;
+ virtual uint16_t GetStartPosition() const = 0;
+ virtual uint16_t GetStopPosition() const = 0;
+};
+//-----------------------------------------------------------------------------
+#endif
+
+
--- /dev/null
+ /*
+ $Revision: 1.5 $
+ $Date: 2010/03/04 11:49:52 $
+ $Author: faust $
+ */
+
+#ifndef BASE_SETTINGS_H
+#define BASE_SETTINGS_H
+
+#include <string.h>
+#include <string>
+#include <vector>
+
+using namespace std;
+
+//-----------------------------------------------------------------------------
+struct PARAM_VALUE
+{
+ PARAM_VALUE()
+ : param(),
+ value()
+ {};
+ bool operator==(const PARAM_VALUE & rhs) const
+ { return !strcasecmp(param.c_str(), rhs.param.c_str()); };
+
+ bool operator<(const PARAM_VALUE & rhs) const
+ { return strcasecmp(param.c_str(), rhs.param.c_str()) < 0; };
+
+ string param;
+ vector<string> value;
+};
+//-----------------------------------------------------------------------------
+struct MODULE_SETTINGS
+{
+ MODULE_SETTINGS()
+ : moduleName(),
+ moduleParams()
+ {};
+ MODULE_SETTINGS(const MODULE_SETTINGS & rvalue)
+ : moduleName(rvalue.moduleName),
+ moduleParams(rvalue.moduleParams)
+ {};
+ bool operator==(const MODULE_SETTINGS & rhs) const
+ { return !strcasecmp(moduleName.c_str(), rhs.moduleName.c_str()); };
+
+ bool operator<(const MODULE_SETTINGS & rhs) const
+ { return strcasecmp(moduleName.c_str(), rhs.moduleName.c_str()) < 0; };
+
+string moduleName;
+vector<PARAM_VALUE> moduleParams;
+};
+//-----------------------------------------------------------------------------
+#endif //BASE_SETTINGS_H
+
+
--- /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>
+ */
+
+ /*
+ $Revision: 1.16 $
+ $Date: 2010/01/19 11:09:48 $
+ $Author: faust $
+ */
+
+#ifndef BASE_STORE_H
+#define BASE_STORE_H
+
+#include <string>
+#include <vector>
+#include <map>
+
+#include "user_stat.h"
+#include "user_conf.h"
+#include "corp_conf.h"
+#include "service_conf.h"
+#include "admin_conf.h"
+#include "tariff_conf.h"
+#include "base_settings.h"
+#include "stg_message.h"
+
+using namespace std;
+//-----------------------------------------------------------------------------
+class BASE_STORE
+{
+public:
+ virtual ~BASE_STORE(){};
+ virtual int GetUsersList(vector<string> * usersList) const = 0;
+ virtual int AddUser(const string & login) const = 0;
+ virtual int DelUser(const string & login) const = 0;
+ virtual int SaveUserStat(const USER_STAT & stat, const string & login) const = 0;
+ virtual int SaveUserConf(const USER_CONF & conf, const string & login) const = 0;
+ virtual int RestoreUserStat(USER_STAT * stat, const string & login) const = 0;
+ virtual int RestoreUserConf(USER_CONF * conf, const string & login) const = 0;
+
+ virtual int WriteUserChgLog(const string & login,
+ const string & admLogin,
+ uint32_t admIP,
+ const string & paramName,
+ const string & oldValue,
+ const string & newValue,
+ const string & message = "") const = 0;
+
+ virtual int WriteUserConnect(const string & login, uint32_t ip) const = 0;
+
+ virtual int WriteUserDisconnect(const string & login,
+ const DIR_TRAFF & up,
+ const DIR_TRAFF & down,
+ const DIR_TRAFF & sessionUp,
+ const DIR_TRAFF & sessionDown,
+ double cash,
+ double freeMb,
+ const std::string & reason) const = 0;
+
+ virtual int WriteDetailedStat(const map<IP_DIR_PAIR, STAT_NODE> * statTree,
+ time_t lastStat,
+ const string & login) const = 0;
+
+ virtual int AddMessage(STG_MSG * msg, const string & login) const = 0;
+ virtual int EditMessage(const STG_MSG & msg, const string & login) const = 0;
+ virtual int GetMessage(uint64_t id, STG_MSG * msg, const string & login) const = 0;
+ virtual int DelMessage(uint64_t id, const string & login) const = 0;
+ virtual int GetMessageHdrs(vector<STG_MSG_HDR> * hdrsList, const string & login) const = 0;
+
+
+ virtual int SaveMonthStat(const USER_STAT & stat, int month, int year, const string & login) const = 0;
+
+ virtual int GetAdminsList(vector<string> * adminsList) const = 0;
+ virtual int SaveAdmin(const ADMIN_CONF & ac) const = 0;
+ virtual int RestoreAdmin(ADMIN_CONF * ac, const string & login) const = 0;
+ virtual int AddAdmin(const string & login) const = 0;
+ virtual int DelAdmin(const string & login) const = 0;
+
+ virtual int GetTariffsList(vector<string> * tariffsList) const = 0;
+ virtual int AddTariff(const string & name) const = 0;
+ virtual int DelTariff(const string & name) const = 0;
+ virtual int SaveTariff(const TARIFF_DATA & td, const string & tariffName) const = 0;
+ virtual int RestoreTariff(TARIFF_DATA * td, const string & tariffName) const = 0;
+
+ virtual int GetCorpsList(vector<string> * corpsList) const = 0;
+ virtual int SaveCorp(const CORP_CONF & cc) const = 0;
+ virtual int RestoreCorp(CORP_CONF * cc, const string & name) const = 0;
+ virtual int AddCorp(const string & name) const = 0;
+ virtual int DelCorp(const string & name) const = 0;
+
+ virtual int GetServicesList(vector<string> * corpsList) const = 0;
+ virtual int SaveService(const SERVICE_CONF & sc) const = 0;
+ virtual int RestoreService(SERVICE_CONF * sc, const string & name) const = 0;
+ virtual int AddService(const string & name) const = 0;
+ virtual int DelService(const string & name) const = 0;
+
+ virtual void SetSettings(const MODULE_SETTINGS & s) = 0;
+ virtual int ParseSettings() = 0;
+ virtual const string & GetStrError() const = 0;
+ virtual const string & GetVersion() const = 0;
+};
+//-----------------------------------------------------------------------------
+
+#endif //BASE_STORE_H
+
--- /dev/null
+#ifndef CORP_CONF_H
+#define CORP_CONF_H
+
+struct CORP_CONF
+{
+string name;
+double cash;
+};
+
+#endif //CORP_CONF_H
--- /dev/null
+#ifndef PACKETH
+#define PACKETH
+
+#include "os_int.h"
+
+#define CONN_SYN_N 0
+#define CONN_SYN_ACK_N 1
+#define CONN_ACK_N 2
+#define ALIVE_SYN_N 3
+#define ALIVE_ACK_N 4
+#define DISCONN_SYN_N 5
+#define DISCONN_SYN_ACK_N 6
+#define DISCONN_ACK_N 7
+#define FIN_N 8
+#define ERROR_N 9
+#define INFO_N 10
+#define INFO_7_N 11
+#define INFO_8_N 12
+#define UPDATE_N 13
+
+#define DIR_NUM (10)
+
+#define IA_FREEMB_LEN (16)
+#define IA_LOGIN_LEN (32)
+#define IA_PASSWD_LEN (32)
+#define IA_MAX_TYPE_LEN (16)
+#define IA_MAX_MSG_LEN (235)
+#define IA_MAX_MSG_LEN_8 (1030)
+#define IA_DIR_NAME_LEN (16)
+#define IA_MAGIC_LEN (6)
+#define IA_PROTO_VER_LEN (2)
+
+#define ST_NOT_INETABLE (0)
+#define ST_INETABLE (1)
+
+#define IA_ID "00100"
+
+typedef int8_t string16[IA_DIR_NAME_LEN];
+//-----------------------------------------------------------------------------
+struct HDR_8
+{
+int8_t magic[IA_MAGIC_LEN];
+int8_t protoVer[IA_PROTO_VER_LEN];
+//uint32_t ip;
+//int8_t padding[4];
+};
+//-----------------------------------------------------------------------------
+struct CONN_SYN_6
+{
+int8_t magic[IA_MAGIC_LEN];
+int8_t protoVer[IA_PROTO_VER_LEN];
+int8_t loginS[IA_LOGIN_LEN];
+int32_t len; // Byte-order dependent
+int8_t type[IA_MAX_TYPE_LEN];
+int8_t login[IA_LOGIN_LEN];
+int8_t padding[2];
+};
+//-----------------------------------------------------------------------------
+struct CONN_SYN_8
+{
+HDR_8 hdr;
+int8_t loginS[IA_LOGIN_LEN];
+int32_t len; // Byte-order dependent
+int8_t type[IA_MAX_TYPE_LEN];
+int8_t login[IA_LOGIN_LEN];
+uint32_t dirs; // Byte-order dependent
+};
+//-----------------------------------------------------------------------------
+struct CONN_SYN_ACK_6
+{
+int32_t len; // Byte-order dependent
+int8_t type[IA_MAX_TYPE_LEN];
+uint32_t rnd; // Byte-order dependent
+int32_t userTimeOut; // Byte-order dependent
+int32_t aliveDelay; // Byte-order dependent
+string16 dirName[DIR_NUM];
+};
+//-----------------------------------------------------------------------------
+struct CONN_SYN_ACK_8
+{
+HDR_8 hdr;
+int32_t len; // Byte-order dependent
+int8_t type[IA_MAX_TYPE_LEN];
+uint32_t rnd; // Byte-order dependent
+int32_t userTimeOut; // Byte-order dependent
+int32_t aliveDelay; // Byte-order dependent
+string16 dirName[DIR_NUM];
+};
+//-----------------------------------------------------------------------------
+struct CONN_ACK_6
+{
+int8_t magic[IA_MAGIC_LEN];
+int8_t protoVer[IA_PROTO_VER_LEN];
+int8_t loginS[IA_LOGIN_LEN];
+int32_t len; // Byte-order dependent
+int8_t type[IA_MAX_TYPE_LEN];
+uint32_t rnd; // Byte-order dependent
+};
+//-----------------------------------------------------------------------------
+struct CONN_ACK_8
+{
+HDR_8 hdr;
+int8_t loginS[IA_LOGIN_LEN];
+int32_t len; // Byte-order dependent
+int8_t type[IA_MAX_TYPE_LEN];
+uint32_t rnd; // Byte-order dependent
+};
+//-----------------------------------------------------------------------------
+struct ALIVE_SYN_6
+{
+int32_t len; // Byte-order dependent
+int8_t type[IA_MAX_TYPE_LEN];
+uint32_t rnd; // Byte-order dependent
+
+int64_t mu[DIR_NUM]; // Byte-order dependent
+int64_t md[DIR_NUM]; // Byte-order dependent
+
+int64_t su[DIR_NUM]; // Byte-order dependent
+int64_t sd[DIR_NUM]; // Byte-order dependent
+
+int64_t cash; // Byte-order dependent
+
+int8_t freeMb[IA_FREEMB_LEN];
+};
+//-----------------------------------------------------------------------------
+struct ALIVE_SYN_8
+{
+HDR_8 hdr;
+int32_t len; // Byte-order dependent
+int8_t type[IA_MAX_TYPE_LEN];
+uint32_t rnd; // Byte-order dependent
+
+int64_t mu[DIR_NUM]; // Byte-order dependent
+int64_t md[DIR_NUM]; // Byte-order dependent
+
+int64_t su[DIR_NUM]; // Byte-order dependent
+int64_t sd[DIR_NUM]; // Byte-order dependent
+
+int64_t cash; // Äåíüãè óìíîæåííûå íà 1000 - Byte-order dependent
+int8_t freeMb[IA_FREEMB_LEN];
+
+uint32_t status; // Byte-order dependent
+int8_t padding[4];
+};
+//-----------------------------------------------------------------------------
+struct ALIVE_ACK_6
+{
+int8_t magic[IA_MAGIC_LEN];
+int8_t protoVer[IA_PROTO_VER_LEN];
+int8_t loginS[IA_LOGIN_LEN];
+int32_t len; // Byte-order dependent
+int8_t type[IA_MAX_TYPE_LEN];
+uint32_t rnd; // Byte-order dependent
+};
+//-----------------------------------------------------------------------------
+struct ALIVE_ACK_8
+{
+HDR_8 hdr;
+int8_t loginS[IA_LOGIN_LEN];
+int32_t len; // Byte-order dependent
+int8_t type[IA_MAX_TYPE_LEN];
+uint32_t rnd; // Byte-order dependent
+};
+//-----------------------------------------------------------------------------
+struct DISCONN_SYN_6
+{
+int8_t magic[IA_MAGIC_LEN];
+int8_t protoVer[IA_PROTO_VER_LEN];
+int8_t loginS[IA_LOGIN_LEN];
+int32_t len; // Byte-order dependent
+int8_t type[IA_MAX_TYPE_LEN];
+int8_t login[IA_LOGIN_LEN];
+int8_t padding[2];
+};
+//-----------------------------------------------------------------------------
+struct DISCONN_SYN_8
+{
+HDR_8 hdr;
+int8_t loginS[IA_LOGIN_LEN];
+int32_t len; // Byte-order dependent
+int8_t type[IA_MAX_TYPE_LEN];
+int8_t login[IA_LOGIN_LEN];
+int8_t padding[4];
+};
+//-----------------------------------------------------------------------------
+struct DISCONN_SYN_ACK_6
+{
+int32_t len; // Byte-order dependent
+int8_t type[IA_MAX_TYPE_LEN];
+uint32_t rnd; // Byte-order dependent
+};
+//-----------------------------------------------------------------------------
+struct DISCONN_SYN_ACK_8
+{
+HDR_8 hdr;
+int32_t len; // Byte-order dependent
+int8_t type[IA_MAX_TYPE_LEN];
+uint32_t rnd; // Byte-order dependent
+};
+//-----------------------------------------------------------------------------
+struct DISCONN_ACK_6
+{
+int8_t magic[IA_MAGIC_LEN];
+int8_t protoVer[IA_PROTO_VER_LEN];
+int8_t loginS[IA_LOGIN_LEN];
+int32_t len; // Byte-order dependent
+int8_t type[IA_MAX_TYPE_LEN];
+uint32_t rnd; // Byte-order dependent
+};
+//-----------------------------------------------------------------------------
+struct DISCONN_ACK_8
+{
+HDR_8 hdr;
+int8_t loginS[IA_LOGIN_LEN];
+int32_t len; // Byte-order dependent
+int8_t type[IA_MAX_TYPE_LEN];
+uint32_t rnd; // Byte-order dependent
+};
+//-----------------------------------------------------------------------------
+struct FIN_6
+{
+int32_t len; // Byte-order dependent
+int8_t type[IA_MAX_TYPE_LEN];
+int8_t ok[3];
+int8_t padding[1];
+};
+//-----------------------------------------------------------------------------
+struct FIN_8
+{
+HDR_8 hdr;
+int32_t len; // Byte-order dependent
+int8_t type[IA_MAX_TYPE_LEN];
+int8_t ok[3];
+int8_t padding[1];
+};
+//-----------------------------------------------------------------------------
+struct ERR
+{
+int32_t len; // Byte-order dependent
+int8_t type[IA_MAX_TYPE_LEN];
+int8_t text[236];
+};
+//-----------------------------------------------------------------------------
+struct ERR_8
+{
+HDR_8 hdr;
+int32_t len; // Byte-order dependent
+int8_t type[IA_MAX_TYPE_LEN];
+int8_t text[236];
+};
+//-----------------------------------------------------------------------------
+struct INFO_6
+{
+int32_t len; // Byte-order dependent
+int8_t type[IA_MAX_TYPE_LEN];
+int8_t infoType;
+int8_t text[IA_MAX_MSG_LEN];
+};
+//-----------------------------------------------------------------------------
+struct INFO_7
+{
+int32_t len; // Byte-order dependent
+int8_t type[IA_MAX_TYPE_LEN];
+int8_t infoType;
+uint32_t sendTime; // Byte-order dependent
+int8_t showTime;
+int8_t text[IA_MAX_MSG_LEN];
+int8_t padding[5];
+};
+//-----------------------------------------------------------------------------
+struct INFO_8
+{
+HDR_8 hdr;
+int32_t len; // Byte-order dependent
+int8_t type[IA_MAX_TYPE_LEN];
+int8_t infoType;
+uint32_t sendTime; // Byte-order dependent
+int8_t showTime;
+int8_t text[IA_MAX_MSG_LEN_8];
+};
+//-----------------------------------------------------------------------------
+struct LOADSTAT
+{
+int64_t mu[DIR_NUM]; // Byte-order dependent
+int64_t md[DIR_NUM]; // Byte-order dependent
+
+int64_t su[DIR_NUM]; // Byte-order dependent
+int64_t sd[DIR_NUM]; // Byte-order dependent
+
+int64_t cash; // Äåíüãè óìíîæåííûå íà 1000 - Byte-order dependent
+int8_t freeMb[IA_FREEMB_LEN];
+int32_t status; // Byte-order dependent
+};
+//-----------------------------------------------------------------------------
+#define CONN_SYN_7 CONN_SYN_6
+#define CONN_SYN_ACK_7 CONN_SYN_ACK_6
+#define CONN_ACK_7 CONN_ACK_6
+#define ALIVE_SYN_7 ALIVE_SYN_6
+#define ALIVE_ACK_7 ALIVE_ACK_6
+#define DISCONN_SYN_7 DISCONN_SYN_6
+#define DISCONN_SYN_ACK_7 DISCONN_SYN_ACK_6
+#define DISCONN_ACK_7 DISCONN_ACK_6
+#define FIN_7 FIN_6
+
+#endif
+
+
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: ibpp.h,v 1.3 2007/10/28 11:17:44 nobunaga Exp $\r
+// Subject : IBPP public header file. This is _the_ only file you include in\r
+// your application files when developing with IBPP.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+// Contributor(s):\r
+//\r
+// Olivier Mascia, main coding\r
+// Matt Hortman, initial linux port\r
+// Mark Jordan, design contributions\r
+// Maxim Abrashkin, enhancement patches\r
+// Torsten Martinsen, enhancement patches\r
+// Michael Hieke, darwin (OS X) port, enhancement patches\r
+// Val Samko, enhancement patches and debugging\r
+// Mike Nordell, invaluable C++ advices\r
+// Claudio Valderrama, help with not-so-well documented IB/FB features\r
+// Many others, excellent suggestions, bug finding, and support\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// Tabulations should be set every four characters when editing this file.\r
+//\r
+// When compiling a project using IBPP, the following defines should be made\r
+// on the command-line (or in makefiles) according to the OS platform and\r
+// compiler used.\r
+//\r
+// Select the platform: IBPP_WINDOWS | IBPP_LINUX | IBPP_DARWIN\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifndef __IBPP_H__\r
+#define __IBPP_H__\r
+\r
+#if !defined(IBPP_WINDOWS) && !defined(IBPP_LINUX) && !defined(IBPP_DARWIN)\r
+#error Please define IBPP_WINDOWS/IBPP_LINUX/IBPP_DARWIN before compiling !\r
+#endif\r
+\r
+#if !defined(__BCPLUSPLUS__) && !defined(__GNUC__) && !defined(_MSC_VER) && !defined(__DMC__)
+#error Your compiler is not recognized.\r
+#endif\r
+\r
+#if defined(IBPP_LINUX) || defined(IBPP_DARWIN)\r
+#define IBPP_UNIX // IBPP_UNIX stands as a common denominator to *NIX flavours\r
+#endif\r
+\r
+// IBPP is written for 32 bits systems or higher.\r
+// The standard type 'int' is assumed to be at least 32 bits.\r
+// And the standard type 'short' is assumed to be exactly 16 bits.\r
+// Everywhere possible, where the exact size of an integer does not matter,\r
+// the standard type 'int' is used. And where an exact integer size is required\r
+// the standard exact precision types definitions of C 99 standard are used.\r
+\r
+#if defined(_MSC_VER) || defined(__DMC__) || defined(__BCPLUSPLUS__)\r
+// C99 §7.18.1.1 Exact-width integer types (only those used by IBPP)\r
+#if defined(_MSC_VER) && (_MSC_VER < 1300) // MSVC 6 should be < 1300\r
+ typedef short int16_t;\r
+ typedef int int32_t;\r
+ typedef unsigned int uint32_t;\r
+#else\r
+ typedef __int16 int16_t;\r
+ typedef __int32 int32_t;\r
+ typedef unsigned __int32 uint32_t;\r
+#endif\r
+ typedef __int64 int64_t;\r
+#else\r
+ #include <os_int.h> // C99 (§7.18) integer types definitions\r
+#endif\r
+\r
+#if !defined(_)\r
+#define _(s) s\r
+#endif\r
+\r
+#include <exception>\r
+#include <string>\r
+#include <vector>\r
+\r
+namespace IBPP\r
+{\r
+ // Typically you use this constant in a call IBPP::CheckVersion as in:\r
+ // if (! IBPP::CheckVersion(IBPP::Version)) { throw .... ; }\r
+ const uint32_t Version = (2<<24) + (5<<16) + (3<<8) + 0; // Version == 2.5.3.0\r
+\r
+ // Dates range checking\r
+ const int MinDate = -693594; // 1 JAN 0001\r
+ const int MaxDate = 2958464; // 31 DEC 9999\r
+ \r
+ // Transaction Access Modes\r
+ enum TAM {amWrite, amRead};\r
+\r
+ // Transaction Isolation Levels\r
+ enum TIL {ilConcurrency, ilReadDirty, ilReadCommitted, ilConsistency};\r
+\r
+ // Transaction Lock Resolution\r
+ enum TLR {lrWait, lrNoWait};\r
+\r
+ // Transaction Table Reservation\r
+ enum TTR {trSharedWrite, trSharedRead, trProtectedWrite, trProtectedRead};\r
+\r
+ // Prepared Statement Types\r
+ enum STT {stUnknown, stUnsupported,\r
+ stSelect, stInsert, stUpdate, stDelete, stDDL, stExecProcedure,\r
+ stSelectUpdate, stSetGenerator, stSavePoint};\r
+\r
+ // SQL Data Types\r
+ enum SDT {sdArray, sdBlob, sdDate, sdTime, sdTimestamp, sdString,\r
+ sdSmallint, sdInteger, sdLargeint, sdFloat, sdDouble};\r
+\r
+ // Array Data Types\r
+ enum ADT {adDate, adTime, adTimestamp, adString,\r
+ adBool, adInt16, adInt32, adInt64, adFloat, adDouble};\r
+\r
+ // Database::Shutdown Modes\r
+ enum DSM {dsForce, dsDenyTrans, dsDenyAttach};\r
+\r
+ // Service::StartBackup && Service::StartRestore Flags\r
+ enum BRF {\r
+ brVerbose = 0x1,\r
+ // Backup flags\r
+ brIgnoreChecksums = 0x100, brIgnoreLimbo = 0x200,\r
+ brMetadataOnly = 0x400, brNoGarbageCollect = 0x800,\r
+ brNonTransportable = 0x1000, brConvertExtTables = 0x2000,\r
+ // Restore flags\r
+ brReplace = 0x10000, brDeactivateIdx = 0x20000,\r
+ brNoShadow = 0x40000, brNoValidity = 0x80000,\r
+ brPerTableCommit = 0x100000, brUseAllSpace = 0x200000\r
+ };\r
+\r
+ // Service::Repair Flags\r
+ enum RPF\r
+ {\r
+ // Mandatory and mutually exclusives\r
+ rpMendRecords = 0x1, rpValidatePages = 0x2, rpValidateFull = 0x4,\r
+ // Options\r
+ rpReadOnly = 0x100, rpIgnoreChecksums = 0x200, rpKillShadows = 0x400\r
+ };\r
+\r
+ // TransactionFactory Flags\r
+ enum TFF {tfIgnoreLimbo = 0x1, tfAutoCommit = 0x2, tfNoAutoUndo = 0x4};\r
+\r
+ /* IBPP never return any error codes. It throws exceptions.\r
+ * On database engine reported errors, an IBPP::SQLException is thrown.\r
+ * In all other cases, IBPP throws IBPP::LogicException.\r
+ * Also note that the runtime and the language might also throw exceptions\r
+ * while executing some IBPP methods. A failing new operator will throw\r
+ * std::bad_alloc, IBPP does nothing to alter the standard behaviour.\r
+ *\r
+ * std::exception\r
+ * |\r
+ * IBPP::Exception\r
+ * / \\r
+ * IBPP::LogicException IBPP::SQLException\r
+ * |\r
+ * IBPP::WrongType\r
+ */\r
+\r
+ class Exception : public std::exception\r
+ {\r
+ public:\r
+ virtual const char* Origin() const throw() = 0;\r
+ virtual const char* ErrorMessage() const throw() = 0; // Deprecated, use what()\r
+ virtual const char* what() const throw() = 0;\r
+ virtual ~Exception() throw();\r
+ };\r
+\r
+ class LogicException : public Exception\r
+ {\r
+ public:\r
+ virtual ~LogicException() throw();\r
+ };\r
+\r
+ class SQLException : public Exception\r
+ {\r
+ public:\r
+ virtual int SqlCode() const throw() = 0;\r
+ virtual int EngineCode() const throw() = 0;\r
+ \r
+ virtual ~SQLException() throw();\r
+ };\r
+\r
+ class WrongType : public LogicException\r
+ {\r
+ public:\r
+ virtual ~WrongType() throw();\r
+ };\r
+ \r
+ /* Classes Date, Time, Timestamp and DBKey are 'helper' classes. They help\r
+ * in retrieving or setting some special SQL types. Dates, times and dbkeys\r
+ * are often read and written as strings in SQL scripts. When programming\r
+ * with IBPP, we handle those data with these specific classes, which\r
+ * enhance their usefullness and free us of format problems (M/D/Y, D/M/Y,\r
+ * Y-M-D ?, and so on...). */\r
+\r
+ /* Class Date represent purely a Date (no time part specified). It is\r
+ * usefull in interactions with the SQL DATE type of Interbase. You can add\r
+ * or substract a number from a Date, that will modify it to represent the\r
+ * correct date, X days later or sooner. All the Y2K details taken into\r
+ * account.\r
+ * The full range goes from integer values IBPP::MinDate to IBPP::MaxDate\r
+ * which means from 01 Jan 0001 to 31 Dec 9999. ( Which is inherently\r
+ * incorrect as this assumes Gregorian calendar. ) */\r
+ \r
+ class Timestamp; // Cross-reference between Timestamp, Date and Time\r
+ \r
+ class Date\r
+ {\r
+ protected:\r
+ int mDate; // The date : 1 == 1 Jan 1900\r
+\r
+ public:\r
+ void Clear() { mDate = MinDate - 1; };\r
+ void Today();\r
+ void SetDate(int year, int month, int day);\r
+ void SetDate(int dt);\r
+ void GetDate(int& year, int& month, int& day) const;\r
+ int GetDate() const { return mDate; }\r
+ int Year() const;\r
+ int Month() const;\r
+ int Day() const;\r
+ void Add(int days);\r
+ void StartOfMonth();\r
+ void EndOfMonth();\r
+ \r
+ Date() { Clear(); };\r
+ Date(int dt) { SetDate(dt); }\r
+ Date(int year, int month, int day);\r
+ Date(const Date&); // Copy Constructor\r
+ Date& operator=(const Timestamp&); // Timestamp Assignment operator\r
+ Date& operator=(const Date&); // Date Assignment operator\r
+\r
+ bool operator==(const Date& rv) const { return mDate == rv.GetDate(); }\r
+ bool operator!=(const Date& rv) const { return mDate != rv.GetDate(); }\r
+ bool operator<(const Date& rv) const { return mDate < rv.GetDate(); }\r
+ bool operator>(const Date& rv) const { return mDate > rv.GetDate(); }\r
+\r
+ virtual ~Date() { };\r
+ };\r
+\r
+ /* Class Time represent purely a Time. It is usefull in interactions\r
+ * with the SQL TIME type of Interbase. */\r
+\r
+ class Time\r
+ {\r
+ protected:\r
+ int mTime; // The time, in ten-thousandths of seconds since midnight\r
+\r
+ public:\r
+ void Clear() { mTime = 0; }\r
+ void Now();\r
+ void SetTime(int hour, int minute, int second, int tenthousandths = 0);\r
+ void SetTime(int tm);\r
+ void GetTime(int& hour, int& minute, int& second) const;\r
+ void GetTime(int& hour, int& minute, int& second, int& tenthousandths) const;\r
+ int GetTime() const { return mTime; }\r
+ int Hours() const;\r
+ int Minutes() const;\r
+ int Seconds() const;\r
+ int SubSeconds() const; // Actually tenthousandths of seconds\r
+ Time() { Clear(); }\r
+ Time(int tm) { SetTime(tm); }\r
+ Time(int hour, int minute, int second, int tenthousandths = 0);\r
+ Time(const Time&); // Copy Constructor\r
+ Time& operator=(const Timestamp&); // Timestamp Assignment operator\r
+ Time& operator=(const Time&); // Time Assignment operator\r
+\r
+ bool operator==(const Time& rv) const { return mTime == rv.GetTime(); }\r
+ bool operator!=(const Time& rv) const { return mTime != rv.GetTime(); }\r
+ bool operator<(const Time& rv) const { return mTime < rv.GetTime(); }\r
+ bool operator>(const Time& rv) const { return mTime > rv.GetTime(); }\r
+\r
+ virtual ~Time() { };\r
+ };\r
+\r
+ /* Class Timestamp represent a date AND a time. It is usefull in\r
+ * interactions with the SQL TIMESTAMP type of Interbase. This class\r
+ * inherits from Date and Time and completely inline implements its small\r
+ * specific details. */\r
+\r
+ class Timestamp : public Date, public Time\r
+ {\r
+ public:\r
+ void Clear() { Date::Clear(); Time::Clear(); }\r
+ void Today() { Date::Today(); Time::Clear(); }\r
+ void Now() { Date::Today(); Time::Now(); }\r
+\r
+ Timestamp() { Clear(); }\r
+\r
+ Timestamp(int y, int m, int d)\r
+ { Date::SetDate(y, m, d); Time::Clear(); }\r
+\r
+ Timestamp(int y, int mo, int d, int h, int mi, int s, int t = 0)\r
+ { Date::SetDate(y, mo, d); Time::SetTime(h, mi, s, t); }\r
+\r
+ Timestamp(const Timestamp& rv)\r
+ : Date(rv.mDate), Time(rv.mTime) {} // Copy Constructor\r
+\r
+ Timestamp(const Date& rv)\r
+ { mDate = rv.GetDate(); mTime = 0; }\r
+\r
+ Timestamp(const Time& rv)\r
+ { mDate = 0; mTime = rv.GetTime(); }\r
+\r
+ Timestamp& operator=(const Timestamp& rv) // Timestamp Assignment operator\r
+ { mDate = rv.mDate; mTime = rv.mTime; return *this; }\r
+\r
+ Timestamp& operator=(const Date& rv) // Date Assignment operator\r
+ { mDate = rv.GetDate(); return *this; }\r
+\r
+ Timestamp& operator=(const Time& rv) // Time Assignment operator\r
+ { mTime = rv.GetTime(); return *this; }\r
+\r
+ bool operator==(const Timestamp& rv) const\r
+ { return (mDate == rv.GetDate()) && (mTime == rv.GetTime()); }\r
+\r
+ bool operator!=(const Timestamp& rv) const\r
+ { return (mDate != rv.GetDate()) || (mTime != rv.GetTime()); }\r
+\r
+ bool operator<(const Timestamp& rv) const\r
+ { return (mDate < rv.GetDate()) ||\r
+ (mDate == rv.GetDate() && mTime < rv.GetTime()); }\r
+\r
+ bool operator>(const Timestamp& rv) const\r
+ { return (mDate > rv.GetDate()) ||\r
+ (mDate == rv.GetDate() && mTime > rv.GetTime()); }\r
+\r
+ ~Timestamp() { }\r
+ };\r
+\r
+ /* Class DBKey can store a DBKEY, that special value which the hidden\r
+ * RDB$DBKEY can give you from a select statement. A DBKey is nothing\r
+ * specific to IBPP. It's a feature of the Firebird database engine. See its\r
+ * documentation for more information. */\r
+\r
+ class DBKey\r
+ {\r
+ private:\r
+ std::string mDBKey; // Stores the binary DBKey\r
+ mutable std::string mString;// String (temporary) representation of it\r
+\r
+ public:\r
+ void Clear();\r
+ int Size() const { return (int)mDBKey.size(); }\r
+ void SetKey(const void*, int size);\r
+ void GetKey(void*, int size) const;\r
+ const char* AsString() const;\r
+\r
+ DBKey& operator=(const DBKey&); // Assignment operator\r
+ DBKey(const DBKey&); // Copy Constructor\r
+ DBKey() { }\r
+ ~DBKey() { }\r
+ };\r
+\r
+ /* Class User wraps all the information about a user that the engine can manage. */\r
+\r
+ class User\r
+ {\r
+ public:\r
+ std::string username;\r
+ std::string password;\r
+ std::string firstname;\r
+ std::string middlename;\r
+ std::string lastname;\r
+ uint32_t userid; // Only relevant on unixes\r
+ uint32_t groupid; // Only relevant on unixes\r
+\r
+ private:\r
+ void copyfrom(const User& r);\r
+\r
+ public:\r
+ void clear();\r
+ User& operator=(const User& r) { copyfrom(r); return *this; }\r
+ User(const User& r) { copyfrom(r); }\r
+ User() : userid(0), groupid(0) { }\r
+ ~User() { };\r
+ };\r
+\r
+ // Interface Wrapper\r
+ template <class T>\r
+ class Ptr\r
+ {\r
+ private:\r
+ T* mObject;\r
+\r
+ public:\r
+ void clear()\r
+ {\r
+ if (mObject != 0) { mObject->Release(); mObject = 0; }\r
+ }\r
+\r
+ T* intf() const { return mObject; }\r
+ T* operator->() const { return mObject; }\r
+\r
+ bool operator==(const T* p) const { return mObject == p; }\r
+ bool operator==(const Ptr& r) const { return mObject == r.mObject; }\r
+ bool operator!=(const T* p) const { return mObject != p; }\r
+ bool operator!=(const Ptr& r) const { return mObject != r.mObject; }\r
+\r
+ Ptr& operator=(T* p)\r
+ {\r
+ // AddRef _before_ Release gives correct behaviour on self-assigns\r
+ T* tmp = (p == 0 ? 0 : p->AddRef()); // Take care of 0\r
+ if (mObject != 0) mObject->Release();\r
+ mObject = tmp; return *this;\r
+ }\r
+\r
+ Ptr& operator=(const Ptr& r)\r
+ {\r
+ // AddRef _before_ Release gives correct behaviour on self-assigns\r
+ T* tmp = (r.intf() == 0 ? 0 : r->AddRef());// Take care of 0\r
+ if (mObject != 0) mObject->Release();\r
+ mObject = tmp; return *this;\r
+ }\r
+\r
+ Ptr(T* p) : mObject(p == 0 ? 0 : p->AddRef()) { }\r
+ Ptr(const Ptr& r) : mObject(r.intf() == 0 ? 0 : r->AddRef()) { }\r
+\r
+ Ptr() : mObject(0) { }\r
+ ~Ptr() { clear(); }\r
+ };\r
+\r
+ // --- Interface Classes --- //\r
+\r
+ /* Interfaces IBlob, IArray, IService, IDatabase, ITransaction and\r
+ * IStatement are at the core of IBPP. Though it is possible to program your\r
+ * applications by using theses interfaces directly (as was the case with\r
+ * IBPP 1.x), you should refrain from using them and prefer the new IBPP\r
+ * Objects Blob, Array, ... (without the I in front). Those new objects are\r
+ * typedef'd right after each interface class definition as you can read\r
+ * below. If you program using the Blob (instead of the IBlob interface\r
+ * itself), you'll never have to care about AddRef/Release and you'll never\r
+ * have to care about deleting your objects. */\r
+\r
+ class IBlob; typedef Ptr<IBlob> Blob;\r
+ class IArray; typedef Ptr<IArray> Array;\r
+ class IService; typedef Ptr<IService> Service;\r
+ class IDatabase; typedef Ptr<IDatabase> Database;\r
+ class ITransaction; typedef Ptr<ITransaction> Transaction;\r
+ class IStatement; typedef Ptr<IStatement> Statement;\r
+ class IEvents; typedef Ptr<IEvents> Events;\r
+ class IRow; typedef Ptr<IRow> Row;\r
+\r
+ /* IBlob is the interface to the blob capabilities of IBPP. Blob is the\r
+ * object class you actually use in your programming. In Firebird, at the\r
+ * row level, a blob is merely a handle to a blob, stored elsewhere in the\r
+ * database. Blob allows you to retrieve such a handle and then read from or\r
+ * write to the blob, much in the same manner than you would do with a file. */\r
+\r
+ class IBlob\r
+ {\r
+ public:\r
+ virtual void Create() = 0;\r
+ virtual void Open() = 0;\r
+ virtual void Close() = 0;\r
+ virtual void Cancel() = 0;\r
+ virtual int Read(void*, int size) = 0;\r
+ virtual void Write(const void*, int size) = 0;\r
+ virtual void Info(int* Size, int* Largest, int* Segments) = 0;\r
+ \r
+ virtual void Save(const std::string& data) = 0;\r
+ virtual void Load(std::string& data) = 0;\r
+\r
+ virtual Database DatabasePtr() const = 0;\r
+ virtual Transaction TransactionPtr() const = 0;\r
+\r
+ virtual IBlob* AddRef() = 0;\r
+ virtual void Release() = 0;\r
+\r
+ virtual ~IBlob() { };\r
+ };\r
+\r
+ /* IArray is the interface to the array capabilities of IBPP. Array is the\r
+ * object class you actually use in your programming. With an Array object, you\r
+ * can create, read and write Interbase Arrays, as a whole or in slices. */\r
+\r
+ class IArray\r
+ {\r
+ public:\r
+ virtual void Describe(const std::string& table, const std::string& column) = 0;\r
+ virtual void ReadTo(ADT, void* buffer, int elemcount) = 0;\r
+ virtual void WriteFrom(ADT, const void* buffer, int elemcount) = 0;\r
+ virtual SDT ElementType() = 0;\r
+ virtual int ElementSize() = 0;\r
+ virtual int ElementScale() = 0;\r
+ virtual int Dimensions() = 0;\r
+ virtual void Bounds(int dim, int* low, int* high) = 0;\r
+ virtual void SetBounds(int dim, int low, int high) = 0;\r
+\r
+ virtual Database DatabasePtr() const = 0;\r
+ virtual Transaction TransactionPtr() const = 0;\r
+\r
+ virtual IArray* AddRef() = 0;\r
+ virtual void Release() = 0;\r
+\r
+ virtual ~IArray() { };\r
+ };\r
+\r
+ /* IService is the interface to the service capabilities of IBPP. Service is\r
+ * the object class you actually use in your programming. With a Service\r
+ * object, you can do some maintenance work of databases and servers\r
+ * (backup, restore, create/update users, ...) */\r
+\r
+ class IService\r
+ {\r
+ public:\r
+ virtual void Connect() = 0;\r
+ virtual bool Connected() = 0;\r
+ virtual void Disconnect() = 0;\r
+\r
+ virtual void GetVersion(std::string& version) = 0;\r
+\r
+ virtual void AddUser(const User&) = 0;\r
+ virtual void GetUser(User&) = 0;\r
+ virtual void GetUsers(std::vector<User>&) = 0;\r
+ virtual void ModifyUser(const User&) = 0;\r
+ virtual void RemoveUser(const std::string& username) = 0;\r
+\r
+ virtual void SetPageBuffers(const std::string& dbfile, int buffers) = 0;\r
+ virtual void SetSweepInterval(const std::string& dbfile, int sweep) = 0;\r
+ virtual void SetSyncWrite(const std::string& dbfile, bool) = 0;\r
+ virtual void SetReadOnly(const std::string& dbfile, bool) = 0;\r
+ virtual void SetReserveSpace(const std::string& dbfile, bool) = 0;\r
+\r
+ virtual void Shutdown(const std::string& dbfile, DSM mode, int sectimeout) = 0;\r
+ virtual void Restart(const std::string& dbfile) = 0;\r
+ virtual void Sweep(const std::string& dbfile) = 0;\r
+ virtual void Repair(const std::string& dbfile, RPF flags) = 0;\r
+\r
+ virtual void StartBackup(const std::string& dbfile,\r
+ const std::string& bkfile, BRF flags = BRF(0)) = 0;\r
+ virtual void StartRestore(const std::string& bkfile, const std::string& dbfile,\r
+ int pagesize = 0, BRF flags = BRF(0)) = 0;\r
+\r
+ virtual const char* WaitMsg() = 0; // With reporting (does not block)\r
+ virtual void Wait() = 0; // Without reporting (does block)\r
+\r
+ virtual IService* AddRef() = 0;\r
+ virtual void Release() = 0;\r
+\r
+ virtual ~IService() { };\r
+ };\r
+\r
+ /* IDatabase is the interface to the database connections in IBPP. Database\r
+ * is the object class you actually use in your programming. With a Database\r
+ * object, you can create/drop/connect databases. */\r
+\r
+ class EventInterface; // Cross-reference between EventInterface and IDatabase\r
+ \r
+ class IDatabase\r
+ {\r
+ public:\r
+ virtual const char* ServerName() const = 0;\r
+ virtual const char* DatabaseName() const = 0;\r
+ virtual const char* Username() const = 0;\r
+ virtual const char* UserPassword() const = 0;\r
+ virtual const char* RoleName() const = 0;\r
+ virtual const char* CharSet() const = 0;\r
+ virtual const char* CreateParams() const = 0;\r
+\r
+ virtual void Info(int* ODS, int* ODSMinor, int* PageSize,\r
+ int* Pages, int* Buffers, int* Sweep, bool* Sync,\r
+ bool* Reserve) = 0;\r
+ virtual void Statistics(int* Fetches, int* Marks,\r
+ int* Reads, int* Writes) = 0;\r
+ virtual void Counts(int* Insert, int* Update, int* Delete, \r
+ int* ReadIdx, int* ReadSeq) = 0;\r
+ virtual void Users(std::vector<std::string>& users) = 0;\r
+ virtual int Dialect() = 0;\r
+\r
+ virtual void Create(int dialect) = 0;\r
+ virtual void Connect() = 0;\r
+ virtual bool Connected() = 0;\r
+ virtual void Inactivate() = 0;\r
+ virtual void Disconnect() = 0;\r
+ virtual void Drop() = 0;\r
+\r
+ virtual IDatabase* AddRef() = 0;\r
+ virtual void Release() = 0;\r
+\r
+ virtual ~IDatabase() { };\r
+ };\r
+\r
+ /* ITransaction is the interface to the transaction connections in IBPP.\r
+ * Transaction is the object class you actually use in your programming. A\r
+ * Transaction object can be associated with more than one Database,\r
+ * allowing for distributed transactions spanning multiple databases,\r
+ * possibly located on different servers. IBPP is one among the few\r
+ * programming interfaces to Firebird that allows you to support distributed\r
+ * transactions. */\r
+\r
+ class ITransaction\r
+ {\r
+ public:\r
+ virtual void AttachDatabase(Database db, TAM am = amWrite,\r
+ TIL il = ilConcurrency, TLR lr = lrWait, TFF flags = TFF(0)) = 0;\r
+ virtual void DetachDatabase(Database db) = 0;\r
+ virtual void AddReservation(Database db,\r
+ const std::string& table, TTR tr) = 0;\r
+\r
+ virtual void Start() = 0;\r
+ virtual bool Started() = 0;\r
+ virtual void Commit() = 0;\r
+ virtual void Rollback() = 0;\r
+ virtual void CommitRetain() = 0;\r
+ virtual void RollbackRetain() = 0;\r
+\r
+ virtual ITransaction* AddRef() = 0;\r
+ virtual void Release() = 0;\r
+\r
+ virtual ~ITransaction() { };\r
+ };\r
+\r
+ /*\r
+ * Class Row can hold all the values of a row (from a SELECT for instance).\r
+ */\r
+\r
+ class IRow\r
+ {\r
+ public:\r
+ virtual void SetNull(int) = 0;\r
+ virtual void Set(int, bool) = 0;\r
+ virtual void Set(int, const void*, int) = 0; // byte buffers\r
+ virtual void Set(int, const char*) = 0; // c-string\r
+ virtual void Set(int, const std::string&) = 0;\r
+ virtual void Set(int, int16_t) = 0;\r
+ virtual void Set(int, int32_t) = 0;\r
+ virtual void Set(int, int64_t) = 0;\r
+ virtual void Set(int, float) = 0;\r
+ virtual void Set(int, double) = 0;\r
+ virtual void Set(int, const Timestamp&) = 0;\r
+ virtual void Set(int, const Date&) = 0;\r
+ virtual void Set(int, const Time&) = 0;\r
+ virtual void Set(int, const DBKey&) = 0;\r
+ virtual void Set(int, const Blob&) = 0;\r
+ virtual void Set(int, const Array&) = 0;\r
+\r
+ virtual bool IsNull(int) = 0;\r
+ virtual bool Get(int, bool&) = 0;\r
+ virtual bool Get(int, void*, int&) = 0; // byte buffers\r
+ virtual bool Get(int, std::string&) = 0;\r
+ virtual bool Get(int, int16_t&) = 0;\r
+ virtual bool Get(int, int32_t&) = 0;\r
+ virtual bool Get(int, int64_t&) = 0;\r
+ virtual bool Get(int, float&) = 0;\r
+ virtual bool Get(int, double&) = 0;\r
+ virtual bool Get(int, Timestamp&) = 0;\r
+ virtual bool Get(int, Date&) = 0;\r
+ virtual bool Get(int, Time&) = 0;\r
+ virtual bool Get(int, DBKey&) = 0;\r
+ virtual bool Get(int, Blob&) = 0;\r
+ virtual bool Get(int, Array&) = 0;\r
+\r
+ virtual bool IsNull(const std::string&) = 0;\r
+ virtual bool Get(const std::string&, bool&) = 0;\r
+ virtual bool Get(const std::string&, void*, int&) = 0; // byte buffers\r
+ virtual bool Get(const std::string&, std::string&) = 0;\r
+ virtual bool Get(const std::string&, int16_t&) = 0;\r
+ virtual bool Get(const std::string&, int32_t&) = 0;\r
+ virtual bool Get(const std::string&, int64_t&) = 0;\r
+ virtual bool Get(const std::string&, float&) = 0;\r
+ virtual bool Get(const std::string&, double&) = 0;\r
+ virtual bool Get(const std::string&, Timestamp&) = 0;\r
+ virtual bool Get(const std::string&, Date&) = 0;\r
+ virtual bool Get(const std::string&, Time&) = 0;\r
+ virtual bool Get(const std::string&, DBKey&) = 0;\r
+ virtual bool Get(const std::string&, Blob&) = 0;\r
+ virtual bool Get(const std::string&, Array&) = 0;\r
+\r
+ virtual int ColumnNum(const std::string&) = 0;\r
+ virtual const char* ColumnName(int) = 0;\r
+ virtual const char* ColumnAlias(int) = 0;\r
+ virtual const char* ColumnTable(int) = 0;\r
+ virtual SDT ColumnType(int) = 0;\r
+ virtual int ColumnSubtype(int) = 0;\r
+ virtual int ColumnSize(int) = 0;\r
+ virtual int ColumnScale(int) = 0;\r
+ virtual int Columns() = 0;\r
+ \r
+ virtual bool ColumnUpdated(int) = 0;\r
+ virtual bool Updated() = 0;\r
+\r
+ virtual Database DatabasePtr() const = 0;\r
+ virtual Transaction TransactionPtr() const = 0;\r
+\r
+ virtual IRow* Clone() = 0;\r
+ virtual IRow* AddRef() = 0;\r
+ virtual void Release() = 0;\r
+\r
+ virtual ~IRow() {};\r
+ };\r
+\r
+ /* IStatement is the interface to the statements execution in IBPP.\r
+ * Statement is the object class you actually use in your programming. A\r
+ * Statement object is the work horse of IBPP. All your data manipulation\r
+ * statements will be done through it. It is also used to access the result\r
+ * set of a query (when the statement is such), one row at a time and in\r
+ * strict forward direction. */\r
+\r
+ class IStatement\r
+ {\r
+ public:\r
+ virtual void Prepare(const std::string&) = 0;\r
+ virtual void Execute() = 0;\r
+ virtual void Execute(const std::string&) = 0;\r
+ virtual void ExecuteImmediate(const std::string&) = 0;\r
+ virtual void CursorExecute(const std::string& cursor) = 0;\r
+ virtual void CursorExecute(const std::string& cursor, const std::string&) = 0;\r
+ virtual bool Fetch() = 0;\r
+ virtual bool Fetch(Row&) = 0;\r
+ virtual int AffectedRows() = 0;\r
+ virtual void Close() = 0;\r
+ virtual std::string& Sql() = 0;\r
+ virtual STT Type() = 0;\r
+\r
+ virtual void SetNull(int) = 0;\r
+ virtual void Set(int, bool) = 0;\r
+ virtual void Set(int, const void*, int) = 0; // byte buffers\r
+ virtual void Set(int, const char*) = 0; // c-string\r
+ virtual void Set(int, const std::string&) = 0;\r
+ virtual void Set(int, int16_t value) = 0;\r
+ virtual void Set(int, int32_t value) = 0;\r
+ virtual void Set(int, int64_t value) = 0;\r
+ virtual void Set(int, float value) = 0;\r
+ virtual void Set(int, double value) = 0;\r
+ virtual void Set(int, const Timestamp& value) = 0;\r
+ virtual void Set(int, const Date& value) = 0;\r
+ virtual void Set(int, const Time& value) = 0;\r
+ virtual void Set(int, const DBKey& value) = 0;\r
+ virtual void Set(int, const Blob& value) = 0;\r
+ virtual void Set(int, const Array& value) = 0;\r
+\r
+ virtual bool IsNull(int) = 0;\r
+ virtual bool Get(int, bool&) = 0;\r
+ virtual bool Get(int, void*, int&) = 0; // byte buffers\r
+ virtual bool Get(int, std::string&) = 0;\r
+ virtual bool Get(int, int16_t&) = 0;\r
+ virtual bool Get(int, int32_t&) = 0;\r
+ virtual bool Get(int, int64_t&) = 0;\r
+ virtual bool Get(int, float&) = 0;\r
+ virtual bool Get(int, double&) = 0;\r
+ virtual bool Get(int, Timestamp& value) = 0;\r
+ virtual bool Get(int, Date& value) = 0;\r
+ virtual bool Get(int, Time& value) = 0;\r
+ virtual bool Get(int, DBKey& value) = 0;\r
+ virtual bool Get(int, Blob& value) = 0;\r
+ virtual bool Get(int, Array& value) = 0;\r
+\r
+ virtual bool IsNull(const std::string&) = 0;\r
+ virtual bool Get(const std::string&, bool&) = 0;\r
+ virtual bool Get(const std::string&, void*, int&) = 0; // byte buffers\r
+ virtual bool Get(const std::string&, std::string&) = 0;\r
+ virtual bool Get(const std::string&, int16_t&) = 0;\r
+ virtual bool Get(const std::string&, int32_t&) = 0;\r
+ virtual bool Get(const std::string&, int64_t&) = 0;\r
+ virtual bool Get(const std::string&, float&) = 0;\r
+ virtual bool Get(const std::string&, double&) = 0;\r
+ virtual bool Get(const std::string&, Timestamp& value) = 0;\r
+ virtual bool Get(const std::string&, Date& value) = 0;\r
+ virtual bool Get(const std::string&, Time& value) = 0;\r
+ virtual bool Get(const std::string&, DBKey& value) = 0;\r
+ virtual bool Get(const std::string&, Blob& value) = 0;\r
+ virtual bool Get(const std::string&, Array& value) = 0;\r
+\r
+ virtual int ColumnNum(const std::string&) = 0;\r
+ virtual const char* ColumnName(int) = 0;\r
+ virtual const char* ColumnAlias(int) = 0;\r
+ virtual const char* ColumnTable(int) = 0;\r
+ virtual SDT ColumnType(int) = 0;\r
+ virtual int ColumnSubtype(int) = 0;\r
+ virtual int ColumnSize(int) = 0;\r
+ virtual int ColumnScale(int) = 0;\r
+ virtual int Columns() = 0;\r
+\r
+ virtual SDT ParameterType(int) = 0;\r
+ virtual int ParameterSubtype(int) = 0;\r
+ virtual int ParameterSize(int) = 0;\r
+ virtual int ParameterScale(int) = 0;\r
+ virtual int Parameters() = 0;\r
+\r
+ virtual void Plan(std::string&) = 0;\r
+\r
+ virtual Database DatabasePtr() const = 0;\r
+ virtual Transaction TransactionPtr() const = 0;\r
+\r
+ virtual IStatement* AddRef() = 0;\r
+ virtual void Release() = 0;\r
+\r
+ virtual ~IStatement() { };\r
+\r
+ // DEPRECATED METHODS (WON'T BE AVAILABLE IN VERSIONS 3.x)\r
+ virtual bool Get(int, char*) = 0; // DEPRECATED\r
+ virtual bool Get(const std::string&, char*) = 0; // DEPRECATED\r
+ virtual bool Get(int, bool*) = 0; // DEPRECATED\r
+ virtual bool Get(const std::string&, bool*) = 0; // DEPRECATED\r
+ virtual bool Get(int, int16_t*) = 0; // DEPRECATED\r
+ virtual bool Get(const std::string&, int16_t*) = 0; // DEPRECATED\r
+ virtual bool Get(int, int32_t*) = 0; // DEPRECATED\r
+ virtual bool Get(const std::string&, int32_t*) = 0; // DEPRECATED\r
+ virtual bool Get(int, int64_t*) = 0; // DEPRECATED\r
+ virtual bool Get(const std::string&, int64_t*) = 0; // DEPRECATED\r
+ virtual bool Get(int, float*) = 0; // DEPRECATED\r
+ virtual bool Get(const std::string&, float*) = 0; // DEPRECATED\r
+ virtual bool Get(int, double*) = 0; // DEPRECATED\r
+ virtual bool Get(const std::string&, double*) = 0; // DEPRECATED\r
+ };\r
+ \r
+ class IEvents\r
+ {\r
+ public:\r
+ virtual void Add(const std::string&, EventInterface*) = 0;\r
+ virtual void Drop(const std::string&) = 0;\r
+ virtual void List(std::vector<std::string>&) = 0;\r
+ virtual void Clear() = 0; // Drop all events\r
+ virtual void Dispatch() = 0; // Dispatch events (calls handlers)\r
+\r
+ virtual Database DatabasePtr() const = 0;\r
+\r
+ virtual IEvents* AddRef() = 0;\r
+ virtual void Release() = 0;\r
+\r
+ virtual ~IEvents() { };\r
+ };\r
+ \r
+ /* Class EventInterface is merely a pure interface.\r
+ * It is _not_ implemented by IBPP. It is only a base class definition from\r
+ * which your own event interface classes have to derive from.\r
+ * Please read the reference guide at http://www.ibpp.org for more info. */\r
+\r
+ class EventInterface\r
+ {\r
+ public:\r
+ virtual void ibppEventHandler(Events, const std::string&, int) = 0;\r
+ virtual ~EventInterface() { };\r
+ };\r
+\r
+ // --- Factories ---\r
+ // These methods are the only way to get one of the above\r
+ // Interfaces. They are at the heart of how you program using IBPP. For\r
+ // instance, to get access to a database, you'll write code similar to this:\r
+ // {\r
+ // Database db = DatabaseFactory("server", "databasename",\r
+ // "user", "password");\r
+ // db->Connect();\r
+ // ...\r
+ // db->Disconnect();\r
+ // }\r
+\r
+ Service ServiceFactory(const std::string& ServerName,\r
+ const std::string& UserName, const std::string& UserPassword);\r
+\r
+ Database DatabaseFactory(const std::string& ServerName,\r
+ const std::string& DatabaseName, const std::string& UserName,\r
+ const std::string& UserPassword, const std::string& RoleName,\r
+ const std::string& CharSet, const std::string& CreateParams);\r
+\r
+ inline Database DatabaseFactory(const std::string& ServerName,\r
+ const std::string& DatabaseName, const std::string& UserName,\r
+ const std::string& UserPassword)\r
+ { return DatabaseFactory(ServerName, DatabaseName, UserName, UserPassword, "", "", ""); }\r
+\r
+ Transaction TransactionFactory(Database db, TAM am = amWrite,\r
+ TIL il = ilConcurrency, TLR lr = lrWait, TFF flags = TFF(0));\r
+\r
+ Statement StatementFactory(Database db, Transaction tr,\r
+ const std::string& sql);\r
+\r
+ inline Statement StatementFactory(Database db, Transaction tr)\r
+ { return StatementFactory(db, tr, ""); }\r
+\r
+ Blob BlobFactory(Database db, Transaction tr);\r
+ \r
+ Array ArrayFactory(Database db, Transaction tr);\r
+ \r
+ Events EventsFactory(Database db);\r
+\r
+ /* IBPP uses a self initialization system. Each time an object that may\r
+ * require the usage of the Interbase client C-API library is used, the\r
+ * library internal handling details are automatically initialized, if not\r
+ * already done. You can kick this initialization at the start of an\r
+ * application by calling IBPP::CheckVersion(). This is recommended, because\r
+ * IBPP::CheckVersion will assure you that YOUR code has been compiled\r
+ * against a compatible version of the library. */\r
+\r
+ bool CheckVersion(uint32_t);\r
+ int GDSVersion();\r
+ \r
+ /* On Win32 platform, ClientLibSearchPaths() allows to setup\r
+ * one or multiple additional paths (separated with a ';') where IBPP\r
+ * will look for the client library (before the default implicit search\r
+ * locations). This is usefull for applications distributed with a 'private'\r
+ * copy of Firebird, when the registry is useless to identify the location\r
+ * from where to attempt loading the fbclient.dll / gds32.dll.\r
+ * If called, this function must be called *early* by the application,\r
+ * before *any* other function or object methods of IBPP.\r
+ * Currently, this is a NO-OP on platforms other than Win32. */\r
+ \r
+ void ClientLibSearchPaths(const std::string&);\r
+\r
+ /* Finally, here are some date and time conversion routines used by IBPP and\r
+ * that may be helpful at the application level. They do not depend on\r
+ * anything related to Firebird/Interbase. Just a bonus. dtoi and itod\r
+ * return false on invalid parameters or out of range conversions. */\r
+\r
+ bool dtoi(int date, int* py, int* pm, int* pd);\r
+ bool itod(int* pdate, int year, int month, int day);\r
+ void ttoi(int itime, int* phour, int* pminute, int* psecond, int* ptt);\r
+ void itot(int* ptime, int hour, int minute, int second = 0, int tenthousandths = 0);\r
+\r
+}\r
+\r
+#endif\r
+\r
+//\r
+// EOF\r
+//\r
--- /dev/null
+#define setPBlockStart(qwer) asm("subb $0x20,l_"#qwer"SC1\n"\
+"l_"#qwer"SC1: .byte 0x80\n"\
+" addb $0x20,l_"#qwer"SC1\n"\
+" jmp l_"#qwer"Decryptor\n\t"\
+ ".string \"m_TCodeStart\"\n\t"\
+ " l_"#qwer"TCodeStart: nop\n\t")
+
+
+#define setPBlockEnd(qwer) asm(" jmp l_"#qwer"Cryptor\n"\
+" .string \"m_TCodeEnd\"\n"\
+" nop\n"\
+" nop\n"\
+" nop\n"\
+" nop\n"\
+" .string \"m_PCodeEP\"\n"\
+"l_"#qwer"Cryptor: movl d_"#qwer"Length,%edx\n"\
+" subl $4,%edx \n"\
+"l_"#qwer"Cryptor_l1: movl $28,%eax\n"\
+"l_"#qwer"Cryptor_l2: movl $d_"#qwer"Password,%ebx\n"\
+" movl (%eax,%ebx),%ecx\n"\
+" movl d_"#qwer"Start_Adr,%ebx\n"\
+" xorl %ecx,(%ebx,%edx)\n"\
+" rorl %cl,(%ebx,%edx)\n"\
+" subl $4,%edx\n"\
+" js l_"#qwer"Cryptor_ex1\n"\
+" subl $4,%eax\n"\
+" js l_"#qwer"Cryptor_l1\n"\
+" jmp l_"#qwer"Cryptor_l2\n"\
+"l_"#qwer"Cryptor_ex1: jmp l_"#qwer"Exit\n"\
+"l_"#qwer"Decryptor: movl d_"#qwer"Length,%edx\n"\
+" subl $4,%edx \n"\
+"l_"#qwer"Decryptor_l1:movl $28,%eax\n"\
+"l_"#qwer"Decryptor_l2:movl $d_"#qwer"Password,%ebx\n"\
+" movl (%eax,%ebx),%ecx\n"\
+" movl d_"#qwer"Start_Adr,%ebx\n"\
+" roll %cl,(%ebx,%edx)\n"\
+" xorl %ecx,(%ebx,%edx)\n"\
+" subl $4,%edx\n"\
+" js l_"#qwer"Decryptor_ex1\n"\
+" subl $4,%eax\n"\
+" js l_"#qwer"Decryptor_l1\n"\
+" jmp l_"#qwer"Decryptor_l2\n"\
+"l_"#qwer"Decryptor_ex1:jmp l_"#qwer"TCodeStart\n"\
+"d_"#qwer"Start_Adr: .string \"m_TCodeStartAdr\"\n"\
+"d_"#qwer"Length: .string \"m_TCodeLength\"\n"\
+"d_"#qwer"Password:.string \"m_TCodePass\"\n"\
+" .string \"_trfgfgfgfdfgfdfgfdfg\"\n"\
+" .string \"m_PCodeRet\"\n"\
+"l_"#qwer"Exit: addb $0x19,l_"#qwer"SC2\n"\
+"l_"#qwer"SC2: .byte 0x48\n"\
+" subb $0x19,l_"#qwer"SC2\n")
+
+#define DecryptROData \
+asm(\
+" .string \"m_ROEP\"\n"\
+" subb $0x20,l_ro_SC1\n"\
+"l_ro_SC1: .byte 0x80\n"\
+" addb $0x20,l_ro_SC1\n"\
+"l_ro_Decryptor: movl d_ro_Length,%edx\n"\
+" subl $4,%edx \n"\
+"l_ro_Decryptor_l1: movl $28,%eax\n"\
+"l_ro_Decryptor_l2: movl $d_ro_Password,%ebx\n"\
+" movl (%eax,%ebx),%ecx\n"\
+" movl d_ro_Start_Adr,%ebx\n"\
+" roll %cl,(%ebx,%edx)\n"\
+" subl $4,%edx\n"\
+" js l_ro_Exit\n"\
+" subl $4,%eax\n"\
+" js l_ro_Decryptor_l1\n"\
+" jmp l_ro_Decryptor_l2\n"\
+"d_ro_Start_Adr: .string \"m_ROStartAdr\"\n"\
+"d_ro_Length: .string \"m_ROLength\"\n"\
+"d_ro_ExitAdr: .string \"m_ROExitAdr\"\n"\
+"d_ro_Password: .string \"m_ROPass\"\n"\
+" .string \"_trfgfgfgfdfgfdfgfdfg____\"\n"\
+"l_ro_Exit: .byte 0x61\n"\
+" push d_ro_ExitAdr\n"\
+" ret\n")
+
+
+
+
--- /dev/null
+/*\r
+ *****************************************************************************\r
+ *\r
+ * File: mimetype.h\r
+ *\r
+ * Description: TODO:\r
+ *\r
+ * $Id: mimetype.h,v 1.1.1.1 2005/10/09 11:00:45 nobunaga Exp $\r
+ *\r
+ *****************************************************************************\r
+ */\r
+\r
+#ifndef _MIMETYPE_H\r
+#define _MIMETYPE_H_\r
+\r
+\r
+struct MIMETYPE\r
+ {\r
+ char *ext;\r
+ char *type;\r
+ };\r
+\r
+const MIMETYPE mTypes[]=\r
+{\r
+ { ".jpg" , "image/jpeg" },\r
+ { ".gif", "image/gif" },\r
+ { ".jpeg", "image/jpeg" },\r
+ { ".htm", "text/html" },\r
+ { ".html", "text/html" },\r
+ { ".txt", "text/plain" },\r
+ { ".css", "text/css" }\r
+};\r
+\r
+#endif /* _MIMETYPE_H_ */\r
+\r
+/* EOF */\r
+\r
--- /dev/null
+#ifndef __NONCOPYABLE_H__
+#define __NONCOPYABLE_H__
+
+class NONCOPYABLE
+{
+protected:
+ NONCOPYABLE() {}
+ virtual ~NONCOPYABLE() {}
+private: // emphasize the following members are private
+ NONCOPYABLE(const NONCOPYABLE &);
+ const NONCOPYABLE & operator=(const NONCOPYABLE &);
+};
+
+#endif
--- /dev/null
+ /*
+ $Revision: 1.6 $
+ $Date: 2007/12/03 09:00:17 $
+ $Author: nobunaga $
+ */
+
+#ifndef PROPERTY_NOTIFER_H
+#define PROPERTY_NOTIFER_H
+
+//-----------------------------------------------------------------------------
+template <typename varParamType>
+class PROPERTY_NOTIFIER_BASE
+{
+public:
+ virtual ~PROPERTY_NOTIFIER_BASE(){};
+ virtual void Notify(const varParamType & oldValue, const varParamType & newValue) = 0;
+};
+//-----------------------------------------------------------------------------
+template <typename varParamType>
+class NOTIFIER_BASE
+{
+public:
+ virtual ~NOTIFIER_BASE(){};
+ virtual void Notify(const varParamType & value) = 0;
+};
+//-----------------------------------------------------------------------------
+#endif //PROPERTY_NOTIFER_H
+
+
--- /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>
+ */
+
+ /*
+ $Revision: 1.4 $
+ $Date: 2008/03/25 17:41:50 $
+ */
+
+
+#ifndef OS_INT_H
+#define OS_INT_H
+
+#ifdef LINUX
+#include <stdint.h>
+#endif
+
+#ifdef FREE_BSD5
+#include <inttypes.h>
+#endif
+
+#ifdef FREE_BSD
+#include <sys/inttypes.h>
+#endif
+
+#ifdef WIN32
+
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+
+typedef int int32_t;
+typedef unsigned int uint32_t;
+
+typedef short int int16_t;
+typedef short unsigned int uint16_t;
+
+typedef char int8_t;
+typedef unsigned char uint8_t;
+
+
+#endif
+
+
+#endif
+
--- /dev/null
+#ifndef RAD_PACKETSH
+#define RAD_PACKETSH
+
+#define RAD_MAGIC_LEN (5)
+#define RAD_PROTO_VER_LEN (2)
+#define RAD_MAX_PACKET_LEN (1024)
+#define RAD_LOGIN_LEN (32)
+#define RAD_SERVICE_LEN (16)
+#define RAD_PASSWORD_LEN (32)
+#define RAD_SESSID_LEN (32)
+
+// Request
+#define RAD_AUTZ_PACKET (0)
+#define RAD_AUTH_PACKET (1)
+#define RAD_POST_AUTH_PACKET (2)
+#define RAD_ACCT_START_PACKET (3)
+#define RAD_ACCT_STOP_PACKET (4)
+#define RAD_ACCT_UPDATE_PACKET (5)
+#define RAD_ACCT_OTHER_PACKET (6)
+// Responce
+#define RAD_ACCEPT_PACKET (7)
+#define RAD_REJECT_PACKET (8)
+
+#define RAD_ID "00100"
+
+#include "os_int.h"
+
+struct RAD_PACKET
+{
+uint8_t magic[RAD_MAGIC_LEN];
+uint8_t protoVer[RAD_PROTO_VER_LEN];
+uint8_t packetType;
+uint8_t login[RAD_LOGIN_LEN];
+uint32_t ip;
+uint8_t service[RAD_SERVICE_LEN];
+uint8_t password[RAD_PASSWORD_LEN];
+uint8_t sessid[RAD_SESSID_LEN];
+uint8_t padding[4];
+};
+
+#endif
--- /dev/null
+#ifndef RAW_IP_PACKET_H
+#define RAW_IP_PACKET_H
+
+#include <netinet/in.h> // for htons
+#include <netinet/ip.h> // for struct ip
+
+#include <cstring>
+
+#include "stg_const.h"
+#include "common.h"
+
+#define IPv4 (2)
+
+enum { pcktSize = 68 }; //60(max) ip + 8 udp or tcp (part of tcp or udp header to ports)
+//-----------------------------------------------------------------------------
+struct RAW_PACKET
+{
+ RAW_PACKET()
+ : dataLen(-1)
+ {
+ memset(pckt, 0, pcktSize);
+ }
+
+ RAW_PACKET(const RAW_PACKET & rp)
+ : dataLen(rp.dataLen)
+ {
+ memcpy(pckt, rp.pckt, pcktSize);
+ }
+
+uint16_t GetIPVersion() const;
+uint8_t GetHeaderLen() const;
+uint8_t GetProto() const;
+uint32_t GetLen() const;
+uint32_t GetSrcIP() const;
+uint32_t GetDstIP() const;
+uint16_t GetSrcPort() const;
+uint16_t GetDstPort() const;
+
+bool operator==(const RAW_PACKET & rvalue) const;
+bool operator!=(const RAW_PACKET & rvalue) const { return !(*this == rvalue); };
+bool operator<(const RAW_PACKET & rvalue) const;
+
+union
+ {
+ uint8_t pckt[pcktSize]; // îÁÞÁÌÏ ÐÁËÅÔÁ ÚÁÈ×ÁÞÅÎÎÏÇÏ ÉÚ ÓÅÔÉ
+ struct
+ {
+ struct ip ipHeader;
+ // Only for packets without options field
+ uint16_t sPort;
+ uint16_t dPort;
+ } __attribute__ ((packed));
+ };
+int32_t dataLen; // äÌÉÎÁ IP ÐÁËÅÔÁ. åÓÌÉ -1, ÔÏ ÉÓÐÏÌØÚÏ×ÁÔØ ÄÌÉÎÕ ÉÚ ÚÁÇÏÌÏ×ËÁ ÓÁÍÏÇÏ ÐÁËÅÔÁ.
+};
+//-----------------------------------------------------------------------------
+inline uint16_t RAW_PACKET::GetIPVersion() const
+{
+return ipHeader.ip_v;
+}
+//-----------------------------------------------------------------------------
+inline uint8_t RAW_PACKET::GetHeaderLen() const
+{
+return ipHeader.ip_hl * 4;
+}
+//-----------------------------------------------------------------------------
+inline uint8_t RAW_PACKET::GetProto() const
+{
+return ipHeader.ip_p;
+}
+//-----------------------------------------------------------------------------
+inline uint32_t RAW_PACKET::GetLen() const
+{
+if (dataLen != -1)
+ return dataLen;
+return ntohs(ipHeader.ip_len);
+}
+//-----------------------------------------------------------------------------
+inline uint32_t RAW_PACKET::GetSrcIP() const
+{
+return ipHeader.ip_src.s_addr;
+}
+//-----------------------------------------------------------------------------
+inline uint32_t RAW_PACKET::GetDstIP() const
+{
+return ipHeader.ip_dst.s_addr;
+}
+//-----------------------------------------------------------------------------
+inline uint16_t RAW_PACKET::GetSrcPort() const
+{
+if (ipHeader.ip_p == 1) // for icmp proto return port 0
+ return 0;
+return ntohs(*((uint16_t*)(pckt + ipHeader.ip_hl * 4)));
+}
+//-----------------------------------------------------------------------------
+inline uint16_t RAW_PACKET::GetDstPort() const
+{
+if (ipHeader.ip_p == 1) // for icmp proto return port 0
+ return 0;
+return ntohs(*((uint16_t*)(pckt + ipHeader.ip_hl * 4 + 2)));
+}
+//-----------------------------------------------------------------------------
+inline bool RAW_PACKET::operator==(const RAW_PACKET & rvalue) const
+{
+if (ipHeader.ip_src.s_addr != rvalue.ipHeader.ip_src.s_addr)
+ return false;
+
+if (ipHeader.ip_dst.s_addr != rvalue.ipHeader.ip_dst.s_addr)
+ return false;
+
+if (ipHeader.ip_p != 1 && rvalue.ipHeader.ip_p != 1)
+ {
+ if (*((uint16_t *)(pckt + ipHeader.ip_hl * 4)) !=
+ *((uint16_t *)(rvalue.pckt + rvalue.ipHeader.ip_hl * 4)))
+ return false;
+
+ if (*((uint16_t *)(pckt + ipHeader.ip_hl * 4 + 2)) !=
+ *((uint16_t *)(rvalue.pckt + rvalue.ipHeader.ip_hl * 4 + 2)))
+ return false;
+ }
+
+if (ipHeader.ip_p != rvalue.ipHeader.ip_p)
+ return false;
+
+return true;
+}
+/*//-----------------------------------------------------------------------------
+inline bool operator==(const RAW_PACKET & lhs, const RAW_PACKET & rhs)
+{
+if (lhs.GetSrcIP() != rhs.GetSrcIP())
+ return false;
+
+if (lhs.GetDstIP() != rhs.GetDstIP())
+ return false;
+
+if (lhs.GetSrcPort() != rhs.GetSrcPort())
+ return false;
+
+if (lhs.GetDstPort() != rhs.GetDstPort())
+ return false;
+
+if (lhs.GetProto() != rhs.GetProto())
+ return false;
+
+return true;
+}*/
+//-----------------------------------------------------------------------------
+inline bool RAW_PACKET::operator<(const RAW_PACKET & rvalue) const
+{
+if (ipHeader.ip_src.s_addr < rvalue.ipHeader.ip_src.s_addr)
+ return true;
+if (ipHeader.ip_src.s_addr > rvalue.ipHeader.ip_src.s_addr)
+ return false;
+
+if (ipHeader.ip_dst.s_addr < rvalue.ipHeader.ip_dst.s_addr)
+ return true;
+if (ipHeader.ip_dst.s_addr > rvalue.ipHeader.ip_dst.s_addr)
+ return false;
+
+if (ipHeader.ip_p != 1 && rvalue.ipHeader.ip_p != 1)
+ {
+ if (*((uint16_t *)(pckt + ipHeader.ip_hl * 4)) <
+ *((uint16_t *)(rvalue.pckt + rvalue.ipHeader.ip_hl * 4)))
+ return true;
+ if (*((uint16_t *)(pckt + ipHeader.ip_hl * 4)) >
+ *((uint16_t *)(rvalue.pckt + rvalue.ipHeader.ip_hl * 4)))
+ return false;
+
+ if (*((uint16_t *)(pckt + ipHeader.ip_hl * 4 + 2)) <
+ *((uint16_t *)(rvalue.pckt + rvalue.ipHeader.ip_hl * 4 + 2)))
+ return true;
+ if (*((uint16_t *)(pckt + ipHeader.ip_hl * 4 + 2)) >
+ *((uint16_t *)(rvalue.pckt + rvalue.ipHeader.ip_hl * 4 + 2)))
+ return false;
+ }
+
+if (ipHeader.ip_p < rvalue.ipHeader.ip_p)
+ return true;
+
+return false;
+}
+//-----------------------------------------------------------------------------
+/*inline bool operator<(const RAW_PACKET & lhs, const RAW_PACKET & rhs)
+{
+if (lhs.GetSrcIP() < rhs.GetSrcIP())
+ return true;
+if (lhs.GetSrcIP() > rhs.GetSrcIP())
+ return false;
+
+if (lhs.GetDstIP() < rhs.GetDstIP())
+ return true;
+if (lhs.GetDstIP() > rhs.GetDstIP())
+ return false;
+
+if (lhs.GetSrcPort() < rhs.GetSrcPort())
+ return true;
+if (lhs.GetSrcPort() > rhs.GetSrcPort())
+ return false;
+
+if (lhs.GetDstPort() < rhs.GetDstPort())
+ return true;
+if (lhs.GetDstPort() > rhs.GetDstPort())
+ return false;
+
+if (lhs.GetProto() < rhs.GetProto())
+ return true;
+
+return false;
+}*/
+//-----------------------------------------------------------------------------
+
+#endif
+
+
--- /dev/null
+ /*
+ $Revision: 1.9 $
+ $Date: 2010/03/11 14:42:04 $
+ $Author: faust $
+ */
+
+/*
+ * Copyright (c) 2001 by Peter Simons <simons@cryp.to>.
+ * All rights reserved.
+ */
+
+#ifndef RESETABLE_VARIABLE_H
+#define RESETABLE_VARIABLE_H
+
+// This is a wrapper class about variables where you want to keep
+// track of whether it has been assigened yet or not.
+
+#include <iostream>
+
+template <typename varT>
+class RESETABLE
+{
+ template <typename varT1>
+ friend std::ostream & operator<<(std::ostream & o, RESETABLE<varT1> v);
+public:
+ typedef varT value_type;
+
+ //-------------------------------------------------------------------------
+ RESETABLE()
+ : value(),
+ is_set(false)
+ {
+ }
+ //-------------------------------------------------------------------------
+ RESETABLE<value_type>(const RESETABLE<value_type> & rvalue)
+ : value(rvalue.value),
+ is_set(rvalue.is_set)
+ {
+ }
+ //-------------------------------------------------------------------------
+ RESETABLE(const value_type& val)
+ : value(val),
+ is_set(true)
+ {
+ }
+ //-------------------------------------------------------------------------
+ RESETABLE<value_type> & operator=(const RESETABLE<value_type> & rvalue)
+ {
+ value = rvalue.value;
+ is_set = rvalue.is_set;
+ return *this;
+ }
+ //-------------------------------------------------------------------------
+ RESETABLE<value_type> & operator= (const value_type& rhs)
+ {
+ value = rhs;
+ is_set = true;
+ return *this;
+ }
+ //-------------------------------------------------------------------------
+ const value_type& const_data() const throw()
+ {
+ return value;
+ }
+ //-------------------------------------------------------------------------
+ value_type& data() throw()
+ {
+ return value;
+ }
+ //-------------------------------------------------------------------------
+ operator const value_type&() const throw()
+ {
+ return value;
+ }
+ //-------------------------------------------------------------------------
+ bool res_empty() const throw()
+ {
+ return !is_set;
+ }
+ //-------------------------------------------------------------------------
+ void reset() throw()
+ {
+ is_set = false;
+ }
+ //-------------------------------------------------------------------------
+protected:
+ value_type value;
+ bool is_set;
+};
+//-----------------------------------------------------------------------------
+template <typename varT>
+std::ostream & operator<<(std::ostream & o, RESETABLE<varT> v)
+{
+ return o << v.value;
+}
+//-------------------------------------------------------------------------
+#endif // RESETABLE_VARIABLE_H
+
--- /dev/null
+#ifndef RS_PACKETSH
+#define RS_PACKETSH
+
+#define RS_MAGIC_LEN (6)
+#define RS_PROTO_VER_LEN (2)
+#define RS_MAX_PACKET_LEN (1048)
+#define RS_LOGIN_LEN (32)
+#define RS_PARAMS_LEN (979)
+
+#define RS_ALIVE_PACKET (0)
+#define RS_CONNECT_PACKET (1)
+#define RS_DISCONNECT_PACKET (2)
+
+#define RS_ID "RSP00"
+
+#include "os_int.h"
+
+struct RS_PACKET_HEADER
+{
+int8_t magic[RS_MAGIC_LEN];
+int8_t protoVer[RS_PROTO_VER_LEN];
+int8_t packetType;
+uint32_t ip;
+uint32_t id;
+int8_t login[RS_LOGIN_LEN];
+int8_t padding[7];
+} __attribute__((__packed__)); // 48 bytes, 6 blocks
+
+struct RS_PACKET_TAIL
+{
+int8_t magic[RS_MAGIC_LEN];
+int8_t params[RS_PARAMS_LEN];
+int8_t padding[7];
+} __attribute__((__packed__)); // 992 bytes, 124 blocks
+
+#endif
--- /dev/null
+#ifndef SERVICE_CONF_H
+#define SERVICE_CONF_H
+
+struct SERVICE_CONF
+{
+string name;
+string comment;
+double cost;
+int payDay;
+};
+
+#endif //SERVICE_CONF_H
+
--- /dev/null
+// =============================================================================\r
+// FILE: StdString.h\r
+// AUTHOR: Joe O'Leary (with outside help noted in comments)\r
+// REMARKS:\r
+// This header file declares the CStdStr template. This template derives\r
+// the Standard C++ Library basic_string<> template and add to it the\r
+// the following conveniences:\r
+// - The full MFC CString set of functions (including implicit cast)\r
+// - writing to/reading from COM IStream interfaces\r
+// - Functional objects for use in STL algorithms\r
+//\r
+// From this template, we intstantiate two classes: CStdStringA and\r
+// CStdStringW. The name "CStdString" is just a #define of one of these,\r
+// based upone the _UNICODE macro setting\r
+//\r
+// This header also declares our own version of the MFC/ATL UNICODE-MBCS\r
+// conversion macros. Our version looks exactly like the Microsoft's to\r
+// facilitate portability.\r
+//\r
+// NOTE:\r
+// If you you use this in an MFC or ATL build, you should include either\r
+// afx.h or atlbase.h first, as appropriate.\r
+//\r
+// PEOPLE WHO HAVE CONTRIBUTED TO THIS CLASS:\r
+//\r
+// Several people have helped me iron out problems and othewise improve\r
+// this class. OK, this is a long list but in my own defense, this code\r
+// has undergone two major rewrites. Many of the improvements became\r
+// necessary after I rewrote the code as a template. Others helped me\r
+// improve the CString facade.\r
+//\r
+// Anyway, these people are (in chronological order):\r
+//\r
+// - Pete the Plumber (???)\r
+// - Julian Selman\r
+// - Chris (of Melbsys)\r
+// - Dave Plummer\r
+// - John C Sipos\r
+// - Chris Sells\r
+// - Nigel Nunn\r
+// - Fan Xia\r
+// - Matthew Williams\r
+// - Carl Engman\r
+// - Mark Zeren\r
+// - Craig Watson\r
+// - Rich Zuris\r
+// - Karim Ratib\r
+// - Chris Conti\r
+// - Baptiste Lepilleur\r
+// - Greg Pickles\r
+// - Jim Cline\r
+// - Jeff Kohn\r
+// - Todd Heckel\r
+// - Ullrich Pollähne\r
+// - Joe Vitaterna\r
+// - Joe Woodbury\r
+// - Aaron (no last name)\r
+// - Joldakowski (???)\r
+// - Scott Hathaway\r
+// - Eric Nitzche\r
+// - Pablo Presedo\r
+// - Farrokh Nejadlotfi\r
+// - Jason Mills\r
+// - Igor Kholodov\r
+// - Mike Crusader\r
+// - John James\r
+// - Wang Haifeng\r
+// - Tim Dowty\r
+// - Arnt Witteveen\r
+// - Glen Maynard\r
+// - Paul DeMarco\r
+// - Bagira (full name?)\r
+// - Ronny Schulz\r
+// - Jakko Van Hunen\r
+// - Charles G\r
+//\r
+// REVISION HISTORY\r
+// 2003-JUL-10 - Thanks to Charles G for making me realize my 'FmtArg' fixes\r
+// had inadvertently broken the DLL-export code (which is\r
+// normally commented out. I had to move it up higher. Also\r
+// this helped me catch a bug in ssicoll that would prevent\r
+// compilation, otherwise.\r
+//\r
+// 2003-MAR-14 - Thanks to Jakko Van Hunen for pointing out a copy-and-paste\r
+// bug in one of the overloads of FmtArg.\r
+//\r
+// 2003-MAR-10 - Thanks to Ronny Schulz for (twice!) sending me some changes\r
+// to help CStdString build on SGI and for pointing out an\r
+// error in placement of my preprocessor macros for ssfmtmsg.\r
+//\r
+// 2002-NOV-26 - Thanks to Bagira for pointing out that my implementation of\r
+// SpanExcluding was not properly handling the case in which\r
+// the string did NOT contain any of the given characters\r
+//\r
+// 2002-OCT-21 - Many thanks to Paul DeMarco who was invaluable in helping me\r
+// get this code working with Borland's free compiler as well\r
+// as the Dev-C++ compiler (available free at SourceForge).\r
+//\r
+// 2002-SEP-13 - Thanks to Glen Maynard who helped me get rid of some loud\r
+// but harmless warnings that were showing up on g++. Glen\r
+// also pointed out that some pre-declarations of FmtArg<>\r
+// specializations were unnecessary (and no good on G++)\r
+//\r
+// 2002-JUN-26 - Thanks to Arnt Witteveen for pointing out that I was using\r
+// static_cast<> in a place in which I should have been using\r
+// reinterpret_cast<> (the ctor for unsigned char strings).\r
+// That's what happens when I don't unit-test properly!\r
+// Arnt also noticed that CString was silently correcting the\r
+// 'nCount' argument to Left() and Right() where CStdString was\r
+// not (and crashing if it was bad). That is also now fixed!\r
+//\r
+// 2002-FEB-25 - Thanks to Tim Dowty for pointing out (and giving me the fix\r
+// for) a conversion problem with non-ASCII MBCS characters.\r
+// CStdString is now used in my favorite commercial MP3 player!\r
+//\r
+// 2001-DEC-06 - Thanks to Wang Haifeng for spotting a problem in one of the\r
+// assignment operators (for _bstr_t) that would cause compiler\r
+// errors when refcounting protection was turned off.\r
+//\r
+// 2001-NOV-27 - Remove calls to operator!= which involve reverse_iterators\r
+// due to a conflict with the rel_ops operator!=. Thanks to\r
+// John James for pointing this out.\r
+//\r
+// 2001-OCT-29 - Added a minor range checking fix for the Mid function to\r
+// make it as forgiving as CString's version is. Thanks to\r
+// Igor Kholodov for noticing this. \r
+// - Added a specialization of std::swap for CStdString. Thanks\r
+// to Mike Crusader for suggesting this! It's commented out\r
+// because you're not supposed to inject your own code into the\r
+// 'std' namespace. But if you don't care about that, it's\r
+// there if you want it\r
+// - Thanks to Jason Mills for catching a case where CString was\r
+// more forgiving in the Delete() function than I was.\r
+//\r
+// 2001-JUN-06 - I was violating the Standard name lookup rules stated\r
+// in [14.6.2(3)]. None of the compilers I've tried so\r
+// far apparently caught this but HP-UX aCC 3.30 did. The\r
+// fix was to add 'this->' prefixes in many places.\r
+// Thanks to Farrokh Nejadlotfi for this!\r
+//\r
+// 2001-APR-27 - StreamLoad was calculating the number of BYTES in one\r
+// case, not characters. Thanks to Pablo Presedo for this.\r
+//\r
+// 2001-FEB-23 - Replace() had a bug which caused infinite loops if the\r
+// source string was empty. Fixed thanks to Eric Nitzsche.\r
+//\r
+// 2001-FEB-23 - Scott Hathaway was a huge help in providing me with the\r
+// ability to build CStdString on Sun Unix systems. He\r
+// sent me detailed build reports about what works and what\r
+// does not. If CStdString compiles on your Unix box, you\r
+// can thank Scott for it.\r
+//\r
+// 2000-DEC-29 - Joldakowski noticed one overload of Insert failed to do a\r
+// range check as CString's does. Now fixed -- thanks!\r
+//\r
+// 2000-NOV-07 - Aaron pointed out that I was calling static member\r
+// functions of char_traits via a temporary. This was not\r
+// technically wrong, but it was unnecessary and caused\r
+// problems for poor old buggy VC5. Thanks Aaron!\r
+//\r
+// 2000-JUL-11 - Joe Woodbury noted that the CString::Find docs don't match\r
+// what the CString::Find code really ends up doing. I was\r
+// trying to match the docs. Now I match the CString code\r
+// - Joe also caught me truncating strings for GetBuffer() calls\r
+// when the supplied length was less than the current length.\r
+//\r
+// 2000-MAY-25 - Better support for STLPORT's Standard library distribution\r
+// - Got rid of the NSP macro - it interfered with Koenig lookup\r
+// - Thanks to Joe Woodbury for catching a TrimLeft() bug that\r
+// I introduced in January. Empty strings were not getting\r
+// trimmed\r
+//\r
+// 2000-APR-17 - Thanks to Joe Vitaterna for pointing out that ReverseFind\r
+// is supposed to be a const function.\r
+//\r
+// 2000-MAR-07 - Thanks to Ullrich Pollähne for catching a range bug in one\r
+// of the overloads of assign.\r
+//\r
+// 2000-FEB-01 - You can now use CStdString on the Mac with CodeWarrior!\r
+// Thanks to Todd Heckel for helping out with this.\r
+//\r
+// 2000-JAN-23 - Thanks to Jim Cline for pointing out how I could make the\r
+// Trim() function more efficient.\r
+// - Thanks to Jeff Kohn for prompting me to find and fix a typo\r
+// in one of the addition operators that takes _bstr_t.\r
+// - Got rid of the .CPP file - you only need StdString.h now!\r
+//\r
+// 1999-DEC-22 - Thanks to Greg Pickles for helping me identify a problem\r
+// with my implementation of CStdString::FormatV in which\r
+// resulting string might not be properly NULL terminated.\r
+//\r
+// 1999-DEC-06 - Chris Conti pointed yet another basic_string<> assignment\r
+// bug that MS has not fixed. CStdString did nothing to fix\r
+// it either but it does now! The bug was: create a string\r
+// longer than 31 characters, get a pointer to it (via c_str())\r
+// and then assign that pointer to the original string object.\r
+// The resulting string would be empty. Not with CStdString!\r
+//\r
+// 1999-OCT-06 - BufferSet was erasing the string even when it was merely\r
+// supposed to shrink it. Fixed. Thanks to Chris Conti.\r
+// - Some of the Q172398 fixes were not checking for assignment-\r
+// to-self. Fixed. Thanks to Baptiste Lepilleur.\r
+//\r
+// 1999-AUG-20 - Improved Load() function to be more efficient by using \r
+// SizeOfResource(). Thanks to Rich Zuris for this.\r
+// - Corrected resource ID constructor, again thanks to Rich.\r
+// - Fixed a bug that occurred with UNICODE characters above\r
+// the first 255 ANSI ones. Thanks to Craig Watson. \r
+// - Added missing overloads of TrimLeft() and TrimRight().\r
+// Thanks to Karim Ratib for pointing them out\r
+//\r
+// 1999-JUL-21 - Made all calls to GetBuf() with no args check length first.\r
+//\r
+// 1999-JUL-10 - Improved MFC/ATL independence of conversion macros\r
+// - Added SS_NO_REFCOUNT macro to allow you to disable any\r
+// reference-counting your basic_string<> impl. may do.\r
+// - Improved ReleaseBuffer() to be as forgiving as CString.\r
+// Thanks for Fan Xia for helping me find this and to\r
+// Matthew Williams for pointing it out directly.\r
+//\r
+// 1999-JUL-06 - Thanks to Nigel Nunn for catching a very sneaky bug in\r
+// ToLower/ToUpper. They should call GetBuf() instead of\r
+// data() in order to ensure the changed string buffer is not\r
+// reference-counted (in those implementations that refcount).\r
+//\r
+// 1999-JUL-01 - Added a true CString facade. Now you can use CStdString as\r
+// a drop-in replacement for CString. If you find this useful,\r
+// you can thank Chris Sells for finally convincing me to give\r
+// in and implement it.\r
+// - Changed operators << and >> (for MFC CArchive) to serialize\r
+// EXACTLY as CString's do. So now you can send a CString out\r
+// to a CArchive and later read it in as a CStdString. I have\r
+// no idea why you would want to do this but you can. \r
+//\r
+// 1999-JUN-21 - Changed the CStdString class into the CStdStr template.\r
+// - Fixed FormatV() to correctly decrement the loop counter.\r
+// This was harmless bug but a bug nevertheless. Thanks to\r
+// Chris (of Melbsys) for pointing it out\r
+// - Changed Format() to try a normal stack-based array before\r
+// using to _alloca().\r
+// - Updated the text conversion macros to properly use code\r
+// pages and to fit in better in MFC/ATL builds. In other\r
+// words, I copied Microsoft's conversion stuff again. \r
+// - Added equivalents of CString::GetBuffer, GetBufferSetLength\r
+// - new sscpy() replacement of CStdString::CopyString()\r
+// - a Trim() function that combines TrimRight() and TrimLeft().\r
+//\r
+// 1999-MAR-13 - Corrected the "NotSpace" functional object to use _istpace()\r
+// instead of _isspace() Thanks to Dave Plummer for this.\r
+//\r
+// 1999-FEB-26 - Removed errant line (left over from testing) that #defined\r
+// _MFC_VER. Thanks to John C Sipos for noticing this.\r
+//\r
+// 1999-FEB-03 - Fixed a bug in a rarely-used overload of operator+() that\r
+// caused infinite recursion and stack overflow\r
+// - Added member functions to simplify the process of\r
+// persisting CStdStrings to/from DCOM IStream interfaces \r
+// - Added functional objects (e.g. StdStringLessNoCase) that\r
+// allow CStdStrings to be used as keys STL map objects with\r
+// case-insensitive comparison \r
+// - Added array indexing operators (i.e. operator[]). I\r
+// originally assumed that these were unnecessary and would be\r
+// inherited from basic_string. However, without them, Visual\r
+// C++ complains about ambiguous overloads when you try to use\r
+// them. Thanks to Julian Selman to pointing this out. \r
+//\r
+// 1998-FEB-?? - Added overloads of assign() function to completely account\r
+// for Q172398 bug. Thanks to "Pete the Plumber" for this\r
+//\r
+// 1998-FEB-?? - Initial submission\r
+//\r
+// COPYRIGHT:\r
+// 2002 Joseph M. O'Leary. This code is 100% free. Use it anywhere you\r
+// want. Rewrite it, restructure it, whatever. If you can write software\r
+// that makes money off of it, good for you. I kinda like capitalism. \r
+// Please don't blame me if it causes your $30 billion dollar satellite\r
+// explode in orbit. If you redistribute it in any form, I'd appreciate it\r
+// if you would leave this notice here.\r
+//\r
+// If you find any bugs, please let me know:\r
+//\r
+// jmoleary@earthlink.net\r
+// http://www.joeo.net\r
+//\r
+// The latest version of this code should always be available at the\r
+// following link:\r
+//\r
+// http://www.joeo.net/code/StdString.zip\r
+// =============================================================================\r
+\r
+// Avoid multiple inclusion the VC++ way,\r
+// Turn off browser references\r
+// Turn off unavoidable compiler warnings\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER > 1100)\r
+ #pragma once\r
+ #pragma component(browser, off, references, "CStdString")\r
+ #pragma warning (disable : 4290) // C++ Exception Specification ignored\r
+ #pragma warning (disable : 4127) // Conditional expression is constant\r
+ #pragma warning (disable : 4097) // typedef name used as synonym for class name\r
+#endif\r
+\r
+// Borland warnings to turn off\r
+#ifdef __BORLANDC__\r
+ #pragma option push -w-inl\r
+// #pragma warn -inl // Turn off inline function warnings\r
+#endif\r
+\r
+#ifndef STDSTRING_H\r
+#define STDSTRING_H\r
+\r
+// MACRO: SS_UNSIGNED\r
+// ------------------\r
+// This macro causes the addition of a constructor and assignment operator\r
+// which take unsigned characters. CString has such functions and in order\r
+// to provide maximum CString-compatability, this code needs them as well.\r
+// In practice you will likely never need these functions...\r
+\r
+//#define SS_UNSIGNED\r
+\r
+#ifdef SS_ALLOW_UNSIGNED_CHARS\r
+ #define SS_UNSIGNED\r
+#endif\r
+\r
+// MACRO: SS_SAFE_FORMAT\r
+// ---------------------\r
+// This macro provides limited compatability with a questionable CString\r
+// "feature". You can define it in order to avoid a common problem that\r
+// people encounter when switching from CString to CStdString.\r
+//\r
+// To illustrate the problem -- With CString, you can do this:\r
+//\r
+// CString sName("Joe");\r
+// CString sTmp;\r
+// sTmp.Format("My name is %s", sName); // WORKS!\r
+//\r
+// However if you were to try this with CStdString, your program would\r
+// crash.\r
+//\r
+// CStdString sName("Joe");\r
+// CStdString sTmp;\r
+// sTmp.Format("My name is %s", sName); // CRASHES!\r
+//\r
+// You must explicitly call c_str() or cast the object to the proper type\r
+//\r
+// sTmp.Format("My name is %s", sName.c_str()); // WORKS!\r
+// sTmp.Format("My name is %s", static_cast<PCSTR>(sName));// WORKS!\r
+// sTmp.Format("My name is %s", (PCSTR)sName);// WORKS!\r
+//\r
+// This is because it is illegal to pass anything but a POD type as a\r
+// variadic argument to a variadic function (i.e. as one of the "..."\r
+// arguments). The type const char* is a POD type. The type CStdString\r
+// is not. Of course, neither is the type CString, but CString lets you do\r
+// it anyway due to the way they laid out the class in binary. I have no\r
+// control over this in CStdString since I derive from whatever\r
+// implementation of basic_string is available.\r
+//\r
+// However if you have legacy code (which does this) that you want to take\r
+// out of the MFC world and you don't want to rewrite all your calls to\r
+// Format(), then you can define this flag and it will no longer crash.\r
+//\r
+// Note however that this ONLY works for Format(), not sprintf, fprintf, \r
+// etc. If you pass a CStdString object to one of those functions, your\r
+// program will crash. Not much I can do to get around this, short of\r
+// writing substitutes for those functions as well.\r
+\r
+#define SS_SAFE_FORMAT // use new template style Format() function\r
+\r
+\r
+// MACRO: SS_NO_IMPLICIT_CAST\r
+// --------------------------\r
+// Some people don't like the implicit cast to const char* (or rather to\r
+// const CT*) that CStdString (and MFC's CString) provide. That was the\r
+// whole reason I created this class in the first place, but hey, whatever\r
+// bakes your cake. Just #define this macro to get rid of the the implicit\r
+// cast.\r
+\r
+//#define SS_NO_IMPLICIT_CAST // gets rid of operator const CT*()\r
+\r
+\r
+// MACRO: SS_NO_REFCOUNT\r
+// ---------------------\r
+// turns off reference counting at the assignment level. Only needed\r
+// for the version of basic_string<> that comes with Visual C++ versions\r
+// 6.0 or earlier, and only then in some heavily multithreaded scenarios.\r
+// Uncomment it if you feel you need it.\r
+\r
+//#define SS_NO_REFCOUNT\r
+\r
+// MACRO: SS_WIN32\r
+// ---------------\r
+// When this flag is set, we are building code for the Win32 platform and\r
+// may use Win32 specific functions (such as LoadString). This gives us\r
+// a couple of nice extras for the code.\r
+//\r
+// Obviously, Microsoft's is not the only compiler available for Win32 out\r
+// there. So I can't just check to see if _MSC_VER is defined to detect\r
+// if I'm building on Win32. So for now, if you use MS Visual C++ or\r
+// Borland's compiler, I turn this on. Otherwise you may turn it on\r
+// yourself, if you prefer\r
+#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(_WIN32)\r
+ #define SS_WIN32\r
+#endif\r
+\r
+// MACRO: SS_ANSI\r
+// --------------\r
+// When this macro is defined, the code attempts only to use ANSI/ISO\r
+// standard library functions to do it's work. It will NOT attempt to use\r
+// any Win32 of Visual C++ specific functions -- even if they are\r
+// available. You may define this flag yourself to prevent any Win32\r
+// of VC++ specific functions from being called.\r
+\r
+// If we're not on Win32, we MUST use an ANSI build\r
+#ifndef SS_WIN32\r
+ #if !defined(SS_NO_ANSI)\r
+ #define SS_ANSI\r
+ #endif\r
+#endif\r
+\r
+// MACRO: SS_ALLOCA\r
+// ----------------\r
+// Some implementations of the Standard C Library have a non-standard\r
+// function known as alloca(). This functions allows one to allocate a\r
+// variable amount of memory on the stack. It comes in very useful for\r
+// the ASCII/MBCS conversion macros.\r
+//\r
+// Here we attempt to determine automatically if alloca() is available on\r
+// this platform. If so we define SS_ALLOCA to be the name of the alloca\r
+// function. If SS_ALLOCA is undefined later on, then the conversion\r
+// macros will not be compiled.\r
+//\r
+// You may prevent SS_ALLOCA\r
+\r
+\r
+\r
+// Avoid legacy code screw up: if _UNICODE is defined, UNICODE must be as well\r
+\r
+#if defined (_UNICODE) && !defined (UNICODE)\r
+ #define UNICODE\r
+#endif\r
+#if defined (UNICODE) && !defined (_UNICODE)\r
+ #define _UNICODE\r
+#endif\r
+\r
+// -----------------------------------------------------------------------------\r
+// MIN and MAX. The Standard C++ template versions go by so many names (at\r
+// at least in the MS implementation) that you never know what's available\r
+// -----------------------------------------------------------------------------\r
+template<class Type>\r
+inline const Type& SSMIN(const Type& arg1, const Type& arg2)\r
+{\r
+ return arg2 < arg1 ? arg2 : arg1;\r
+}\r
+template<class Type>\r
+inline const Type& SSMAX(const Type& arg1, const Type& arg2)\r
+{\r
+ return arg2 > arg1 ? arg2 : arg1;\r
+}\r
+\r
+// If they have not #included W32Base.h (part of my W32 utility library) then\r
+// we need to define some stuff. Otherwise, this is all defined there.\r
+\r
+#if !defined(W32BASE_H)\r
+\r
+ // If they want us to use only standard C++ stuff (no Win32 stuff)\r
+\r
+ #ifdef SS_ANSI\r
+\r
+ // On Win32 we have TCHAR.H so just include it. This is NOT violating\r
+ // the spirit of SS_ANSI as we are not calling any Win32 functions here.\r
+ \r
+ #ifdef SS_WIN32\r
+\r
+ #include <TCHAR.H>\r
+ #include <WTYPES.H>\r
+ #ifndef STRICT\r
+ #define STRICT\r
+ #endif\r
+\r
+ // ... but on non-Win32 platforms, we must #define the types we need.\r
+\r
+ #else\r
+\r
+ typedef const char* PCSTR;\r
+ typedef char* PSTR;\r
+ typedef const wchar_t* PCWSTR;\r
+ typedef wchar_t* PWSTR;\r
+ #ifdef UNICODE\r
+ typedef wchar_t TCHAR;\r
+ #else\r
+ typedef char TCHAR;\r
+ #endif\r
+ typedef wchar_t OLECHAR;\r
+\r
+ #endif // #ifndef _WIN32\r
+\r
+\r
+ // Make sure ASSERT and verify are defined using only ANSI stuff\r
+\r
+ #ifndef ASSERT\r
+ #include <assert.h>\r
+ #define ASSERT(f) assert((f))\r
+ #endif\r
+ #ifndef VERIFY\r
+ #ifdef _DEBUG\r
+ #define VERIFY(x) ASSERT((x))\r
+ #else\r
+ #define VERIFY(x) x\r
+ #endif\r
+ #endif\r
+\r
+ #else // ...else SS_ANSI is NOT defined\r
+\r
+ #include <TCHAR.H>\r
+ #include <WTYPES.H>\r
+ #ifndef STRICT\r
+ #define STRICT\r
+ #endif\r
+\r
+ // Make sure ASSERT and verify are defined\r
+\r
+ #ifndef ASSERT\r
+ #include <crtdbg.h>\r
+ #define ASSERT(f) _ASSERTE((f))\r
+ #endif\r
+ #ifndef VERIFY\r
+ #ifdef _DEBUG\r
+ #define VERIFY(x) ASSERT((x))\r
+ #else\r
+ #define VERIFY(x) x\r
+ #endif\r
+ #endif\r
+\r
+ #endif // #ifdef SS_ANSI\r
+\r
+ #ifndef UNUSED\r
+ #define UNUSED(x) x\r
+ #endif\r
+\r
+#endif // #ifndef W32BASE_H\r
+\r
+// Standard headers needed\r
+\r
+#include <string> // basic_string\r
+#include <algorithm> // for_each, etc.\r
+#include <functional> // for StdStringLessNoCase, et al\r
+#include <locale> // for various facets\r
+\r
+// If this is a recent enough version of VC include comdef.h, so we can write\r
+// member functions to deal with COM types & compiler support classes e.g. _bstr_t\r
+\r
+#if defined (_MSC_VER) && (_MSC_VER >= 1100)\r
+ #include <comdef.h>\r
+ #define SS_INC_COMDEF // signal that we #included MS comdef.h file\r
+ #define STDSTRING_INC_COMDEF\r
+ #define SS_NOTHROW __declspec(nothrow)\r
+#else\r
+ #define SS_NOTHROW\r
+#endif\r
+\r
+#ifndef TRACE\r
+ #define TRACE_DEFINED_HERE\r
+ #define TRACE\r
+#endif\r
+\r
+// Microsoft defines PCSTR, PCWSTR, etc, but no PCTSTR. I hate to use the\r
+// versions with the "L" in front of them because that's a leftover from Win 16\r
+// days, even though it evaluates to the same thing. Therefore, Define a PCSTR\r
+// as an LPCTSTR.\r
+\r
+#if !defined(PCTSTR) && !defined(PCTSTR_DEFINED)\r
+ typedef const TCHAR* PCTSTR;\r
+ #define PCTSTR_DEFINED\r
+#endif\r
+\r
+#if !defined(PCOLESTR) && !defined(PCOLESTR_DEFINED)\r
+ typedef const OLECHAR* PCOLESTR;\r
+ #define PCOLESTR_DEFINED\r
+#endif\r
+\r
+#if !defined(POLESTR) && !defined(POLESTR_DEFINED)\r
+ typedef OLECHAR* POLESTR;\r
+ #define POLESTR_DEFINED\r
+#endif\r
+\r
+#if !defined(PCUSTR) && !defined(PCUSTR_DEFINED)\r
+ typedef const unsigned char* PCUSTR;\r
+ typedef unsigned char* PUSTR;\r
+ #define PCUSTR_DEFINED\r
+#endif\r
+\r
+\r
+// SGI compiler 7.3 doesnt know these types - oh and btw, remember to use\r
+// -LANG:std in the CXX Flags\r
+#if defined(__sgi)\r
+ typedef unsigned long DWORD;\r
+ typedef void * LPCVOID;\r
+#endif\r
+\r
+\r
+// SS_USE_FACET macro and why we need it:\r
+//\r
+// Since I'm a good little Standard C++ programmer, I use locales. Thus, I\r
+// need to make use of the use_facet<> template function here. Unfortunately,\r
+// this need is complicated by the fact the MS' implementation of the Standard\r
+// C++ Library has a non-standard version of use_facet that takes more\r
+// arguments than the standard dictates. Since I'm trying to write CStdString\r
+// to work with any version of the Standard library, this presents a problem.\r
+//\r
+// The upshot of this is that I can't do 'use_facet' directly. The MS' docs\r
+// tell me that I have to use a macro, _USE() instead. Since _USE obviously\r
+// won't be available in other implementations, this means that I have to write\r
+// my OWN macro -- SS_USE_FACET -- that evaluates either to _USE or to the\r
+// standard, use_facet.\r
+//\r
+// If you are having trouble with the SS_USE_FACET macro, in your implementation\r
+// of the Standard C++ Library, you can define your own version of SS_USE_FACET.\r
+#ifndef schMSG\r
+ #define schSTR(x) #x\r
+ #define schSTR2(x) schSTR(x)\r
+ #define schMSG(desc) message(__FILE__ "(" schSTR2(__LINE__) "):" #desc)\r
+#endif\r
+\r
+#ifndef SS_USE_FACET\r
+ // STLPort #defines a macro (__STL_NO_EXPLICIT_FUNCTION_TMPL_ARGS) for\r
+ // all MSVC builds, erroneously in my opinion. It causes problems for\r
+ // my SS_ANSI builds. In my code, I always comment out that line. You'll\r
+ // find it in \stlport\config\stl_msvc.h\r
+ #if defined(__SGI_STL_PORT) && (__SGI_STL_PORT >= 0x400 )\r
+ #if defined(__STL_NO_EXPLICIT_FUNCTION_TMPL_ARGS) && defined(_MSC_VER)\r
+ #ifdef SS_ANSI\r
+ #pragma schMSG(__STL_NO_EXPLICIT_FUNCTION_TMPL_ARGS defined!!)\r
+ #endif\r
+ #endif\r
+ #define SS_USE_FACET(loc, fac) std::use_facet<fac >(loc)\r
+ #elif defined(_MSC_VER )\r
+ #define SS_USE_FACET(loc, fac) std::_USE(loc, fac)\r
+\r
+ // ...and\r
+ #elif defined(_RWSTD_NO_TEMPLATE_ON_RETURN_TYPE)\r
+ #define SS_USE_FACET(loc, fac) std::use_facet(loc, (fac*)0)\r
+ #else\r
+ #define SS_USE_FACET(loc, fac) std::use_facet<fac >(loc)\r
+ #endif\r
+#endif\r
+\r
+// =============================================================================\r
+// UNICODE/MBCS conversion macros. Made to work just like the MFC/ATL ones.\r
+// =============================================================================\r
+\r
+#include <wchar.h> // Added to Std Library with Amendment #1.\r
+\r
+// First define the conversion helper functions. We define these regardless of\r
+// any preprocessor macro settings since their names won't collide. \r
+\r
+// Not sure if we need all these headers. I believe ANSI says we do.\r
+\r
+#include <stdio.h>\r
+#include <stdarg.h>\r
+#include <wctype.h>\r
+#include <ctype.h>\r
+#include <stdlib.h>\r
+#ifndef va_start\r
+ #include <varargs.h>\r
+#endif\r
+\r
+// StdCodeCvt - made to look like Win32 functions WideCharToMultiByte\r
+// and MultiByteToWideChar but uses locales in SS_ANSI\r
+// builds\r
+//typedef int mbstate_t;\r
+#if defined (SS_ANSI) || !defined (SS_WIN32)\r
+\r
+ typedef std::codecvt<wchar_t, char, std::mbstate_t> SSCodeCvt;\r
+\r
+\r
+ inline PWSTR StdCodeCvt(PWSTR pW, PCSTR pA, int nChars,\r
+ const std::locale& loc=std::locale())\r
+ {\r
+ ASSERT(0 != pA);\r
+ ASSERT(0 != pW);\r
+ pW[0] = '\0';\r
+ PCSTR pBadA = 0;\r
+ PWSTR pBadW = 0;\r
+ SSCodeCvt::result res = SSCodeCvt::ok;\r
+ const SSCodeCvt& conv = SS_USE_FACET(loc, SSCodeCvt);\r
+ SSCodeCvt::state_type st= { 0 };\r
+ res = conv.in(st,\r
+ pA, pA + nChars, pBadA,\r
+ pW, pW + nChars, pBadW);\r
+ ASSERT(SSCodeCvt::ok == res);\r
+ return pW;\r
+ }\r
+ inline PWSTR StdCodeCvt(PWSTR pW, PCUSTR pA, int nChars,\r
+ const std::locale& loc=std::locale())\r
+ {\r
+ return StdCodeCvt(pW, (PCSTR)pA, nChars, loc);\r
+ }\r
+\r
+ inline PSTR StdCodeCvt(PSTR pA, PCWSTR pW, int nChars,\r
+ const std::locale& loc=std::locale())\r
+ {\r
+ ASSERT(0 != pA);\r
+ ASSERT(0 != pW);\r
+ pA[0] = '\0';\r
+ PSTR pBadA = 0;\r
+ PCWSTR pBadW = 0;\r
+ SSCodeCvt::result res = SSCodeCvt::ok;\r
+ const SSCodeCvt& conv = SS_USE_FACET(loc, SSCodeCvt);\r
+ SSCodeCvt::state_type st= { 0 };\r
+ res = conv.out(st,\r
+ pW, pW + nChars, pBadW,\r
+ pA, pA + nChars, pBadA);\r
+ ASSERT(SSCodeCvt::ok == res);\r
+ return pA;\r
+ }\r
+ inline PUSTR StdCodeCvt(PUSTR pA, PCWSTR pW, int nChars,\r
+ const std::locale& loc=std::locale())\r
+ {\r
+ return (PUSTR)StdCodeCvt((PSTR)pA, pW, nChars, loc);\r
+ }\r
+\r
+#else // ...or are we doing things assuming win32 and Visual C++?\r
+\r
+ #include <malloc.h> // needed for _alloca\r
+\r
+ inline PWSTR StdCodeCvt(PWSTR pW, PCSTR pA, int nChars, UINT acp=CP_ACP)\r
+ {\r
+ ASSERT(0 != pA);\r
+ ASSERT(0 != pW);\r
+ pW[0] = '\0';\r
+ MultiByteToWideChar(acp, 0, pA, -1, pW, nChars);\r
+ return pW;\r
+ }\r
+ inline PWSTR StdCodeCvt(PWSTR pW, PCUSTR pA, int nChars, UINT acp=CP_ACP)\r
+ {\r
+ return StdCodeCvt(pW, (PCSTR)pA, nChars, acp);\r
+ }\r
+\r
+ inline PSTR StdCodeCvt(PSTR pA, PCWSTR pW, int nChars, UINT acp=CP_ACP)\r
+ {\r
+ ASSERT(0 != pA);\r
+ ASSERT(0 != pW);\r
+ pA[0] = '\0';\r
+ WideCharToMultiByte(acp, 0, pW, -1, pA, nChars, 0, 0);\r
+ return pA;\r
+ }\r
+ inline PUSTR StdCodeCvt(PUSTR pA, PCWSTR pW, int nChars, UINT acp=CP_ACP)\r
+ {\r
+ return (PUSTR)StdCodeCvt((PSTR)pA, pW, nChars, acp);\r
+ }\r
+\r
+#endif\r
+// Unicode/MBCS conversion macros are only available on implementations of\r
+// the "C" library that have the non-standard _alloca function. As far as I\r
+// know that's only Microsoft's though I've hear that the function exits\r
+// elsewhere. \r
+ \r
+#if defined(SS_ALLOCA) && !defined SS_NO_CONVERSION\r
+\r
+ #include <malloc.h> // needed for _alloca\r
+\r
+\r
+ // Define our conversion macros to look exactly like Microsoft's to\r
+ // facilitate using this stuff both with and without MFC/ATL\r
+\r
+ #ifdef _CONVERSION_USES_THREAD_LOCALE\r
+ #ifndef _DEBUG\r
+ #define SSCVT int _cvt; _cvt; UINT _acp=GetACP(); \\r
+ _acp; PCWSTR _pw; _pw; PCSTR _pa; _pa\r
+ #else\r
+ #define SSCVT int _cvt = 0; _cvt; UINT _acp=GetACP();\\r
+ _acp; PCWSTR _pw=0; _pw; PCSTR _pa=0; _pa\r
+ #endif\r
+ #else\r
+ #ifndef _DEBUG\r
+ #define SSCVT int _cvt; _cvt; UINT _acp=CP_ACP; _acp;\\r
+ PCWSTR _pw; _pw; PCSTR _pa; _pa\r
+ #else\r
+ #define SSCVT int _cvt = 0; _cvt; UINT _acp=CP_ACP; \\r
+ _acp; PCWSTR _pw=0; _pw; PCSTR _pa=0; _pa\r
+ #endif\r
+ #endif\r
+\r
+ #ifdef _CONVERSION_USES_THREAD_LOCALE\r
+ #define SSA2W(pa) (\\r
+ ((_pa = pa) == 0) ? 0 : (\\r
+ _cvt = (sslen(_pa)+1),\\r
+ StdCodeCvt((PWSTR) _alloca(_cvt*2), _pa, _cvt, _acp)))\r
+ #define SSW2A(pw) (\\r
+ ((_pw = pw) == 0) ? 0 : (\\r
+ _cvt = (sslen(_pw)+1)*2,\\r
+ StdW2AHelper((LPSTR) _alloca(_cvt), _pw, _cvt, _acp)))\r
+ #else\r
+ #define SSA2W(pa) (\\r
+ ((_pa = pa) == 0) ? 0 : (\\r
+ _cvt = (sslen(_pa)+1),\\r
+ StdCodeCvt((PWSTR) _alloca(_cvt*2), _pa, _cvt)))\r
+ #define SSW2A(pw) (\\r
+ ((_pw = pw) == 0) ? 0 : (\\r
+ _cvt = (sslen(_pw)+1)*2,\\r
+ StdCodeCvt((LPSTR) _alloca(_cvt), _pw, _cvt)))\r
+ #endif\r
+\r
+ #define SSA2CW(pa) ((PCWSTR)SSA2W((pa)))\r
+ #define SSW2CA(pw) ((PCSTR)SSW2A((pw)))\r
+\r
+ #ifdef UNICODE\r
+ #define SST2A SSW2A\r
+ #define SSA2T SSA2W\r
+ #define SST2CA SSW2CA\r
+ #define SSA2CT SSA2CW\r
+ inline PWSTR SST2W(PTSTR p) { return p; }\r
+ inline PTSTR SSW2T(PWSTR p) { return p; }\r
+ inline PCWSTR SST2CW(PCTSTR p) { return p; }\r
+ inline PCTSTR SSW2CT(PCWSTR p) { return p; }\r
+ #else\r
+ #define SST2W SSA2W\r
+ #define SSW2T SSW2A\r
+ #define SST2CW SSA2CW\r
+ #define SSW2CT SSW2CA\r
+ inline PSTR SST2A(PTSTR p) { return p; }\r
+ inline PTSTR SSA2T(PSTR p) { return p; }\r
+ inline PCSTR SST2CA(PCTSTR p) { return p; }\r
+ inline PCTSTR SSA2CT(PCSTR p) { return p; }\r
+ #endif // #ifdef UNICODE\r
+\r
+ #if defined(UNICODE)\r
+ // in these cases the default (TCHAR) is the same as OLECHAR\r
+ inline PCOLESTR SST2COLE(PCTSTR p) { return p; }\r
+ inline PCTSTR SSOLE2CT(PCOLESTR p) { return p; }\r
+ inline POLESTR SST2OLE(PTSTR p) { return p; }\r
+ inline PTSTR SSOLE2T(POLESTR p) { return p; }\r
+ #elif defined(OLE2ANSI)\r
+ // in these cases the default (TCHAR) is the same as OLECHAR\r
+ inline PCOLESTR SST2COLE(PCTSTR p) { return p; }\r
+ inline PCTSTR SSOLE2CT(PCOLESTR p) { return p; }\r
+ inline POLESTR SST2OLE(PTSTR p) { return p; }\r
+ inline PTSTR SSOLE2T(POLESTR p) { return p; }\r
+ #else\r
+ //CharNextW doesn't work on Win95 so we use this\r
+ #define SST2COLE(pa) SSA2CW((pa))\r
+ #define SST2OLE(pa) SSA2W((pa))\r
+ #define SSOLE2CT(po) SSW2CA((po))\r
+ #define SSOLE2T(po) SSW2A((po))\r
+ #endif\r
+\r
+ #ifdef OLE2ANSI\r
+ #define SSW2OLE SSW2A\r
+ #define SSOLE2W SSA2W\r
+ #define SSW2COLE SSW2CA\r
+ #define SSOLE2CW SSA2CW\r
+ inline POLESTR SSA2OLE(PSTR p) { return p; }\r
+ inline PSTR SSOLE2A(POLESTR p) { return p; }\r
+ inline PCOLESTR SSA2COLE(PCSTR p) { return p; }\r
+ inline PCSTR SSOLE2CA(PCOLESTR p){ return p; }\r
+ #else\r
+ #define SSA2OLE SSA2W\r
+ #define SSOLE2A SSW2A\r
+ #define SSA2COLE SSA2CW\r
+ #define SSOLE2CA SSW2CA\r
+ inline POLESTR SSW2OLE(PWSTR p) { return p; }\r
+ inline PWSTR SSOLE2W(POLESTR p) { return p; }\r
+ inline PCOLESTR SSW2COLE(PCWSTR p) { return p; }\r
+ inline PCWSTR SSOLE2CW(PCOLESTR p){ return p; }\r
+ #endif\r
+\r
+ // Above we've defined macros that look like MS' but all have\r
+ // an 'SS' prefix. Now we need the real macros. We'll either\r
+ // get them from the macros above or from MFC/ATL. \r
+\r
+ #if defined (USES_CONVERSION)\r
+\r
+ #define _NO_STDCONVERSION // just to be consistent\r
+\r
+ #else\r
+\r
+ #ifdef _MFC_VER\r
+\r
+ #include <afxconv.h>\r
+ #define _NO_STDCONVERSION // just to be consistent\r
+\r
+ #else\r
+\r
+ #define USES_CONVERSION SSCVT\r
+ #define A2CW SSA2CW\r
+ #define W2CA SSW2CA\r
+ #define T2A SST2A\r
+ #define A2T SSA2T\r
+ #define T2W SST2W\r
+ #define W2T SSW2T\r
+ #define T2CA SST2CA\r
+ #define A2CT SSA2CT\r
+ #define T2CW SST2CW\r
+ #define W2CT SSW2CT\r
+ #define ocslen sslen\r
+ #define ocscpy sscpy\r
+ #define T2COLE SST2COLE\r
+ #define OLE2CT SSOLE2CT\r
+ #define T2OLE SST2COLE\r
+ #define OLE2T SSOLE2CT\r
+ #define A2OLE SSA2OLE\r
+ #define OLE2A SSOLE2A\r
+ #define W2OLE SSW2OLE\r
+ #define OLE2W SSOLE2W\r
+ #define A2COLE SSA2COLE\r
+ #define OLE2CA SSOLE2CA\r
+ #define W2COLE SSW2COLE\r
+ #define OLE2CW SSOLE2CW\r
+ \r
+ #endif // #ifdef _MFC_VER\r
+ #endif // #ifndef USES_CONVERSION\r
+#endif // #ifndef SS_NO_CONVERSION\r
+\r
+// Define ostring - generic name for std::basic_string<OLECHAR>\r
+\r
+#if !defined(ostring) && !defined(OSTRING_DEFINED)\r
+ typedef std::basic_string<OLECHAR> ostring;\r
+ #define OSTRING_DEFINED\r
+#endif\r
+\r
+// StdCodeCvt when there's no conversion to be done\r
+inline PSTR StdCodeCvt(PSTR pDst, PCSTR pSrc, int nChars)\r
+{\r
+ if ( nChars > 0 )\r
+ {\r
+ pDst[0] = '\0';\r
+ std::basic_string<char>::traits_type::copy(pDst, pSrc, nChars);\r
+// std::char_traits<char>::copy(pDst, pSrc, nChars);\r
+ if ( nChars > 0 )\r
+ pDst[nChars] = '\0';\r
+ }\r
+\r
+ return pDst;\r
+}\r
+inline PSTR StdCodeCvt(PSTR pDst, PCUSTR pSrc, int nChars)\r
+{\r
+ return StdCodeCvt(pDst, (PCSTR)pSrc, nChars);\r
+}\r
+inline PUSTR StdCodeCvt(PUSTR pDst, PCSTR pSrc, int nChars)\r
+{\r
+ return (PUSTR)StdCodeCvt((PSTR)pDst, pSrc, nChars);\r
+}\r
+\r
+inline PWSTR StdCodeCvt(PWSTR pDst, PCWSTR pSrc, int nChars)\r
+{\r
+ if ( nChars > 0 )\r
+ {\r
+ pDst[0] = '\0';\r
+ std::basic_string<wchar_t>::traits_type::copy(pDst, pSrc, nChars);\r
+// std::char_traits<wchar_t>::copy(pDst, pSrc, nChars);\r
+ if ( nChars > 0 )\r
+ pDst[nChars] = '\0';\r
+ }\r
+\r
+ return pDst;\r
+}\r
+\r
+\r
+// Define tstring -- generic name for std::basic_string<TCHAR>\r
+\r
+#if !defined(tstring) && !defined(TSTRING_DEFINED)\r
+ typedef std::basic_string<TCHAR> tstring;\r
+ #define TSTRING_DEFINED\r
+#endif\r
+\r
+// a very shorthand way of applying the fix for KB problem Q172398\r
+// (basic_string assignment bug)\r
+\r
+#if defined ( _MSC_VER ) && ( _MSC_VER < 1200 )\r
+ #define Q172398(x) (x).erase()\r
+#else\r
+ #define Q172398(x)\r
+#endif\r
+\r
+// =============================================================================\r
+// INLINE FUNCTIONS ON WHICH CSTDSTRING RELIES\r
+//\r
+// Usually for generic text mapping, we rely on preprocessor macro definitions\r
+// to map to string functions. However the CStdStr<> template cannot use\r
+// macro-based generic text mappings because its character types do not get\r
+// resolved until template processing which comes AFTER macro processing. In\r
+// other words, UNICODE is of little help to us in the CStdStr template\r
+//\r
+// Therefore, to keep the CStdStr declaration simple, we have these inline\r
+// functions. The template calls them often. Since they are inline (and NOT\r
+// exported when this is built as a DLL), they will probably be resolved away\r
+// to nothing. \r
+//\r
+// Without these functions, the CStdStr<> template would probably have to broken\r
+// out into two, almost identical classes. Either that or it would be a huge,\r
+// convoluted mess, with tons of "if" statements all over the place checking the\r
+// size of template parameter CT.\r
+// \r
+// In several cases, you will see two versions of each function. One version is\r
+// the more portable, standard way of doing things, while the other is the\r
+// non-standard, but often significantly faster Visual C++ way.\r
+// =============================================================================\r
+\r
+// If they defined SS_NO_REFCOUNT, then we must convert all assignments\r
+\r
+#ifdef SS_NO_REFCOUNT\r
+ #define SSREF(x) (x).c_str()\r
+#else\r
+ #define SSREF(x) (x)\r
+#endif\r
+\r
+// -----------------------------------------------------------------------------\r
+// sslen: strlen/wcslen wrappers\r
+// -----------------------------------------------------------------------------\r
+template<typename CT> inline int sslen(const CT* pT)\r
+{\r
+ return 0 == pT ? 0 : std::basic_string<CT>::traits_type::length(pT);\r
+// return 0 == pT ? 0 : std::char_traits<CT>::length(pT);\r
+}\r
+inline SS_NOTHROW int sslen(const std::string& s)\r
+{\r
+ return s.length();\r
+}\r
+inline SS_NOTHROW int sslen(const std::wstring& s)\r
+{\r
+ return s.length();\r
+}\r
+\r
+// -----------------------------------------------------------------------------\r
+// sstolower/sstoupper -- convert characters to upper/lower case\r
+// -----------------------------------------------------------------------------\r
+template<typename CT>\r
+inline CT sstolower(const CT& t, const std::locale& loc = std::locale())\r
+{\r
+ return std::tolower<CT>(t, loc);\r
+}\r
+template<typename CT>\r
+inline CT sstoupper(const CT& t, const std::locale& loc = std::locale())\r
+{\r
+ return std::toupper<CT>(t, loc);\r
+}\r
+\r
+// -----------------------------------------------------------------------------\r
+// ssasn: assignment functions -- assign "sSrc" to "sDst"\r
+// -----------------------------------------------------------------------------\r
+typedef std::string::size_type SS_SIZETYPE; // just for shorthand, really\r
+typedef std::string::pointer SS_PTRTYPE; \r
+typedef std::wstring::size_type SW_SIZETYPE;\r
+typedef std::wstring::pointer SW_PTRTYPE; \r
+\r
+inline void ssasn(std::string& sDst, const std::string& sSrc)\r
+{\r
+ if ( sDst.c_str() != sSrc.c_str() )\r
+ {\r
+ sDst.erase();\r
+ sDst.assign(SSREF(sSrc));\r
+ }\r
+}\r
+inline void ssasn(std::string& sDst, PCSTR pA)\r
+{\r
+ // Watch out for NULLs, as always.\r
+\r
+ if ( 0 == pA )\r
+ {\r
+ sDst.erase();\r
+ }\r
+\r
+ // If pA actually points to part of sDst, we must NOT erase(), but\r
+ // rather take a substring\r
+\r
+ else if ( pA >= sDst.c_str() && pA <= sDst.c_str() + sDst.size() )\r
+ {\r
+ sDst =sDst.substr(static_cast<SS_SIZETYPE>(pA-sDst.c_str()));\r
+ }\r
+\r
+ // Otherwise (most cases) apply the assignment bug fix, if applicable\r
+ // and do the assignment\r
+\r
+ else\r
+ {\r
+ Q172398(sDst);\r
+ sDst.assign(pA);\r
+ }\r
+}\r
+inline void ssasn(std::string& sDst, const std::wstring& sSrc)\r
+{\r
+ int nLen = sSrc.size();\r
+ sDst.resize(nLen * sizeof(wchar_t) + 1);\r
+ StdCodeCvt(const_cast<SS_PTRTYPE>(sDst.data()), sSrc.c_str(), nLen);\r
+ sDst.resize(nLen);\r
+ //sDst.resize(sslen(sDst.c_str()));\r
+}\r
+inline void ssasn(std::string& sDst, PCWSTR pW)\r
+{\r
+ int nLen = sslen(pW);\r
+ sDst.resize(nLen * sizeof(wchar_t) + 1);\r
+ StdCodeCvt(const_cast<SS_PTRTYPE>(sDst.data()), pW, nLen);\r
+ sDst.resize(nLen);\r
+ //sDst.resize(sslen(sDst.c_str()));\r
+}\r
+inline void ssasn(std::string& sDst, const int nNull)\r
+{\r
+ UNUSED(nNull);\r
+ ASSERT(nNull==0);\r
+ sDst.assign("");\r
+} \r
+inline void ssasn(std::wstring& sDst, const std::wstring& sSrc)\r
+{\r
+ if ( sDst.c_str() != sSrc.c_str() )\r
+ {\r
+ sDst.erase();\r
+ sDst.assign(SSREF(sSrc));\r
+ }\r
+}\r
+inline void ssasn(std::wstring& sDst, PCWSTR pW)\r
+{\r
+ // Watch out for NULLs, as always.\r
+\r
+ if ( 0 == pW )\r
+ {\r
+ sDst.erase();\r
+ }\r
+\r
+ // If pW actually points to part of sDst, we must NOT erase(), but\r
+ // rather take a substring\r
+\r
+ else if ( pW >= sDst.c_str() && pW <= sDst.c_str() + sDst.size() )\r
+ {\r
+ sDst = sDst.substr(static_cast<SW_SIZETYPE>(pW-sDst.c_str()));\r
+ }\r
+\r
+ // Otherwise (most cases) apply the assignment bug fix, if applicable\r
+ // and do the assignment\r
+\r
+ else\r
+ {\r
+ Q172398(sDst);\r
+ sDst.assign(pW);\r
+ }\r
+}\r
+#undef StrSizeType\r
+inline void ssasn(std::wstring& sDst, const std::string& sSrc)\r
+{\r
+ int nLen = sSrc.size();\r
+ sDst.resize(nLen+1);\r
+ StdCodeCvt(const_cast<SW_PTRTYPE>(sDst.data()), sSrc.c_str(), nLen+1);\r
+ sDst.resize(sslen(sDst.c_str()));\r
+}\r
+inline void ssasn(std::wstring& sDst, PCSTR pA)\r
+{\r
+ int nLen = sslen(pA);\r
+ sDst.resize(nLen+1);\r
+ StdCodeCvt(const_cast<SW_PTRTYPE>(sDst.data()), pA, nLen+1);\r
+ sDst.resize(sslen(sDst.c_str()));\r
+}\r
+inline void ssasn(std::wstring& sDst, const int nNull)\r
+{\r
+ UNUSED(nNull);\r
+ ASSERT(nNull==0);\r
+ sDst.assign(L"");\r
+}\r
+\r
+\r
+// -----------------------------------------------------------------------------\r
+// ssadd: string object concatenation -- add second argument to first\r
+// -----------------------------------------------------------------------------\r
+inline void ssadd(std::string& sDst, const std::wstring& sSrc)\r
+{\r
+ int nSrcLen = sSrc.size();\r
+ int nDstLen = sDst.size();\r
+ int nEndLen = nSrcLen + nDstLen;\r
+ sDst.resize(nEndLen + 1);\r
+ StdCodeCvt(const_cast<SS_PTRTYPE>(sDst.data()+nDstLen), sSrc.c_str(), nSrcLen);\r
+ sDst.resize(nEndLen);\r
+}\r
+inline void ssadd(std::string& sDst, const std::string& sSrc)\r
+{\r
+ if ( &sDst == &sSrc )\r
+ sDst.reserve(2*sDst.size());\r
+\r
+ sDst.append(sSrc.c_str());\r
+}\r
+inline void ssadd(std::string& sDst, PCWSTR pW)\r
+{\r
+ int nSrcLen = sslen(pW);\r
+ int nDstLen = sDst.size();\r
+ int nEndLen = nSrcLen + nDstLen;\r
+ sDst.resize(nEndLen + 1);\r
+ StdCodeCvt(const_cast<SS_PTRTYPE>(sDst.data()+nDstLen), pW, nSrcLen+1);\r
+ sDst.resize(nEndLen);\r
+}\r
+inline void ssadd(std::string& sDst, PCSTR pA)\r
+{\r
+ if ( pA )\r
+ {\r
+ // If the string being added is our internal string or a part of our\r
+ // internal string, then we must NOT do any reallocation without\r
+ // first copying that string to another object (since we're using a\r
+ // direct pointer)\r
+\r
+ if ( pA >= sDst.c_str() && pA <= sDst.c_str()+sDst.length())\r
+ {\r
+ if ( sDst.capacity() <= sDst.size()+sslen(pA) )\r
+ sDst.append(std::string(pA));\r
+ else\r
+ sDst.append(pA);\r
+ }\r
+ else\r
+ {\r
+ sDst.append(pA); \r
+ }\r
+ }\r
+}\r
+inline void ssadd(std::wstring& sDst, const std::wstring& sSrc)\r
+{\r
+ if ( &sDst == &sSrc )\r
+ sDst.reserve(2*sDst.size());\r
+\r
+ sDst.append(sSrc.c_str());\r
+}\r
+inline void ssadd(std::wstring& sDst, const std::string& sSrc)\r
+{\r
+ int nSrcLen = sSrc.size();\r
+ int nDstLen = sDst.size();\r
+ int nEndLen = nSrcLen + nDstLen;\r
+ sDst.resize(nEndLen+1);\r
+ StdCodeCvt(const_cast<SW_PTRTYPE>(sDst.data()+nDstLen), sSrc.c_str(), nSrcLen+1);\r
+ sDst.resize(nEndLen);\r
+}\r
+inline void ssadd(std::wstring& sDst, PCSTR pA)\r
+{\r
+ int nSrcLen = sslen(pA);\r
+ int nDstLen = sDst.size();\r
+ int nEndLen = nSrcLen + nDstLen;\r
+ sDst.resize(nEndLen + 1);\r
+ StdCodeCvt(const_cast<SW_PTRTYPE>(sDst.data()+nDstLen), pA, nSrcLen+1);\r
+ sDst.resize(nEndLen);\r
+}\r
+inline void ssadd(std::wstring& sDst, PCWSTR pW)\r
+{\r
+ if ( pW )\r
+ {\r
+ // If the string being added is our internal string or a part of our\r
+ // internal string, then we must NOT do any reallocation without\r
+ // first copying that string to another object (since we're using a\r
+ // direct pointer)\r
+\r
+ if ( pW >= sDst.c_str() && pW <= sDst.c_str()+sDst.length())\r
+ {\r
+ if ( sDst.capacity() <= sDst.size()+sslen(pW) )\r
+ sDst.append(std::wstring(pW));\r
+ else\r
+ sDst.append(pW);\r
+ }\r
+ else\r
+ {\r
+ sDst.append(pW);\r
+ }\r
+ }\r
+}\r
+\r
+\r
+// -----------------------------------------------------------------------------\r
+// ssicmp: comparison (case insensitive )\r
+// -----------------------------------------------------------------------------\r
+template<typename CT>\r
+inline int ssicmp(const CT* pA1, const CT* pA2)\r
+{\r
+ std::locale loc;\r
+ const std::ctype<CT>& ct = SS_USE_FACET(loc, std::ctype<CT>);\r
+ CT f;\r
+ CT l;\r
+\r
+ do \r
+ {\r
+ f = ct.tolower(*(pA1++));\r
+ l = ct.tolower(*(pA2++));\r
+ } while ( (f) && (f == l) );\r
+\r
+ return (int)(f - l);\r
+}\r
+\r
+// -----------------------------------------------------------------------------\r
+// ssupr/sslwr: Uppercase/Lowercase conversion functions\r
+// -----------------------------------------------------------------------------\r
+\r
+template<typename CT>\r
+inline void sslwr(CT* pT, size_t nLen)\r
+{\r
+ SS_USE_FACET(std::locale(), std::ctype<CT>).tolower(pT, pT+nLen);\r
+}\r
+template<typename CT>\r
+inline void ssupr(CT* pT, size_t nLen)\r
+{\r
+ SS_USE_FACET(std::locale(), std::ctype<CT>).toupper(pT, pT+nLen);\r
+}\r
+\r
+\r
+// -----------------------------------------------------------------------------\r
+// vsprintf/vswprintf or _vsnprintf/_vsnwprintf equivalents. In standard\r
+// builds we can't use _vsnprintf/_vsnwsprintf because they're MS extensions.\r
+// -----------------------------------------------------------------------------\r
+#if defined(SS_ANSI) || !defined(_MSC_VER)\r
+\r
+ // Borland's headers put some ANSI "C" functions in the 'std' namespace.\r
+ // Promote them to the global namespace so we can use them here.\r
+\r
+ #if defined(__BORLANDC__)\r
+ using std::vsprintf;\r
+ using std::vswprintf;\r
+ #endif\r
+ inline int ssvsprintf(PSTR pA, size_t /*nCount*/, PCSTR pFmtA, va_list vl)\r
+ {\r
+ return vsprintf(pA, pFmtA, vl);\r
+ }\r
+ inline int ssvsprintf(PWSTR pW, size_t nCount, PCWSTR pFmtW, va_list vl)\r
+ {\r
+ // JMO: Some distributions of the "C" have a version of vswprintf that\r
+ // takes 3 arguments (e.g. Microsoft, Borland, GNU). Others have a \r
+ // version which takes 4 arguments (an extra "count" argument in the\r
+ // second position. The best stab I can take at this so far is that if\r
+ // you are NOT running with MS, Borland, or GNU, then I'll assume you\r
+ // have the version that takes 4 arguments.\r
+ //\r
+ // I'm sure that these checks don't catch every platform correctly so if\r
+ // you get compiler errors on one of the lines immediately below, it's\r
+ // probably because your implemntation takes a different number of\r
+ // arguments. You can comment out the offending line (and use the\r
+ // alternate version) or you can figure out what compiler flag to check\r
+ // and add that preprocessor check in. Regardless, if you get an error\r
+ // on these lines, I'd sure like to hear from you about it.\r
+ //\r
+ // Thanks to Ronny Schulz for the SGI-specific checks here.\r
+\r
+// #if !defined(__MWERKS__) && !defined(__SUNPRO_CC_COMPAT) && !defined(__SUNPRO_CC)\r
+ #if !defined(_MSC_VER) \\r
+ && !defined (__BORLANDC__) \\r
+ && !defined(__GNUC__) \\r
+ && !defined(__sgi)\r
+\r
+ return vswprintf(pW, nCount, pFmtW, vl);\r
+\r
+ // suddenly with the current SGI 7.3 compiler there is no such function as\r
+ // vswprintf and the substitute needs explicit casts to compile\r
+\r
+ #elif defined(__sgi)\r
+\r
+ nCount;\r
+ return vsprintf( (char *)pW, (char *)pFmtW, vl);\r
+\r
+ #else\r
+\r
+ nCount;\r
+ return vswprintf(pW, pFmtW, vl);\r
+\r
+ #endif\r
+\r
+ }\r
+#else\r
+ inline int ssnprintf(PSTR pA, size_t nCount, PCSTR pFmtA, va_list vl)\r
+ {\r
+ return _vsnprintf(pA, nCount, pFmtA, vl);\r
+ }\r
+ inline int ssnprintf(PWSTR pW, size_t nCount, PCWSTR pFmtW, va_list vl)\r
+ {\r
+ return _vsnwprintf(pW, nCount, pFmtW, vl);\r
+ }\r
+#endif\r
+\r
+\r
+\r
+// -----------------------------------------------------------------------------\r
+// ssload: Type safe, overloaded ::LoadString wrappers\r
+// There is no equivalent of these in non-Win32-specific builds. However, I'm\r
+// thinking that with the message facet, there might eventually be one\r
+// -----------------------------------------------------------------------------\r
+#if defined (SS_WIN32) && !defined(SS_ANSI)\r
+ inline int ssload(HMODULE hInst, UINT uId, PSTR pBuf, int nMax)\r
+ {\r
+ return ::LoadStringA(hInst, uId, pBuf, nMax);\r
+ }\r
+ inline int ssload(HMODULE hInst, UINT uId, PWSTR pBuf, int nMax)\r
+ {\r
+ return ::LoadStringW(hInst, uId, pBuf, nMax);\r
+ }\r
+#endif\r
+\r
+\r
+// -----------------------------------------------------------------------------\r
+// sscoll/ssicoll: Collation wrappers\r
+// Note -- with MSVC I have reversed the arguments order here because the\r
+// functions appear to return the opposite of what they should\r
+// -----------------------------------------------------------------------------\r
+template <typename CT>\r
+inline int sscoll(const CT* sz1, int nLen1, const CT* sz2, int nLen2)\r
+{\r
+ const std::collate<CT>& coll =\r
+ SS_USE_FACET(std::locale(), std::collate<CT>);\r
+\r
+ return coll.compare(sz2, sz2+nLen2, sz1, sz1+nLen1);\r
+}\r
+template <typename CT>\r
+inline int ssicoll(const CT* sz1, int nLen1, const CT* sz2, int nLen2)\r
+{\r
+ const std::locale loc;\r
+ const std::collate<CT>& coll = SS_USE_FACET(loc, std::collate<CT>);\r
+\r
+ // Some implementations seem to have trouble using the collate<>\r
+ // facet typedefs so we'll just default to basic_string and hope\r
+ // that's what the collate facet uses (which it generally should)\r
+\r
+// std::collate<CT>::string_type s1(sz1);\r
+// std::collate<CT>::string_type s2(sz2);\r
+ const std::basic_string<CT> sEmpty;\r
+ std::basic_string<CT> s1(sz1 ? sz1 : sEmpty.c_str());\r
+ std::basic_string<CT> s2(sz2 ? sz2 : sEmpty.c_str());\r
+\r
+ sslwr(const_cast<CT*>(s1.c_str()), nLen1);\r
+ sslwr(const_cast<CT*>(s2.c_str()), nLen2);\r
+ return coll.compare(s2.c_str(), s2.c_str()+nLen2,\r
+ s1.c_str(), s1.c_str()+nLen1);\r
+}\r
+\r
+\r
+// -----------------------------------------------------------------------------\r
+// ssfmtmsg: FormatMessage equivalents. Needed because I added a CString facade\r
+// Again -- no equivalent of these on non-Win32 builds but their might one day\r
+// be one if the message facet gets implemented\r
+// -----------------------------------------------------------------------------\r
+#if defined (SS_WIN32) && !defined(SS_ANSI)\r
+ inline DWORD ssfmtmsg(DWORD dwFlags, LPCVOID pSrc, DWORD dwMsgId,\r
+ DWORD dwLangId, PSTR pBuf, DWORD nSize,\r
+ va_list* vlArgs)\r
+ { \r
+ return FormatMessageA(dwFlags, pSrc, dwMsgId, dwLangId,\r
+ pBuf, nSize,vlArgs);\r
+ }\r
+ inline DWORD ssfmtmsg(DWORD dwFlags, LPCVOID pSrc, DWORD dwMsgId,\r
+ DWORD dwLangId, PWSTR pBuf, DWORD nSize,\r
+ va_list* vlArgs)\r
+ {\r
+ return FormatMessageW(dwFlags, pSrc, dwMsgId, dwLangId,\r
+ pBuf, nSize,vlArgs);\r
+ }\r
+#else\r
+#endif\r
+ \r
+\r
+\r
+// FUNCTION: sscpy. Copies up to 'nMax' characters from pSrc to pDst.\r
+// -----------------------------------------------------------------------------\r
+// FUNCTION: sscpy\r
+// inline int sscpy(PSTR pDst, PCSTR pSrc, int nMax=-1);\r
+// inline int sscpy(PUSTR pDst, PCSTR pSrc, int nMax=-1)\r
+// inline int sscpy(PSTR pDst, PCWSTR pSrc, int nMax=-1);\r
+// inline int sscpy(PWSTR pDst, PCWSTR pSrc, int nMax=-1);\r
+// inline int sscpy(PWSTR pDst, PCSTR pSrc, int nMax=-1);\r
+//\r
+// DESCRIPTION:\r
+// This function is very much (but not exactly) like strcpy. These\r
+// overloads simplify copying one C-style string into another by allowing\r
+// the caller to specify two different types of strings if necessary.\r
+//\r
+// The strings must NOT overlap\r
+//\r
+// "Character" is expressed in terms of the destination string, not\r
+// the source. If no 'nMax' argument is supplied, then the number of\r
+// characters copied will be sslen(pSrc). A NULL terminator will\r
+// also be added so pDst must actually be big enough to hold nMax+1\r
+// characters. The return value is the number of characters copied,\r
+// not including the NULL terminator.\r
+//\r
+// PARAMETERS: \r
+// pSrc - the string to be copied FROM. May be a char based string, an\r
+// MBCS string (in Win32 builds) or a wide string (wchar_t).\r
+// pSrc - the string to be copied TO. Also may be either MBCS or wide\r
+// nMax - the maximum number of characters to be copied into szDest. Note\r
+// that this is expressed in whatever a "character" means to pDst.\r
+// If pDst is a wchar_t type string than this will be the maximum\r
+// number of wchar_ts that my be copied. The pDst string must be\r
+// large enough to hold least nMaxChars+1 characters.\r
+// If the caller supplies no argument for nMax this is a signal to\r
+// the routine to copy all the characters in pSrc, regardless of\r
+// how long it is.\r
+//\r
+// RETURN VALUE: none\r
+// -----------------------------------------------------------------------------\r
+template<typename CT1, typename CT2>\r
+inline int sscpycvt(CT1* pDst, const CT2* pSrc, int nChars)\r
+{\r
+ StdCodeCvt(pDst, pSrc, nChars);\r
+ pDst[SSMAX(nChars, 0)] = '\0';\r
+ return nChars;\r
+}\r
+\r
+template<typename CT1, typename CT2>\r
+inline int sscpy(CT1* pDst, const CT2* pSrc, int nMax, int nLen)\r
+{\r
+ return sscpycvt(pDst, pSrc, SSMIN(nMax, nLen));\r
+}\r
+template<typename CT1, typename CT2>\r
+inline int sscpy(CT1* pDst, const CT2* pSrc, int nMax)\r
+{\r
+ return sscpycvt(pDst, pSrc, SSMIN(nMax, sslen(pSrc)));\r
+}\r
+template<typename CT1, typename CT2>\r
+inline int sscpy(CT1* pDst, const CT2* pSrc)\r
+{\r
+ return sscpycvt(pDst, pSrc, sslen(pSrc));\r
+}\r
+template<typename CT1, typename CT2>\r
+inline int sscpy(CT1* pDst, const std::basic_string<CT2>& sSrc, int nMax)\r
+{\r
+ return sscpycvt(pDst, sSrc.c_str(), SSMIN(nMax, (int)sSrc.length()));\r
+}\r
+template<typename CT1, typename CT2>\r
+inline int sscpy(CT1* pDst, const std::basic_string<CT2>& sSrc)\r
+{\r
+ return sscpycvt(pDst, sSrc.c_str(), (int)sSrc.length());\r
+}\r
+\r
+#ifdef SS_INC_COMDEF\r
+ template<typename CT1>\r
+ inline int sscpy(CT1* pDst, const _bstr_t& bs, int nMax)\r
+ {\r
+ return sscpycvt(pDst, static_cast<PCOLESTR>(bs),\r
+ SSMIN(nMax, static_cast<int>(bs.length())));\r
+ }\r
+ template<typename CT1>\r
+ inline int sscpy(CT1* pDst, const _bstr_t& bs)\r
+ {\r
+ return sscpy(pDst, bs, static_cast<int>(bs.length()));\r
+ }\r
+#endif\r
+\r
+\r
+// -----------------------------------------------------------------------------\r
+// Functional objects for changing case. They also let you pass locales\r
+// -----------------------------------------------------------------------------\r
+\r
+#ifdef SS_ANSI\r
+ template<typename CT>\r
+ struct SSToUpper : public std::binary_function<CT, std::locale, CT>\r
+ {\r
+ inline CT operator()(const CT& t, const std::locale& loc) const\r
+ {\r
+ return sstoupper<CT>(t, loc);\r
+ }\r
+ };\r
+ template<typename CT>\r
+ struct SSToLower : public std::binary_function<CT, std::locale, CT>\r
+ {\r
+ inline CT operator()(const CT& t, const std::locale& loc) const\r
+ {\r
+ return sstolower<CT>(t, loc);\r
+ }\r
+ };\r
+#endif\r
+\r
+// This struct is used for TrimRight() and TrimLeft() function implementations.\r
+//template<typename CT>\r
+//struct NotSpace : public std::unary_function<CT, bool>\r
+//{\r
+// const std::locale& loc;\r
+// inline NotSpace(const std::locale& locArg) : loc(locArg) {}\r
+// inline bool operator() (CT t) { return !std::isspace(t, loc); }\r
+//};\r
+template<typename CT>\r
+struct NotSpace : public std::unary_function<CT, bool>\r
+{\r
+\r
+ // DINKUMWARE BUG:\r
+ // Note -- using std::isspace in a COM DLL gives us access violations\r
+ // because it causes the dynamic addition of a function to be called\r
+ // when the library shuts down. Unfortunately the list is maintained\r
+ // in DLL memory but the function is in static memory. So the COM DLL\r
+ // goes away along with the function that was supposed to be called,\r
+ // and then later when the DLL CRT shuts down it unloads the list and\r
+ // tries to call the long-gone function.\r
+ // This is DinkumWare's implementation problem. Until then, we will\r
+ // use good old isspace and iswspace from the CRT unless they\r
+ // specify SS_ANSI\r
+ \r
+ const std::locale loc;\r
+ NotSpace(const std::locale& locArg=std::locale()) : loc(locArg) {}\r
+ bool operator() (CT t) const { return !std::isspace(t, loc); }\r
+};\r
+\r
+\r
+\r
+\r
+// Now we can define the template (finally!)\r
+// =============================================================================\r
+// TEMPLATE: CStdStr\r
+// template<typename CT> class CStdStr : public std::basic_string<CT>\r
+//\r
+// REMARKS:\r
+// This template derives from basic_string<CT> and adds some MFC CString-\r
+// like functionality\r
+//\r
+// Basically, this is my attempt to make Standard C++ library strings as\r
+// easy to use as the MFC CString class.\r
+//\r
+// Note that although this is a template, it makes the assumption that the\r
+// template argument (CT, the character type) is either char or wchar_t. \r
+// =============================================================================\r
+\r
+//#define CStdStr _SS // avoid compiler warning 4786\r
+\r
+// template<typename ARG> ARG& FmtArg(ARG& arg) { return arg; }\r
+// PCSTR FmtArg(const std::string& arg) { return arg.c_str(); }\r
+// PCWSTR FmtArg(const std::wstring& arg) { return arg.c_str(); }\r
+\r
+template<typename ARG>\r
+struct FmtArg\r
+{\r
+ explicit FmtArg(const ARG& arg) : a_(arg) {}\r
+ const ARG& Val() const { return a_; }\r
+ const ARG& a_;\r
+private:\r
+ FmtArg& operator=(const FmtArg&) { return *this; }\r
+};\r
+\r
+template<typename CT>\r
+class CStdStr : public std::basic_string<CT>\r
+{\r
+ // Typedefs for shorter names. Using these names also appears to help\r
+ // us avoid some ambiguities that otherwise arise on some platforms\r
+\r
+ typedef typename std::basic_string<CT> MYBASE; // my base class\r
+ typedef CStdStr<CT> MYTYPE; // myself\r
+ typedef typename MYBASE::const_pointer PCMYSTR; // PCSTR or PCWSTR \r
+ typedef typename MYBASE::pointer PMYSTR; // PSTR or PWSTR\r
+ typedef typename MYBASE::iterator MYITER; // my iterator type\r
+ typedef typename MYBASE::const_iterator MYCITER; // you get the idea...\r
+ typedef typename MYBASE::reverse_iterator MYRITER;\r
+ typedef typename MYBASE::size_type MYSIZE; \r
+ typedef typename MYBASE::value_type MYVAL; \r
+ typedef typename MYBASE::allocator_type MYALLOC;\r
+ \r
+public:\r
+\r
+ // shorthand conversion from PCTSTR to string resource ID\r
+ #define _TRES(pctstr) (LOWORD((DWORD)(pctstr))) \r
+\r
+ // CStdStr inline constructors\r
+ CStdStr()\r
+ {\r
+ }\r
+\r
+ CStdStr(const MYTYPE& str) : MYBASE(SSREF(str))\r
+ {\r
+ }\r
+\r
+ CStdStr(const std::string& str)\r
+ {\r
+ ssasn(*this, SSREF(str));\r
+ }\r
+\r
+ CStdStr(const std::wstring& str)\r
+ {\r
+ ssasn(*this, SSREF(str));\r
+ }\r
+\r
+ CStdStr(PCMYSTR pT, MYSIZE n) : MYBASE(pT, n)\r
+ {\r
+ }\r
+\r
+#ifdef SS_UNSIGNED\r
+ CStdStr(PCUSTR pU)\r
+ {\r
+ *this = reinterpret_cast<PCSTR>(pU);\r
+ }\r
+#endif\r
+\r
+ CStdStr(PCSTR pA)\r
+ {\r
+ #ifdef SS_ANSI\r
+ *this = pA;\r
+ #else\r
+ if ( 0 != HIWORD(pA) )\r
+ *this = pA;\r
+ else if ( 0 != pA && !Load(_TRES(pA)) )\r
+ TRACE(_T("Can't load string %u\n"), _TRES(pA));\r
+ #endif\r
+ }\r
+\r
+ CStdStr(PCWSTR pW)\r
+ {\r
+ #ifdef SS_ANSI\r
+ *this = pW;\r
+ #else\r
+ if ( 0 != HIWORD(pW) )\r
+ *this = pW;\r
+ else if ( 0 != pW && !Load(_TRES(pW)) )\r
+ TRACE(_T("Can't load string %u\n"), _TRES(pW));\r
+ #endif\r
+ }\r
+\r
+ CStdStr(MYCITER first, MYCITER last)\r
+ : MYBASE(first, last)\r
+ {\r
+ }\r
+\r
+ CStdStr(MYSIZE nSize, MYVAL ch, const MYALLOC& al=MYALLOC())\r
+ : MYBASE(nSize, ch, al)\r
+ {\r
+ }\r
+\r
+ #ifdef SS_INC_COMDEF\r
+ CStdStr(const _bstr_t& bstr)\r
+ {\r
+ if ( bstr.length() > 0 )\r
+ this->append(static_cast<PCMYSTR>(bstr), bstr.length());\r
+ }\r
+ #endif\r
+\r
+ // CStdStr inline assignment operators -- the ssasn function now takes care\r
+ // of fixing the MSVC assignment bug (see knowledge base article Q172398).\r
+ MYTYPE& operator=(const MYTYPE& str)\r
+ { \r
+ ssasn(*this, str); \r
+ return *this;\r
+ }\r
+\r
+ MYTYPE& operator=(const std::string& str)\r
+ {\r
+ ssasn(*this, str);\r
+ return *this;\r
+ }\r
+\r
+ MYTYPE& operator=(const std::wstring& str)\r
+ {\r
+ ssasn(*this, str);\r
+ return *this;\r
+ }\r
+\r
+ MYTYPE& operator=(PCSTR pA)\r
+ {\r
+ ssasn(*this, pA);\r
+ return *this;\r
+ }\r
+\r
+ MYTYPE& operator=(PCWSTR pW)\r
+ {\r
+ ssasn(*this, pW);\r
+ return *this;\r
+ }\r
+\r
+#ifdef SS_UNSIGNED\r
+ MYTYPE& operator=(PCUSTR pU)\r
+ {\r
+ ssasn(*this, reinterpret_cast<PCSTR>(pU)):\r
+ return *this;\r
+ }\r
+#endif\r
+\r
+ MYTYPE& operator=(CT t)\r
+ {\r
+ Q172398(*this);\r
+ this->assign(1, t);\r
+ return *this;\r
+ }\r
+\r
+ #ifdef SS_INC_COMDEF\r
+ MYTYPE& operator=(const _bstr_t& bstr)\r
+ {\r
+ if ( bstr.length() > 0 )\r
+ {\r
+ this->assign(static_cast<PCMYSTR>(bstr), bstr.length());\r
+ return *this;\r
+ }\r
+ else\r
+ {\r
+ this->erase();\r
+ return *this;\r
+ }\r
+ }\r
+ #endif\r
+\r
+\r
+ // Overloads also needed to fix the MSVC assignment bug (KB: Q172398)\r
+ // *** Thanks to Pete The Plumber for catching this one ***\r
+ // They also are compiled if you have explicitly turned off refcounting\r
+ #if ( defined(_MSC_VER) && ( _MSC_VER < 1200 ) ) || defined(SS_NO_REFCOUNT) \r
+\r
+ MYTYPE& assign(const MYTYPE& str)\r
+ {\r
+ ssasn(*this, str);\r
+ return *this;\r
+ }\r
+\r
+ MYTYPE& assign(const MYTYPE& str, MYSIZE nStart, MYSIZE nChars)\r
+ {\r
+ // This overload of basic_string::assign is supposed to assign up to\r
+ // <nChars> or the NULL terminator, whichever comes first. Since we\r
+ // are about to call a less forgiving overload (in which <nChars>\r
+ // must be a valid length), we must adjust the length here to a safe\r
+ // value. Thanks to Ullrich Pollähne for catching this bug\r
+\r
+ nChars = SSMIN(nChars, str.length() - nStart);\r
+\r
+ // Watch out for assignment to self\r
+\r
+ if ( this == &str )\r
+ {\r
+ MYTYPE strTemp(str.c_str()+nStart, nChars);\r
+ MYBASE::assign(strTemp);\r
+ }\r
+ else\r
+ {\r
+ Q172398(*this);\r
+ MYBASE::assign(str.c_str()+nStart, nChars);\r
+ }\r
+ return *this;\r
+ }\r
+\r
+ MYTYPE& assign(const MYBASE& str)\r
+ {\r
+ ssasn(*this, str);\r
+ return *this;\r
+ }\r
+\r
+ MYTYPE& assign(const MYBASE& str, MYSIZE nStart, MYSIZE nChars)\r
+ {\r
+ // This overload of basic_string::assign is supposed to assign up to\r
+ // <nChars> or the NULL terminator, whichever comes first. Since we\r
+ // are about to call a less forgiving overload (in which <nChars>\r
+ // must be a valid length), we must adjust the length here to a safe\r
+ // value. Thanks to Ullrich Pollähne for catching this bug\r
+\r
+ nChars = SSMIN(nChars, str.length() - nStart);\r
+\r
+ // Watch out for assignment to self\r
+\r
+ if ( this == &str ) // watch out for assignment to self\r
+ {\r
+ MYTYPE strTemp(str.c_str() + nStart, nChars);\r
+ MYBASE::assign(strTemp);\r
+ }\r
+ else\r
+ {\r
+ Q172398(*this);\r
+ MYBASE::assign(str.c_str()+nStart, nChars);\r
+ }\r
+ return *this;\r
+ }\r
+\r
+ MYTYPE& assign(const CT* pC, MYSIZE nChars)\r
+ {\r
+ // Q172398 only fix -- erase before assigning, but not if we're\r
+ // assigning from our own buffer\r
+\r
+ #if defined ( _MSC_VER ) && ( _MSC_VER < 1200 )\r
+ if ( !this->empty() &&\r
+ ( pC < this->data() || pC > this->data() + this->capacity() ) )\r
+ {\r
+ this->erase();\r
+ }\r
+ #endif\r
+ Q172398(*this);\r
+ MYBASE::assign(pC, nChars);\r
+ return *this;\r
+ }\r
+\r
+ MYTYPE& assign(MYSIZE nChars, MYVAL val)\r
+ {\r
+ Q172398(*this);\r
+ MYBASE::assign(nChars, val);\r
+ return *this;\r
+ }\r
+\r
+ MYTYPE& assign(const CT* pT)\r
+ {\r
+ return this->assign(pT, MYBASE::traits_type::length(pT));\r
+ }\r
+\r
+ MYTYPE& assign(MYCITER iterFirst, MYCITER iterLast)\r
+ {\r
+ #if defined ( _MSC_VER ) && ( _MSC_VER < 1200 ) \r
+ // Q172398 fix. don't call erase() if we're assigning from ourself\r
+ if ( iterFirst < this->begin() ||\r
+ iterFirst > this->begin() + this->size() )\r
+ {\r
+ this->erase()\r
+ }\r
+ #endif\r
+ this->replace(this->begin(), this->end(), iterFirst, iterLast);\r
+ return *this;\r
+ }\r
+ #endif\r
+\r
+\r
+ // -------------------------------------------------------------------------\r
+ // CStdStr inline concatenation.\r
+ // -------------------------------------------------------------------------\r
+ MYTYPE& operator+=(const MYTYPE& str)\r
+ {\r
+ ssadd(*this, str);\r
+ return *this;\r
+ }\r
+\r
+ MYTYPE& operator+=(const std::string& str)\r
+ {\r
+ ssadd(*this, str);\r
+ return *this; \r
+ }\r
+\r
+ MYTYPE& operator+=(const std::wstring& str)\r
+ {\r
+ ssadd(*this, str);\r
+ return *this;\r
+ }\r
+\r
+ MYTYPE& operator+=(PCSTR pA)\r
+ {\r
+ ssadd(*this, pA);\r
+ return *this;\r
+ }\r
+\r
+ MYTYPE& operator+=(PCWSTR pW)\r
+ {\r
+ ssadd(*this, pW);\r
+ return *this;\r
+ }\r
+\r
+ MYTYPE& operator+=(CT t)\r
+ {\r
+ this->append(1, t);\r
+ return *this;\r
+ }\r
+ #ifdef SS_INC_COMDEF // if we have _bstr_t, define a += for it too.\r
+ MYTYPE& operator+=(const _bstr_t& bstr)\r
+ {\r
+ return this->operator+=(static_cast<PCMYSTR>(bstr));\r
+ }\r
+ #endif\r
+\r
+\r
+ // -------------------------------------------------------------------------\r
+ // Case changing functions\r
+ // -------------------------------------------------------------------------\r
+\r
+ MYTYPE& ToUpper()\r
+ {\r
+ // Strictly speaking, this would be about the most portable way\r
+\r
+ // std::transform(begin(),\r
+ // end(),\r
+ // begin(),\r
+ // std::bind2nd(SSToUpper<CT>(), std::locale()));\r
+\r
+ // But practically speaking, this works faster\r
+\r
+ if ( !empty() )\r
+ ssupr(GetBuf(), this->size());\r
+\r
+ return *this;\r
+ }\r
+\r
+\r
+\r
+ MYTYPE& ToLower()\r
+ {\r
+ // Strictly speaking, this would be about the most portable way\r
+\r
+ // std::transform(begin(),\r
+ // end(),\r
+ // begin(),\r
+ // std::bind2nd(SSToLower<CT>(), std::locale()));\r
+\r
+ // But practically speaking, this works faster\r
+\r
+ if ( !empty() )\r
+ sslwr(GetBuf(), this->size());\r
+\r
+ return *this;\r
+ }\r
+\r
+\r
+\r
+ MYTYPE& Normalize()\r
+ {\r
+ return Trim().ToLower();\r
+ }\r
+\r
+\r
+ // -------------------------------------------------------------------------\r
+ // CStdStr -- Direct access to character buffer. In the MS' implementation,\r
+ // the at() function that we use here also calls _Freeze() providing us some\r
+ // protection from multithreading problems associated with ref-counting.\r
+ // In VC 7 and later, of course, the ref-counting stuff is gone.\r
+ // -------------------------------------------------------------------------\r
+\r
+ CT* GetBuf(int nMinLen=-1)\r
+ {\r
+ if ( static_cast<int>(size()) < nMinLen )\r
+ this->resize(static_cast<MYSIZE>(nMinLen));\r
+\r
+ return this->empty() ? const_cast<CT*>(this->data()) : &(this->at(0));\r
+ }\r
+\r
+ CT* SetBuf(int nLen)\r
+ {\r
+ nLen = ( nLen > 0 ? nLen : 0 );\r
+ if ( this->capacity() < 1 && nLen == 0 )\r
+ this->resize(1);\r
+\r
+ this->resize(static_cast<MYSIZE>(nLen));\r
+ return const_cast<CT*>(this->data());\r
+ }\r
+ void RelBuf(int nNewLen=-1)\r
+ {\r
+ this->resize(static_cast<MYSIZE>(nNewLen > -1 ? nNewLen :\r
+ sslen(this->c_str())));\r
+ }\r
+\r
+ void BufferRel() { RelBuf(); } // backwards compatability\r
+ CT* Buffer() { return GetBuf(); } // backwards compatability\r
+ CT* BufferSet(int nLen) { return SetBuf(nLen);}// backwards compatability\r
+\r
+ bool Equals(const CT* pT, bool bUseCase=false) const\r
+ { // get copy, THEN compare (thread safe)\r
+ return bUseCase ? this->compare(pT) == 0 :\r
+ ssicmp(MYTYPE(*this).c_str(), pT) == 0;\r
+ } \r
+\r
+ // -------------------------------------------------------------------------\r
+ // FUNCTION: CStdStr::Load\r
+ // REMARKS:\r
+ // Loads string from resource specified by nID\r
+ //\r
+ // PARAMETERS:\r
+ // nID - resource Identifier. Purely a Win32 thing in this case\r
+ //\r
+ // RETURN VALUE:\r
+ // true if successful, false otherwise\r
+ // -------------------------------------------------------------------------\r
+\r
+#ifndef SS_ANSI\r
+\r
+ bool Load(UINT nId, HMODULE hModule=NULL)\r
+ {\r
+ bool bLoaded = false; // set to true of we succeed.\r
+\r
+ #ifdef _MFC_VER // When in Rome (or MFC land)...\r
+\r
+ CString strRes;\r
+ bLoaded = FALSE != strRes.LoadString(nId);\r
+ if ( bLoaded )\r
+ *this = strRes;\r
+\r
+ #else // otherwise make our own hackneyed version of CString's Load\r
+ \r
+ // Get the resource name and module handle\r
+\r
+ if ( NULL == hModule )\r
+ hModule = GetResourceHandle();\r
+\r
+ PCTSTR szName = MAKEINTRESOURCE((nId>>4)+1); // lifted \r
+ DWORD dwSize = 0;\r
+\r
+ // No sense continuing if we can't find the resource\r
+\r
+ HRSRC hrsrc = ::FindResource(hModule, szName, RT_STRING);\r
+\r
+ if ( NULL == hrsrc )\r
+ {\r
+ TRACE(_T("Cannot find resource %d: 0x%X"), nId, ::GetLastError());\r
+ }\r
+ else if ( 0 == (dwSize = ::SizeofResource(hModule, hrsrc) / sizeof(CT)))\r
+ {\r
+ TRACE(_T("Cant get size of resource %d 0x%X\n"),nId,GetLastError());\r
+ }\r
+ else\r
+ {\r
+ bLoaded = 0 != ssload(hModule, nId, GetBuf(dwSize), dwSize);\r
+ ReleaseBuffer();\r
+ }\r
+\r
+ #endif // #ifdef _MFC_VER\r
+\r
+ if ( !bLoaded )\r
+ TRACE(_T("String not loaded 0x%X\n"), ::GetLastError());\r
+\r
+ return bLoaded;\r
+ }\r
+\r
+#endif // #ifdef SS_ANSI\r
+ \r
+ // -------------------------------------------------------------------------\r
+ // FUNCTION: CStdStr::Format\r
+ // void _cdecl Formst(CStdStringA& PCSTR szFormat, ...)\r
+ // void _cdecl Format(PCSTR szFormat);\r
+ // \r
+ // DESCRIPTION:\r
+ // This function does sprintf/wsprintf style formatting on CStdStringA\r
+ // objects. It looks a lot like MFC's CString::Format. Some people\r
+ // might even call this identical. Fortunately, these people are now\r
+ // dead... heh heh.\r
+ //\r
+ // PARAMETERS: \r
+ // nId - ID of string resource holding the format string\r
+ // szFormat - a PCSTR holding the format specifiers\r
+ // argList - a va_list holding the arguments for the format specifiers.\r
+ //\r
+ // RETURN VALUE: None.\r
+ // -------------------------------------------------------------------------\r
+ // formatting (using wsprintf style formatting)\r
+\r
+ // If they want a Format() function that safely handles string objects\r
+ // without casting\r
+ \r
+#ifdef SS_SAFE_FORMAT \r
+ \r
+ // Question: Joe, you wacky coder you, why do you have so many overloads\r
+ // of the Format() function\r
+ // Answer: One reason only - CString compatability. In short, by making\r
+ // the Format() function a template this way, I can do strong typing\r
+ // and allow people to pass CStdString arguments as fillers for\r
+ // "%s" format specifiers without crashing their program! The downside\r
+ // is that I need to overload on the number of arguments. If you are\r
+ // passing more arguments than I have listed below in any of my\r
+ // overloads, just add another one.\r
+ //\r
+ // Yes, yes, this is really ugly. In essence what I am doing here is\r
+ // protecting people from a bad (and incorrect) programming practice\r
+ // that they should not be doing anyway. I am protecting them from\r
+ // themselves. Why am I doing this? Well, if you had any idea the\r
+ // number of times I've been emailed by people about this\r
+ // "incompatability" in my code, you wouldn't ask.\r
+\r
+ void Fmt(const CT* szFmt, ...)\r
+ {\r
+ va_list argList;\r
+ va_start(argList, szFmt);\r
+ FormatV(szFmt, argList);\r
+ va_end(argList);\r
+ }\r
+\r
+#ifndef SS_ANSI\r
+\r
+ void Format(UINT nId)\r
+ {\r
+ MYTYPE strFmt;\r
+ if ( strFmt.Load(nId) ) \r
+ this->swap(strFmt);\r
+ }\r
+ template<class A1>\r
+ void Format(UINT nId, const A1& v)\r
+ {\r
+ MYTYPE strFmt;\r
+ if ( strFmt.Load(nId) )\r
+ Fmt(strFmt, FmtArg<A1>(v).Val());\r
+ }\r
+ template<class A1, class A2>\r
+ void Format(UINT nId, const A1& v1, const A2& v2)\r
+ {\r
+ MYTYPE strFmt;\r
+ if ( strFmt.Load(nId) )\r
+ Fmt(strFmt, FmtArg<A1>(v1).Val(), FmtArg<A2>(v2).Val());\r
+ }\r
+ template<class A1, class A2, class A3>\r
+ void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3)\r
+ {\r
+ MYTYPE strFmt;\r
+ if ( strFmt.Load(nId) )\r
+ {\r
+ Fmt(strFmt, FmtArg<A1>(v1).Val(), FmtArg<A2>(v2).Val(),\r
+ FmtArg<A3>(v3).Val());\r
+ }\r
+ }\r
+ template<class A1, class A2, class A3, class A4>\r
+ void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,\r
+ const A4& v4)\r
+ {\r
+ MYTYPE strFmt;\r
+ if ( strFmt.Load(nId) )\r
+ {\r
+ Fmt(strFmt, FmtArg<A1>(v1).Val(), FmtArg<A2>(v2).Val(),\r
+ FmtArg<A3>(v3).Val(), FmtArg<A4>(v4).Val());\r
+ }\r
+ }\r
+ template<class A1, class A2, class A3, class A4, class A5>\r
+ void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,\r
+ const A4& v4, const A5& v5)\r
+ {\r
+ MYTYPE strFmt;\r
+ if ( strFmt.Load(nId) )\r
+ {\r
+ Fmt(strFmt, FmtArg<A1>(v1).Val(), FmtArg<A2>(v2).Val(),\r
+ FmtArg<A3>(v3).Val(), FmtArg<A4>(v4).Val(), FmtArg<A5>(v5).Val());\r
+ }\r
+ }\r
+ template<class A1, class A2, class A3, class A4, class A5, class A6>\r
+ void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,\r
+ const A4& v4, const A5& v5, const A6& v6)\r
+ {\r
+ MYTYPE strFmt;\r
+ if ( strFmt.Load(nId) )\r
+ {\r
+ Fmt(strFmt, FmtArg<A1>(v1).Val(), FmtArg<A2>(v2).Val(),\r
+ FmtArg<A3>(v3).Val(), FmtArg<A4>(v4).Val(),FmtArg<A5>(v5).Val(),\r
+ FmtArg<A6>(v6).Val());\r
+ }\r
+ }\r
+ template<class A1, class A2, class A3, class A4, class A5, class A6,\r
+ class A7>\r
+ void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,\r
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7)\r
+ {\r
+ MYTYPE strFmt;\r
+ if ( strFmt.Load(nId) )\r
+ {\r
+ Fmt(strFmt, FmtArg<A1>(v1).Val(), FmtArg<A2>(v2).Val(),\r
+ FmtArg<A3>(v3).Val(), FmtArg<A4>(v4).Val(),FmtArg<A5>(v5).Val(),\r
+ FmtArg<A6>(v6).Val(), FmtArg<A7>(v7).Val());\r
+ }\r
+ }\r
+ template<class A1, class A2, class A3, class A4, class A5, class A6,\r
+ class A7, class A8>\r
+ void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,\r
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,\r
+ const A8& v8)\r
+ {\r
+ MYTYPE strFmt;\r
+ if ( strFmt.Load(nId) )\r
+ {\r
+ Fmt(strFmt, FmtArg<A1>(v1).Val(), FmtArg<A2>(v2).Val(),\r
+ FmtArg<A3>(v3).Val(), FmtArg<A4>(v4).Val(), FmtArg<A5>(v5).Val(),\r
+ FmtArg<A6>(v6).Val(), FmtArg<A7>(v7).Val(), FmtArg<A8>(v8).Val());\r
+ }\r
+ }\r
+ template<class A1, class A2, class A3, class A4, class A5, class A6,\r
+ class A7, class A8, class A9>\r
+ void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,\r
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,\r
+ const A8& v8, const A9& v9)\r
+ {\r
+ MYTYPE strFmt;\r
+ if ( strFmt.Load(nId) )\r
+ {\r
+ Fmt(strFmt, FmtArg<A1>(v1).Val(), FmtArg<A2>(v2).Val(),\r
+ FmtArg<A3>(v3).Val(), FmtArg<A4>(v4).Val(), FmtArg<A5>(v5).Val(),\r
+ FmtArg<A6>(v6).Val(), FmtArg<A7>(v7).Val(), FmtArg<A8>(v8).Val(),\r
+ FmtArg<A9>(v9).Val());\r
+ }\r
+ }\r
+ template<class A1, class A2, class A3, class A4, class A5, class A6,\r
+ class A7, class A8, class A9, class A10>\r
+ void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,\r
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,\r
+ const A8& v8, const A9& v9, const A10& v10)\r
+ {\r
+ MYTYPE strFmt;\r
+ if ( strFmt.Load(nId) )\r
+ {\r
+ Fmt(strFmt, FmtArg<A1>(v1).Val(), FmtArg<A2>(v2).Val(),\r
+ FmtArg<A3>(v3).Val(), FmtArg<A4>(v4).Val(), FmtArg<A5>(v5).Val(),\r
+ FmtArg<A6>(v6).Val(), FmtArg<A7>(v7).Val(), FmtArg<A8>(v8).Val(),\r
+ FmtArg<A9>(v9).Val(), FmtArg<A10>(v10).Val());\r
+ }\r
+ }\r
+ template<class A1, class A2, class A3, class A4, class A5, class A6,\r
+ class A7, class A8, class A9, class A10, class A11>\r
+ void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,\r
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,\r
+ const A8& v8, const A9& v9, const A10& v10, const A11& v11)\r
+ {\r
+ MYTYPE strFmt;\r
+ if ( strFmt.Load(nId) )\r
+ {\r
+ Fmt(strFmt, FmtArg<A1>(v1).Val(), FmtArg<A2>(v2).Val(),\r
+ FmtArg<A3>(v3).Val(), FmtArg<A4>(v4).Val(), FmtArg<A5>(v5).Val(),\r
+ FmtArg<A6>(v6).Val(), FmtArg<A7>(v7).Val(), FmtArg<A8>(v8).Val(),\r
+ FmtArg<A9>(v9).Val(),FmtArg<A10>(v10).Val(),FmtArg<A11>(v11).Val());\r
+ }\r
+ }\r
+ template<class A1, class A2, class A3, class A4, class A5, class A6,\r
+ class A7, class A8, class A9, class A10, class A11, class A12>\r
+ void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,\r
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,\r
+ const A8& v8, const A9& v9, const A10& v10, const A11& v11,\r
+ const A12& v12)\r
+ {\r
+ MYTYPE strFmt;\r
+ if ( strFmt.Load(nId) )\r
+ {\r
+ Fmt(strFmt, FmtArg<A1>(v1).Val(), FmtArg<A2>(v2).Val(),\r
+ FmtArg<A3>(v3).Val(), FmtArg<A4>(v4).Val(), FmtArg<A5>(v5).Val(),\r
+ FmtArg<A6>(v6).Val(), FmtArg<A7>(v7).Val(), FmtArg<A8>(v8).Val(),\r
+ FmtArg<A9>(v9).Val(), FmtArg<A10>(v10).Val(),FmtArg<A11>(v11).Val(),\r
+ FmtArg<A12>(v12).Val());\r
+ }\r
+ }\r
+ template<class A1, class A2, class A3, class A4, class A5, class A6,\r
+ class A7, class A8, class A9, class A10, class A11, class A12,\r
+ class A13>\r
+ void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,\r
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,\r
+ const A8& v8, const A9& v9, const A10& v10, const A11& v11,\r
+ const A12& v12, const A13& v13)\r
+ {\r
+ MYTYPE strFmt;\r
+ if ( strFmt.Load(nId) )\r
+ {\r
+ Fmt(strFmt, FmtArg<A1>(v1).Val(), FmtArg<A2>(v2).Val(),\r
+ FmtArg<A3>(v3).Val(), FmtArg<A4>(v4).Val(), FmtArg<A5>(v5).Val(),\r
+ FmtArg<A6>(v6).Val(), FmtArg<A7>(v7).Val(), FmtArg<A8>(v8).Val(),\r
+ FmtArg<A9>(v9).Val(), FmtArg<A10>(v10).Val(),FmtArg<A11>(v11).Val(),\r
+ FmtArg<A12>(v12).Val(), FmtArg<A13>(v13).Val());\r
+ }\r
+ }\r
+ template<class A1, class A2, class A3, class A4, class A5, class A6,\r
+ class A7, class A8, class A9, class A10, class A11, class A12,\r
+ class A13, class A14>\r
+ void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,\r
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,\r
+ const A8& v8, const A9& v9, const A10& v10, const A11& v11,\r
+ const A12& v12, const A13& v13, const A14& v14)\r
+ {\r
+ MYTYPE strFmt;\r
+ if ( strFmt.Load(nId) )\r
+ {\r
+ Fmt(strFmt, FmtArg<A1>(v1).Val(), FmtArg<A2>(v2).Val(),\r
+ FmtArg<A3>(v3).Val(), FmtArg<A4>(v4).Val(), FmtArg<A5>(v5).Val(),\r
+ FmtArg<A6>(v6).Val(), FmtArg<A7>(v7).Val(), FmtArg<A8>(v8).Val(),\r
+ FmtArg<A9>(v9).Val(), FmtArg<A10>(v10).Val(),FmtArg<A11>(v11).Val(),\r
+ FmtArg<A12>(v12).Val(), FmtArg<A13>(v13).Val(),FmtArg<A14>(v14).Val());\r
+ }\r
+ }\r
+ template<class A1, class A2, class A3, class A4, class A5, class A6,\r
+ class A7, class A8, class A9, class A10, class A11, class A12,\r
+ class A13, class A14, class A15>\r
+ void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,\r
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,\r
+ const A8& v8, const A9& v9, const A10& v10, const A11& v11,\r
+ const A12& v12, const A13& v13, const A14& v14, const A15& v15)\r
+ {\r
+ MYTYPE strFmt;\r
+ if ( strFmt.Load(nId) )\r
+ {\r
+ Fmt(strFmt, FmtArg<A1>(v1).Val(), FmtArg<A2>(v2).Val(),\r
+ FmtArg<A3>(v3).Val(), FmtArg<A4>(v4).Val(), FmtArg<A5>(v5).Val(),\r
+ FmtArg<A6>(v6).Val(), FmtArg<A7>(v7).Val(), FmtArg<A8>(v8).Val(),\r
+ FmtArg<A9>(v9).Val(), FmtArg<A10>(v10).Val(),FmtArg<A11>(v11).Val(),\r
+ FmtArg<A12>(v12).Val(),FmtArg<A13>(v13).Val(),FmtArg<A14>(v14).Val(),\r
+ FmtArg<A15>(v15).Val());\r
+ }\r
+ }\r
+ template<class A1, class A2, class A3, class A4, class A5, class A6,\r
+ class A7, class A8, class A9, class A10, class A11, class A12,\r
+ class A13, class A14, class A15, class A16>\r
+ void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,\r
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,\r
+ const A8& v8, const A9& v9, const A10& v10, const A11& v11,\r
+ const A12& v12, const A13& v13, const A14& v14, const A15& v15,\r
+ const A16& v16)\r
+ {\r
+ MYTYPE strFmt;\r
+ if ( strFmt.Load(nId) )\r
+ {\r
+ Fmt(strFmt, FmtArg<A1>(v1).Val(), FmtArg<A2>(v2).Val(),\r
+ FmtArg<A3>(v3).Val(), FmtArg<A4>(v4).Val(), FmtArg<A5>(v5).Val(),\r
+ FmtArg<A6>(v6).Val(), FmtArg<A7>(v7).Val(), FmtArg<A8>(v8).Val(),\r
+ FmtArg<A9>(v9).Val(), FmtArg<A10>(v10).Val(),FmtArg<A11>(v11).Val(),\r
+ FmtArg<A12>(v12).Val(),FmtArg<A13>(v13).Val(),FmtArg<A14>(v14).Val(),\r
+ FmtArg<A15>(v15).Val(), FmtArg<A16>(v16).Val());\r
+ }\r
+ }\r
+ template<class A1, class A2, class A3, class A4, class A5, class A6,\r
+ class A7, class A8, class A9, class A10, class A11, class A12,\r
+ class A13, class A14, class A15, class A16, class A17>\r
+ void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,\r
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,\r
+ const A8& v8, const A9& v9, const A10& v10, const A11& v11,\r
+ const A12& v12, const A13& v13, const A14& v14, const A15& v15,\r
+ const A16& v16, const A17& v17)\r
+ {\r
+ MYTYPE strFmt;\r
+ if ( strFmt.Load(nId) )\r
+ {\r
+ Fmt(strFmt, FmtArg<A1>(v1).Val(), FmtArg<A2>(v2).Val(),\r
+ FmtArg<A3>(v3).Val(), FmtArg<A4>(v4).Val(), FmtArg<A5>(v5).Val(),\r
+ FmtArg<A6>(v6).Val(), FmtArg<A7>(v7).Val(), FmtArg<A8>(v8).Val(),\r
+ FmtArg<A9>(v9).Val(), FmtArg<A10>(v10).Val(),FmtArg<A11>(v11).Val(),\r
+ FmtArg<A12>(v12).Val(),FmtArg<A13>(v13).Val(),FmtArg<A14>(v14).Val(),\r
+ FmtArg<A15>(v15).Val(),FmtArg<A16>(v16).Val(),FmtArg<A17>(v17).Val());\r
+ }\r
+ }\r
+ \r
+#endif // #ifndef SS_ANSI\r
+\r
+ // ...now the other overload of Format: the one that takes a string literal\r
+\r
+ void Format(const CT* szFmt)\r
+ {\r
+ *this = szFmt;\r
+ }\r
+ template<class A1>\r
+ void Format(const CT* szFmt, A1 v)\r
+ {\r
+ Fmt(szFmt, FmtArg<A1>(v).Val());\r
+ }\r
+ template<class A1, class A2>\r
+ void Format(const CT* szFmt, const A1& v1, const A2& v2)\r
+ {\r
+ Fmt(szFmt, FmtArg<A1>(v1).Val(), FmtArg<A2>(v2).Val());\r
+ }\r
+ template<class A1, class A2, class A3>\r
+ void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3)\r
+ {\r
+ Fmt(szFmt, FmtArg<A1>(v1).Val(), FmtArg<A2>(v2).Val(),\r
+ FmtArg<A3>(v3).Val());\r
+ }\r
+ template<class A1, class A2, class A3, class A4>\r
+ void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,\r
+ const A4& v4)\r
+ {\r
+ Fmt(szFmt, FmtArg<A1>(v1).Val(), FmtArg<A2>(v2).Val(),\r
+ FmtArg<A3>(v3).Val(), FmtArg<A4>(v4).Val());\r
+ }\r
+ template<class A1, class A2, class A3, class A4, class A5>\r
+ void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,\r
+ const A4& v4, const A5& v5)\r
+ {\r
+ Fmt(szFmt, FmtArg<A1>(v1).Val(), FmtArg<A2>(v2).Val(),\r
+ FmtArg<A3>(v3).Val(), FmtArg<A4>(v4).Val(), FmtArg<A5>(v5).Val());\r
+ }\r
+ template<class A1, class A2, class A3, class A4, class A5, class A6>\r
+ void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,\r
+ const A4& v4, const A5& v5, const A6& v6)\r
+ {\r
+ Fmt(szFmt, FmtArg<A1>(v1).Val(), FmtArg<A2>(v2).Val(),\r
+ FmtArg<A3>(v3).Val(), FmtArg<A4>(v4).Val(), FmtArg<A5>(v5).Val(),\r
+ FmtArg<A6>(v6).Val());\r
+ }\r
+ template<class A1, class A2, class A3, class A4, class A5, class A6,\r
+ class A7>\r
+ void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,\r
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7)\r
+ {\r
+ Fmt(szFmt, FmtArg<A1>(v1).Val(), FmtArg<A2>(v2).Val(),\r
+ FmtArg<A3>(v3).Val(), FmtArg<A4>(v4).Val(), FmtArg<A5>(v5).Val(),\r
+ FmtArg<A6>(v6).Val(), FmtArg<A7>(v7).Val());\r
+ }\r
+ template<class A1, class A2, class A3, class A4, class A5, class A6,\r
+ class A7, class A8>\r
+ void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,\r
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,\r
+ const A8& v8)\r
+ {\r
+ Fmt(szFmt, FmtArg<A1>(v1).Val(), FmtArg<A2>(v2).Val(),\r
+ FmtArg<A3>(v3).Val(), FmtArg<A4>(v4).Val(), FmtArg<A5>(v5).Val(),\r
+ FmtArg<A6>(v6).Val(), FmtArg<A7>(v7).Val(), FmtArg<A8>(v8).Val());\r
+ }\r
+ template<class A1, class A2, class A3, class A4, class A5, class A6,\r
+ class A7, class A8, class A9>\r
+ void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,\r
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,\r
+ const A8& v8, const A9& v9)\r
+ {\r
+ Fmt(szFmt, FmtArg<A1>(v1).Val(), FmtArg<A2>(v2).Val(),\r
+ FmtArg<A3>(v3).Val(), FmtArg<A4>(v4).Val(), FmtArg<A5>(v5).Val(),\r
+ FmtArg<A6>(v6).Val(), FmtArg<A7>(v7).Val(), FmtArg<A8>(v8).Val(),\r
+ FmtArg<A9>(v9).Val());\r
+ }\r
+ template<class A1, class A2, class A3, class A4, class A5, class A6,\r
+ class A7, class A8, class A9, class A10>\r
+ void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,\r
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,\r
+ const A8& v8, const A9& v9, const A10& v10)\r
+ {\r
+ Fmt(szFmt, FmtArg<A1>(v1).Val(), FmtArg<A2>(v2).Val(),\r
+ FmtArg<A3>(v3).Val(), FmtArg<A4>(v4).Val(), FmtArg<A5>(v5).Val(),\r
+ FmtArg<A6>(v6).Val(), FmtArg<A7>(v7).Val(), FmtArg<A8>(v8).Val(),\r
+ FmtArg<A9>(v9).Val(), FmtArg<A10>(v10).Val());\r
+ }\r
+ template<class A1, class A2, class A3, class A4, class A5, class A6,\r
+ class A7, class A8, class A9, class A10, class A11>\r
+ void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,\r
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,\r
+ const A8& v8, const A9& v9, const A10& v10, const A11& v11)\r
+ {\r
+ Fmt(szFmt, FmtArg<A1>(v1).Val(), FmtArg<A2>(v2).Val(),\r
+ FmtArg<A3>(v3).Val(), FmtArg<A4>(v4).Val(), FmtArg<A5>(v5).Val(),\r
+ FmtArg<A6>(v6).Val(), FmtArg<A7>(v7).Val(), FmtArg<A8>(v8).Val(),\r
+ FmtArg<A9>(v9).Val(),FmtArg<A10>(v10).Val(),FmtArg<A11>(v11).Val());\r
+ }\r
+ template<class A1, class A2, class A3, class A4, class A5, class A6,\r
+ class A7, class A8, class A9, class A10, class A11, class A12>\r
+ void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,\r
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,\r
+ const A8& v8, const A9& v9, const A10& v10, const A11& v11,\r
+ const A12& v12)\r
+ {\r
+ Fmt(szFmt, FmtArg<A1>(v1).Val(), FmtArg<A2>(v2).Val(),\r
+ FmtArg<A3>(v3).Val(), FmtArg<A4>(v4).Val(), FmtArg<A5>(v5).Val(),\r
+ FmtArg<A6>(v6).Val(), FmtArg<A7>(v7).Val(), FmtArg<A8>(v8).Val(),\r
+ FmtArg<A9>(v9).Val(), FmtArg<A10>(v10).Val(),FmtArg<A11>(v11).Val(),\r
+ FmtArg<A12>(v12).Val());\r
+ }\r
+ template<class A1, class A2, class A3, class A4, class A5, class A6,\r
+ class A7, class A8, class A9, class A10, class A11, class A12,\r
+ class A13>\r
+ void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,\r
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,\r
+ const A8& v8, const A9& v9, const A10& v10, const A11& v11,\r
+ const A12& v12, const A13& v13)\r
+ {\r
+ Fmt(szFmt, FmtArg<A1>(v1).Val(), FmtArg<A2>(v2).Val(),\r
+ FmtArg<A3>(v3).Val(), FmtArg<A4>(v4).Val(), FmtArg<A5>(v5).Val(),\r
+ FmtArg<A6>(v6).Val(), FmtArg<A7>(v7).Val(), FmtArg<A8>(v8).Val(),\r
+ FmtArg<A9>(v9).Val(), FmtArg<A10>(v10).Val(),FmtArg<A11>(v11).Val(),\r
+ FmtArg<A12>(v12).Val(), FmtArg<A13>(v13).Val());\r
+ }\r
+ template<class A1, class A2, class A3, class A4, class A5, class A6,\r
+ class A7, class A8, class A9, class A10, class A11, class A12,\r
+ class A13, class A14>\r
+ void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,\r
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,\r
+ const A8& v8, const A9& v9, const A10& v10, const A11& v11,\r
+ const A12& v12, const A13& v13, const A14& v14)\r
+ {\r
+ Fmt(szFmt, FmtArg<A1>(v1).Val(), FmtArg<A2>(v2).Val(),\r
+ FmtArg<A3>(v3).Val(), FmtArg<A4>(v4).Val(), FmtArg<A5>(v5).Val(),\r
+ FmtArg<A6>(v6).Val(), FmtArg<A7>(v7).Val(), FmtArg<A8>(v8).Val(),\r
+ FmtArg<A9>(v9).Val(), FmtArg<A10>(v10).Val(),FmtArg<A11>(v11).Val(),\r
+ FmtArg<A12>(v12).Val(), FmtArg<A13>(v13).Val(),FmtArg<A14>(v14).Val());\r
+ }\r
+ template<class A1, class A2, class A3, class A4, class A5, class A6,\r
+ class A7, class A8, class A9, class A10, class A11, class A12,\r
+ class A13, class A14, class A15>\r
+ void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,\r
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,\r
+ const A8& v8, const A9& v9, const A10& v10, const A11& v11,\r
+ const A12& v12, const A13& v13, const A14& v14, const A15& v15)\r
+ {\r
+ Fmt(szFmt, FmtArg<A1>(v1).Val(), FmtArg<A2>(v2).Val(),\r
+ FmtArg<A3>(v3).Val(), FmtArg<A4>(v4).Val(), FmtArg<A5>(v5).Val(),\r
+ FmtArg<A6>(v6).Val(), FmtArg<A7>(v7).Val(), FmtArg<A8>(v8).Val(),\r
+ FmtArg<A9>(v9).Val(), FmtArg<A10>(v10).Val(),FmtArg<A11>(v11).Val(),\r
+ FmtArg<A12>(v12).Val(),FmtArg<A13>(v13).Val(),FmtArg<A14>(v14).Val(),\r
+ FmtArg<A15>(v15).Val());\r
+ }\r
+ template<class A1, class A2, class A3, class A4, class A5, class A6,\r
+ class A7, class A8, class A9, class A10, class A11, class A12,\r
+ class A13, class A14, class A15, class A16>\r
+ void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,\r
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,\r
+ const A8& v8, const A9& v9, const A10& v10, const A11& v11,\r
+ const A12& v12, const A13& v13, const A14& v14, const A15& v15,\r
+ const A16& v16)\r
+ {\r
+ Fmt(szFmt, FmtArg<A1>(v1).Val(), FmtArg<A2>(v2).Val(),\r
+ FmtArg<A3>(v3).Val(), FmtArg<A4>(v4).Val(), FmtArg<A5>(v5).Val(),\r
+ FmtArg<A6>(v6).Val(), FmtArg<A7>(v7).Val(), FmtArg<A8>(v8).Val(),\r
+ FmtArg<A9>(v9).Val(), FmtArg<A10>(v10).Val(),FmtArg<A11>(v11).Val(),\r
+ FmtArg<A12>(v12).Val(),FmtArg<A13>(v13).Val(),FmtArg<A14>(v14).Val(),\r
+ FmtArg<A15>(v15).Val(), FmtArg<A16>(v16).Val());\r
+ }\r
+ template<class A1, class A2, class A3, class A4, class A5, class A6,\r
+ class A7, class A8, class A9, class A10, class A11, class A12,\r
+ class A13, class A14, class A15, class A16, class A17>\r
+ void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,\r
+ const A4& v4, const A5& v5, const A6& v6, const A7& v7,\r
+ const A8& v8, const A9& v9, const A10& v10, const A11& v11,\r
+ const A12& v12, const A13& v13, const A14& v14, const A15& v15,\r
+ const A16& v16, const A17& v17)\r
+ {\r
+ Fmt(szFmt, FmtArg<A1>(v1).Val(), FmtArg<A2>(v2).Val(),\r
+ FmtArg<A3>(v3).Val(), FmtArg<A4>(v4).Val(), FmtArg<A5>(v5).Val(),\r
+ FmtArg<A6>(v6).Val(), FmtArg<A7>(v7).Val(), FmtArg<A8>(v8).Val(),\r
+ FmtArg<A9>(v9).Val(), FmtArg<A10>(v10).Val(),FmtArg<A11>(v11).Val(),\r
+ FmtArg<A12>(v12).Val(),FmtArg<A13>(v13).Val(),FmtArg<A14>(v14).Val(),\r
+ FmtArg<A15>(v15).Val(),FmtArg<A16>(v16).Val(),FmtArg<A17>(v17).Val());\r
+ }\r
+\r
+#else // #ifdef SS_SAFE_FORMAT\r
+\r
+\r
+#ifndef SS_ANSI\r
+\r
+ void Format(UINT nId, ...)\r
+ {\r
+ va_list argList;\r
+ va_start(argList, nId);\r
+ va_start(argList, nId);\r
+\r
+ MYTYPE strFmt;\r
+ if ( strFmt.Load(nId) )\r
+ FormatV(strFmt, argList);\r
+\r
+ va_end(argList);\r
+ }\r
+ \r
+#endif // #ifdef SS_ANSI\r
+\r
+ void Format(const CT* szFmt, ...)\r
+ {\r
+ va_list argList;\r
+ va_start(argList, szFmt);\r
+ FormatV(szFmt, argList);\r
+ va_end(argList);\r
+ }\r
+\r
+#endif // #ifdef SS_SAFE_FORMAT\r
+\r
+ void AppendFormat(const CT* szFmt, ...)\r
+ {\r
+ va_list argList;\r
+ va_start(argList, szFmt);\r
+ AppendFormatV(szFmt, argList);\r
+ va_end(argList);\r
+ }\r
+\r
+ #define MAX_FMT_TRIES 5 // #of times we try \r
+ #define FMT_BLOCK_SIZE 2048 // # of bytes to increment per try\r
+ #define BUFSIZE_1ST 256\r
+ #define BUFSIZE_2ND 512\r
+ #define STD_BUF_SIZE 1024\r
+\r
+ // an efficient way to add formatted characters to the string. You may only\r
+ // add up to STD_BUF_SIZE characters at a time, though\r
+ void AppendFormatV(const CT* szFmt, va_list argList)\r
+ {\r
+ CT szBuf[STD_BUF_SIZE];\r
+ #if defined(SS_ANSI) || !defined(_MSC_VER)\r
+ int nLen = ssvsprintf(szBuf, STD_BUF_SIZE-1, szFmt, argList);\r
+ #else\r
+ int nLen = ssnprintf(szBuf, STD_BUF_SIZE-1, szFmt, argList);\r
+ #endif\r
+ if ( 0 < nLen )\r
+ this->append(szBuf, nLen);\r
+ }\r
+\r
+ // -------------------------------------------------------------------------\r
+ // FUNCTION: FormatV\r
+ // void FormatV(PCSTR szFormat, va_list, argList);\r
+ // \r
+ // DESCRIPTION:\r
+ // This function formats the string with sprintf style format-specs. \r
+ // It makes a general guess at required buffer size and then tries\r
+ // successively larger buffers until it finds one big enough or a\r
+ // threshold (MAX_FMT_TRIES) is exceeded.\r
+ //\r
+ // PARAMETERS:\r
+ // szFormat - a PCSTR holding the format of the output\r
+ // argList - a Microsoft specific va_list for variable argument lists\r
+ //\r
+ // RETURN VALUE:\r
+ // -------------------------------------------------------------------------\r
+\r
+ void FormatV(const CT* szFormat, va_list argList)\r
+ {\r
+ #if defined(SS_ANSI) || !defined(_MSC_VER)\r
+ int nLen = sslen(szFormat) + STD_BUF_SIZE;\r
+ ssvsprintf(GetBuffer(nLen), nLen-1, szFormat, argList);\r
+ ReleaseBuffer();\r
+\r
+ #else\r
+\r
+ CT* pBuf = NULL;\r
+ int nChars = 1;\r
+ int nUsed = 0;\r
+ size_type nActual = 0;\r
+ int nTry = 0;\r
+\r
+ do\r
+ {\r
+ // Grow more than linearly (e.g. 512, 1536, 3072, etc)\r
+\r
+ nChars += ((nTry+1) * FMT_BLOCK_SIZE);\r
+ pBuf = reinterpret_cast<CT*>(_alloca(sizeof(CT)*nChars));\r
+ nUsed = ssnprintf(pBuf, nChars-1, szFormat, argList);\r
+\r
+ // Ensure proper NULL termination.\r
+\r
+ nActual = nUsed == -1 ? nChars-1 : SSMIN(nUsed, nChars-1);\r
+ pBuf[nActual+1]= '\0';\r
+\r
+\r
+ } while ( nUsed < 0 && nTry++ < MAX_FMT_TRIES );\r
+\r
+ // assign whatever we managed to format\r
+\r
+ this->assign(pBuf, nActual);\r
+\r
+ #endif\r
+ }\r
+ \r
+\r
+ // -------------------------------------------------------------------------\r
+ // CString Facade Functions:\r
+ //\r
+ // The following methods are intended to allow you to use this class as a\r
+ // drop-in replacement for CString.\r
+ // -------------------------------------------------------------------------\r
+ #ifdef SS_WIN32\r
+ BSTR AllocSysString() const\r
+ {\r
+ ostring os;\r
+ ssasn(os, *this);\r
+ return ::SysAllocString(os.c_str());\r
+ }\r
+ #endif\r
+\r
+ int Collate(PCMYSTR szThat) const\r
+ {\r
+ return sscoll(this->c_str(), this->length(), szThat, sslen(szThat));\r
+ }\r
+\r
+ int CollateNoCase(PCMYSTR szThat) const\r
+ {\r
+ return ssicoll(this->c_str(), this->length(), szThat, sslen(szThat));\r
+ }\r
+\r
+ int Compare(PCMYSTR szThat) const\r
+ {\r
+ return this->compare(szThat); \r
+ }\r
+\r
+ int CompareNoCase(PCMYSTR szThat) const\r
+ {\r
+ return ssicmp(this->c_str(), szThat);\r
+ }\r
+\r
+ int Delete(int nIdx, int nCount=1)\r
+ {\r
+ if ( nIdx < 0 )\r
+ nIdx = 0;\r
+\r
+ if ( nIdx < GetLength() )\r
+ this->erase(static_cast<MYSIZE>(nIdx), static_cast<MYSIZE>(nCount));\r
+\r
+ return GetLength();\r
+ }\r
+\r
+ void Empty()\r
+ {\r
+ this->erase();\r
+ }\r
+\r
+ int Find(CT ch) const\r
+ {\r
+ MYSIZE nIdx = this->find_first_of(ch);\r
+ return static_cast<int>(MYBASE::npos == nIdx ? -1 : nIdx);\r
+ }\r
+\r
+ int Find(PCMYSTR szSub) const\r
+ {\r
+ MYSIZE nIdx = this->find(szSub);\r
+ return static_cast<int>(MYBASE::npos == nIdx ? -1 : nIdx);\r
+ }\r
+\r
+ int Find(CT ch, int nStart) const\r
+ {\r
+ // CString::Find docs say add 1 to nStart when it's not zero\r
+ // CString::Find code doesn't do that however. We'll stick\r
+ // with what the code does\r
+\r
+ MYSIZE nIdx = this->find_first_of(ch, static_cast<MYSIZE>(nStart));\r
+ return static_cast<int>(MYBASE::npos == nIdx ? -1 : nIdx);\r
+ }\r
+\r
+ int Find(PCMYSTR szSub, int nStart) const\r
+ {\r
+ // CString::Find docs say add 1 to nStart when it's not zero\r
+ // CString::Find code doesn't do that however. We'll stick\r
+ // with what the code does\r
+\r
+ MYSIZE nIdx = this->find(szSub, static_cast<MYSIZE>(nStart));\r
+ return static_cast<int>(MYBASE::npos == nIdx ? -1 : nIdx);\r
+ }\r
+\r
+ int FindOneOf(PCMYSTR szCharSet) const\r
+ {\r
+ MYSIZE nIdx = this->find_first_of(szCharSet);\r
+ return static_cast<int>(MYBASE::npos == nIdx ? -1 : nIdx);\r
+ }\r
+\r
+#ifndef SS_ANSI\r
+ void FormatMessage(PCMYSTR szFormat, ...) throw(std::exception)\r
+ {\r
+ va_list argList;\r
+ va_start(argList, szFormat);\r
+ PMYSTR szTemp;\r
+ if ( ssfmtmsg(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER,\r
+ szFormat, 0, 0,\r
+ reinterpret_cast<PMYSTR>(&szTemp), 0, &argList) == 0 ||\r
+ szTemp == 0 )\r
+ {\r
+ throw std::runtime_error("out of memory");\r
+ }\r
+ *this = szTemp;\r
+ LocalFree(szTemp);\r
+ va_end(argList);\r
+ }\r
+\r
+ void FormatMessage(UINT nFormatId, ...) throw(std::exception)\r
+ {\r
+ MYTYPE sFormat;\r
+ VERIFY(sFormat.LoadString(nFormatId) != 0);\r
+ va_list argList;\r
+ va_start(argList, nFormatId);\r
+ PMYSTR szTemp;\r
+ if ( ssfmtmsg(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER,\r
+ sFormat, 0, 0,\r
+ reinterpret_cast<PMYSTR>(&szTemp), 0, &argList) == 0 ||\r
+ szTemp == 0)\r
+ {\r
+ throw std::runtime_error("out of memory");\r
+ }\r
+ *this = szTemp;\r
+ LocalFree(szTemp);\r
+ va_end(argList);\r
+ }\r
+#endif\r
+\r
+\r
+ // -------------------------------------------------------------------------\r
+ // GetXXXX -- Direct access to character buffer\r
+ // -------------------------------------------------------------------------\r
+ CT GetAt(int nIdx) const\r
+ {\r
+ return this->at(static_cast<MYSIZE>(nIdx));\r
+ }\r
+\r
+ CT* GetBuffer(int nMinLen=-1)\r
+ {\r
+ return GetBuf(nMinLen);\r
+ }\r
+\r
+ CT* GetBufferSetLength(int nLen)\r
+ {\r
+ return BufferSet(nLen);\r
+ }\r
+\r
+ // GetLength() -- MFC docs say this is the # of BYTES but\r
+ // in truth it is the number of CHARACTERs (chars or wchar_ts)\r
+ int GetLength() const\r
+ {\r
+ return static_cast<int>(this->length());\r
+ }\r
+\r
+ \r
+ int Insert(int nIdx, CT ch)\r
+ {\r
+ if ( static_cast<MYSIZE>(nIdx) > this->size() -1 )\r
+ this->append(1, ch);\r
+ else\r
+ this->insert(static_cast<MYSIZE>(nIdx), 1, ch);\r
+\r
+ return GetLength();\r
+ }\r
+ int Insert(int nIdx, PCMYSTR sz)\r
+ {\r
+ if ( nIdx >= this->size() )\r
+ this->append(sz, sslen(sz));\r
+ else\r
+ this->insert(static_cast<MYSIZE>(nIdx), sz);\r
+\r
+ return GetLength();\r
+ }\r
+\r
+ bool IsEmpty() const\r
+ {\r
+ return this->empty();\r
+ }\r
+\r
+ MYTYPE Left(int nCount) const\r
+ {\r
+ // Range check the count.\r
+\r
+ nCount = SSMAX(0, SSMIN(nCount, static_cast<int>(this->size())));\r
+ return this->substr(0, static_cast<MYSIZE>(nCount)); \r
+ }\r
+\r
+#ifndef SS_ANSI\r
+ bool LoadString(UINT nId)\r
+ {\r
+ return this->Load(nId);\r
+ }\r
+#endif\r
+\r
+ void MakeLower()\r
+ {\r
+ ToLower();\r
+ }\r
+\r
+ void MakeReverse()\r
+ {\r
+ std::reverse(this->begin(), this->end());\r
+ }\r
+\r
+ void MakeUpper()\r
+ { \r
+ ToUpper();\r
+ }\r
+\r
+ MYTYPE Mid(int nFirst ) const\r
+ {\r
+ return Mid(nFirst, size()-nFirst);\r
+ }\r
+\r
+ MYTYPE Mid(int nFirst, int nCount) const\r
+ {\r
+ // CString does range checking here. Since we're trying to emulate it,\r
+ // we must check too.\r
+\r
+ if ( nFirst < 0 )\r
+ nFirst = 0;\r
+ if ( nCount < 0 )\r
+ nCount = 0;\r
+\r
+ if ( nFirst + nCount > size() )\r
+ nCount = size() - nFirst;\r
+\r
+ if ( nFirst > size() )\r
+ return MYTYPE();\r
+\r
+ ASSERT(nFirst >= 0);\r
+ ASSERT(nFirst + nCount <= size());\r
+\r
+ return this->substr(static_cast<MYSIZE>(nFirst),\r
+ static_cast<MYSIZE>(nCount));\r
+ }\r
+\r
+ void ReleaseBuffer(int nNewLen=-1)\r
+ {\r
+ RelBuf(nNewLen);\r
+ }\r
+\r
+ int Remove(CT ch)\r
+ {\r
+ MYSIZE nIdx = 0;\r
+ int nRemoved = 0;\r
+ while ( (nIdx=this->find_first_of(ch)) != MYBASE::npos )\r
+ {\r
+ this->erase(nIdx, 1);\r
+ nRemoved++;\r
+ }\r
+ return nRemoved;\r
+ }\r
+\r
+ int Replace(CT chOld, CT chNew)\r
+ {\r
+ int nReplaced = 0;\r
+ for ( MYITER iter=this->begin(); iter != this->end(); iter++ )\r
+ {\r
+ if ( *iter == chOld )\r
+ {\r
+ *iter = chNew;\r
+ nReplaced++;\r
+ }\r
+ }\r
+ return nReplaced;\r
+ }\r
+\r
+ int Replace(PCMYSTR szOld, PCMYSTR szNew)\r
+ {\r
+ int nReplaced = 0;\r
+ MYSIZE nIdx = 0;\r
+ MYSIZE nOldLen = sslen(szOld);\r
+ if ( 0 == nOldLen )\r
+ return 0;\r
+\r
+ static const CT ch = CT(0);\r
+ MYSIZE nNewLen = sslen(szNew);\r
+ PCMYSTR szRealNew = szNew == 0 ? &ch : szNew;\r
+\r
+ while ( (nIdx=this->find(szOld, nIdx)) != MYBASE::npos )\r
+ {\r
+ replace(this->begin()+nIdx, this->begin()+nIdx+nOldLen, szRealNew);\r
+ nReplaced++;\r
+ nIdx += nNewLen;\r
+ }\r
+ return nReplaced;\r
+ }\r
+\r
+ int ReverseFind(CT ch) const\r
+ {\r
+ MYSIZE nIdx = this->find_last_of(ch);\r
+ return static_cast<int>(MYBASE::npos == nIdx ? -1 : nIdx);\r
+ }\r
+\r
+ // ReverseFind overload that's not in CString but might be useful\r
+ int ReverseFind(PCMYSTR szFind, MYSIZE pos=MYBASE::npos) const\r
+ {\r
+ MYSIZE nIdx = this->rfind(0 == szFind ? MYTYPE() : szFind, pos);\r
+ return static_cast<int>(MYBASE::npos == nIdx ? -1 : nIdx);\r
+ }\r
+\r
+ MYTYPE Right(int nCount) const\r
+ {\r
+ // Range check the count.\r
+\r
+ nCount = SSMAX(0, SSMIN(nCount, static_cast<int>(this->size())));\r
+ return this->substr(this->size()-static_cast<MYSIZE>(nCount));\r
+ }\r
+\r
+ void SetAt(int nIndex, CT ch)\r
+ {\r
+ ASSERT(this->size() > static_cast<MYSIZE>(nIndex));\r
+ this->at(static_cast<MYSIZE>(nIndex)) = ch;\r
+ }\r
+\r
+#ifndef SS_ANSI\r
+ BSTR SetSysString(BSTR* pbstr) const\r
+ {\r
+ ostring os;\r
+ ssasn(os, *this);\r
+ if ( !::SysReAllocStringLen(pbstr, os.c_str(), os.length()) )\r
+ throw std::runtime_error("out of memory");\r
+\r
+ ASSERT(*pbstr != 0);\r
+ return *pbstr;\r
+ }\r
+#endif\r
+\r
+ MYTYPE SpanExcluding(PCMYSTR szCharSet) const\r
+ {\r
+ MYSIZE pos = this->find_first_of(szCharSet);\r
+ return pos == MYBASE::npos ? *this : Left(pos);\r
+ }\r
+\r
+ MYTYPE SpanIncluding(PCMYSTR szCharSet) const\r
+ {\r
+ MYSIZE pos = this->find_first_not_of(szCharSet);\r
+ return pos == MYBASE::npos ? *this : Left(pos);\r
+ }\r
+\r
+#if !defined(UNICODE) && !defined(SS_ANSI)\r
+\r
+ // CString's OemToAnsi and AnsiToOem functions are available only in\r
+ // Unicode builds. However since we're a template we also need a\r
+ // runtime check of CT and a reinterpret_cast to account for the fact\r
+ // that CStdStringW gets instantiated even in non-Unicode builds.\r
+\r
+ void AnsiToOem()\r
+ {\r
+ if ( sizeof(CT) == sizeof(char) && !empty() )\r
+ {\r
+ ::CharToOem(reinterpret_cast<PCSTR>(this->c_str()),\r
+ reinterpret_cast<PSTR>(GetBuf()));\r
+ }\r
+ else\r
+ {\r
+ ASSERT(false);\r
+ }\r
+ }\r
+\r
+ void OemToAnsi()\r
+ {\r
+ if ( sizeof(CT) == sizeof(char) && !empty() )\r
+ {\r
+ ::OemToChar(reinterpret_cast<PCSTR>(this->c_str()),\r
+ reinterpret_cast<PSTR>(GetBuf()));\r
+ }\r
+ else\r
+ {\r
+ ASSERT(false);\r
+ }\r
+ }\r
+\r
+#endif\r
+ \r
+\r
+ // -------------------------------------------------------------------------\r
+ // Trim and its variants\r
+ // -------------------------------------------------------------------------\r
+ MYTYPE& Trim()\r
+ {\r
+ return TrimLeft().TrimRight();\r
+ }\r
+\r
+ MYTYPE& TrimLeft()\r
+ {\r
+ this->erase(this->begin(),\r
+ std::find_if(this->begin(), this->end(), NotSpace<CT>()));\r
+\r
+ return *this;\r
+ }\r
+\r
+ MYTYPE& TrimLeft(CT tTrim)\r
+ {\r
+ this->erase(0, this->find_first_not_of(tTrim));\r
+ return *this;\r
+ }\r
+\r
+ MYTYPE& TrimLeft(PCMYSTR szTrimChars)\r
+ {\r
+ this->erase(0, this->find_first_not_of(szTrimChars));\r
+ return *this;\r
+ }\r
+\r
+ MYTYPE& TrimRight()\r
+ {\r
+ // NOTE: When comparing reverse_iterators here (MYRITER), I avoid using\r
+ // operator!=. This is because namespace rel_ops also has a template\r
+ // operator!= which conflicts with the global operator!= already defined\r
+ // for reverse_iterator in the header <utility>.\r
+ // Thanks to John James for alerting me to this.\r
+\r
+ MYRITER it = std::find_if(this->rbegin(), this->rend(), NotSpace<CT>());\r
+ if ( !(this->rend() == it) )\r
+ this->erase(this->rend() - it);\r
+\r
+ this->erase(!(it == this->rend()) ? this->find_last_of(*it) + 1 : 0);\r
+ return *this;\r
+ }\r
+\r
+ MYTYPE& TrimRight(CT tTrim)\r
+ {\r
+ MYSIZE nIdx = this->find_last_not_of(tTrim);\r
+ this->erase(MYBASE::npos == nIdx ? 0 : ++nIdx);\r
+ return *this;\r
+ }\r
+\r
+ MYTYPE& TrimRight(PCMYSTR szTrimChars)\r
+ {\r
+ MYSIZE nIdx = this->find_last_not_of(szTrimChars);\r
+ this->erase(MYBASE::npos == nIdx ? 0 : ++nIdx);\r
+ return *this;\r
+ }\r
+\r
+ void FreeExtra()\r
+ {\r
+ MYTYPE mt;\r
+ this->swap(mt);\r
+ if ( !mt.empty() )\r
+ this->assign(mt.c_str(), mt.size());\r
+ }\r
+\r
+ // I have intentionally not implemented the following CString\r
+ // functions. You cannot make them work without taking advantage\r
+ // of implementation specific behavior. However if you absolutely\r
+ // MUST have them, uncomment out these lines for "sort-of-like"\r
+ // their behavior. You're on your own.\r
+\r
+// CT* LockBuffer() { return GetBuf(); }// won't really lock\r
+// void UnlockBuffer(); { } // why have UnlockBuffer w/o LockBuffer?\r
+\r
+ // Array-indexing operators. Required because we defined an implicit cast\r
+ // to operator const CT* (Thanks to Julian Selman for pointing this out)\r
+ CT& operator[](int nIdx)\r
+ {\r
+ return MYBASE::operator[](static_cast<MYSIZE>(nIdx));\r
+ }\r
+\r
+ const CT& operator[](int nIdx) const\r
+ {\r
+ return MYBASE::operator[](static_cast<MYSIZE>(nIdx));\r
+ }\r
+\r
+ CT& operator[](unsigned int nIdx)\r
+ {\r
+ return MYBASE::operator[](static_cast<MYSIZE>(nIdx));\r
+ }\r
+\r
+ const CT& operator[](unsigned int nIdx) const\r
+ {\r
+ return MYBASE::operator[](static_cast<MYSIZE>(nIdx));\r
+ }\r
+\r
+#ifndef SS_NO_IMPLICIT_CAST\r
+ operator const CT*() const\r
+ {\r
+ return this->c_str();\r
+ }\r
+#endif\r
+\r
+ // IStream related functions. Useful in IPersistStream implementations\r
+\r
+#ifdef SS_INC_COMDEF\r
+\r
+ // struct SSSHDR - useful for non Std C++ persistence schemes.\r
+ typedef struct SSSHDR\r
+ {\r
+ BYTE byCtrl;\r
+ ULONG nChars;\r
+ } SSSHDR; // as in "Standard String Stream Header"\r
+\r
+ #define SSSO_UNICODE 0x01 // the string is a wide string\r
+ #define SSSO_COMPRESS 0x02 // the string is compressed\r
+\r
+ // -------------------------------------------------------------------------\r
+ // FUNCTION: StreamSize\r
+ // REMARKS:\r
+ // Returns how many bytes it will take to StreamSave() this CStdString\r
+ // object to an IStream.\r
+ // -------------------------------------------------------------------------\r
+ ULONG StreamSize() const\r
+ {\r
+ // Control header plus string\r
+ ASSERT(this->size()*sizeof(CT) < 0xffffffffUL - sizeof(SSSHDR));\r
+ return (this->size() * sizeof(CT)) + sizeof(SSSHDR);\r
+ }\r
+\r
+ // -------------------------------------------------------------------------\r
+ // FUNCTION: StreamSave\r
+ // REMARKS:\r
+ // Saves this CStdString object to a COM IStream.\r
+ // -------------------------------------------------------------------------\r
+ HRESULT StreamSave(IStream* pStream) const\r
+ {\r
+ ASSERT(size()*sizeof(CT) < 0xffffffffUL - sizeof(SSSHDR));\r
+ HRESULT hr = E_FAIL;\r
+ ASSERT(pStream != 0);\r
+ SSSHDR hdr;\r
+ hdr.byCtrl = sizeof(CT) == 2 ? SSSO_UNICODE : 0;\r
+ hdr.nChars = this->size();\r
+\r
+\r
+ if ( FAILED(hr=pStream->Write(&hdr, sizeof(SSSHDR), 0)) )\r
+ TRACE(_T("StreamSave: Cannot write control header, ERR=0x%X\n"),hr);\r
+ else if ( empty() )\r
+ ; // nothing to write\r
+ else if ( FAILED(hr=pStream->Write(this->c_str(), this->size()*sizeof(CT), 0)) )\r
+ TRACE(_T("StreamSave: Cannot write string to stream 0x%X\n"), hr);\r
+\r
+ return hr;\r
+ }\r
+\r
+\r
+ // -------------------------------------------------------------------------\r
+ // FUNCTION: StreamLoad\r
+ // REMARKS:\r
+ // This method loads the object from an IStream.\r
+ // -------------------------------------------------------------------------\r
+ HRESULT StreamLoad(IStream* pStream)\r
+ {\r
+ ASSERT(pStream != 0);\r
+ SSSHDR hdr;\r
+ HRESULT hr = E_FAIL;\r
+\r
+ if ( FAILED(hr=pStream->Read(&hdr, sizeof(SSSHDR), 0)) )\r
+ {\r
+ TRACE(_T("StreamLoad: Cant read control header, ERR=0x%X\n"), hr);\r
+ }\r
+ else if ( hdr.nChars > 0 )\r
+ {\r
+ ULONG nRead = 0;\r
+ PMYSTR pMyBuf = BufferSet(hdr.nChars);\r
+\r
+ // If our character size matches the character size of the string\r
+ // we're trying to read, then we can read it directly into our\r
+ // buffer. Otherwise, we have to read into an intermediate buffer\r
+ // and convert.\r
+ \r
+ if ( (hdr.byCtrl & SSSO_UNICODE) != 0 )\r
+ {\r
+ ULONG nBytes = hdr.nChars * sizeof(wchar_t);\r
+ if ( sizeof(CT) == sizeof(wchar_t) )\r
+ {\r
+ if ( FAILED(hr=pStream->Read(pMyBuf, nBytes, &nRead)) )\r
+ TRACE(_T("StreamLoad: Cannot read string: 0x%X\n"), hr);\r
+ }\r
+ else\r
+ { \r
+ PWSTR pBufW = reinterpret_cast<PWSTR>(_alloca((nBytes)+1));\r
+ if ( FAILED(hr=pStream->Read(pBufW, nBytes, &nRead)) )\r
+ TRACE(_T("StreamLoad: Cannot read string: 0x%X\n"), hr);\r
+ else\r
+ sscpy(pMyBuf, pBufW, hdr.nChars);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ ULONG nBytes = hdr.nChars * sizeof(char);\r
+ if ( sizeof(CT) == sizeof(char) )\r
+ {\r
+ if ( FAILED(hr=pStream->Read(pMyBuf, nBytes, &nRead)) )\r
+ TRACE(_T("StreamLoad: Cannot read string: 0x%X\n"), hr);\r
+ }\r
+ else\r
+ {\r
+ PSTR pBufA = reinterpret_cast<PSTR>(_alloca(nBytes));\r
+ if ( FAILED(hr=pStream->Read(pBufA, hdr.nChars, &nRead)) )\r
+ TRACE(_T("StreamLoad: Cannot read string: 0x%X\n"), hr);\r
+ else\r
+ sscpy(pMyBuf, pBufA, hdr.nChars);\r
+ }\r
+ }\r
+ }\r
+ else\r
+ {\r
+ this->erase();\r
+ }\r
+ return hr;\r
+ }\r
+#endif // #ifdef SS_INC_COMDEF\r
+\r
+#ifndef SS_ANSI\r
+\r
+ // SetResourceHandle/GetResourceHandle. In MFC builds, these map directly\r
+ // to AfxSetResourceHandle and AfxGetResourceHandle. In non-MFC builds they\r
+ // point to a single static HINST so that those who call the member\r
+ // functions that take resource IDs can provide an alternate HINST of a DLL\r
+ // to search. This is not exactly the list of HMODULES that MFC provides\r
+ // but it's better than nothing.\r
+\r
+#ifdef _MFC_VER\r
+ static void SetResourceHandle(HMODULE hNew)\r
+ {\r
+ AfxSetResourceHandle(hNew);\r
+ }\r
+ static HMODULE GetResourceHandle()\r
+ {\r
+ return AfxGetResourceHandle();\r
+ }\r
+#else\r
+ static void SetResourceHandle(HMODULE hNew)\r
+ {\r
+ SSResourceHandle() = hNew;\r
+ }\r
+ static HMODULE GetResourceHandle()\r
+ {\r
+ return SSResourceHandle();\r
+ }\r
+#endif\r
+\r
+\r
+ template<typename CT2>\r
+ MYTYPE operator+(const CStdStr<CT2>& s2)\r
+ {\r
+ MYTYPE strRet(SSREF(*this));\r
+ strRet += s2.c_str();\r
+ return strRet;\r
+ }\r
+\r
+\r
+#endif\r
+};\r
+\r
+\r
+\r
+// -----------------------------------------------------------------------------\r
+// CStdStr friend addition functions defined as inline\r
+// -----------------------------------------------------------------------------\r
+template<typename CT>\r
+inline\r
+CStdStr<CT> operator+(const CStdStr<CT>& str1, const CStdStr<CT>& str2)\r
+{\r
+ CStdStr<CT> strRet(SSREF(str1));\r
+ strRet.append(str2);\r
+ return strRet;\r
+}\r
+\r
+template<typename CT> \r
+inline\r
+CStdStr<CT> operator+(const CStdStr<CT>& str, CT t)\r
+{\r
+ // this particular overload is needed for disabling reference counting\r
+ // though it's only an issue from line 1 to line 2\r
+\r
+ CStdStr<CT> strRet(SSREF(str)); // 1\r
+ strRet.append(1, t); // 2\r
+ return strRet;\r
+}\r
+\r
+template<typename CT>\r
+inline\r
+CStdStr<CT> operator+(const CStdStr<CT>& str, PCSTR pA)\r
+{\r
+ return CStdStr<CT>(str) + CStdStr<CT>(pA);\r
+}\r
+\r
+template<typename CT>\r
+inline\r
+CStdStr<CT> operator+(PCSTR pA, const CStdStr<CT>& str)\r
+{\r
+ CStdStr<CT> strRet(pA);\r
+ strRet.append(str);\r
+ return strRet;\r
+}\r
+\r
+template<typename CT>\r
+inline\r
+CStdStr<CT> operator+(const CStdStr<CT>& str, PCWSTR pW)\r
+{ \r
+ return CStdStr<CT>(SSREF(str)) + CStdStr<CT>(pW);\r
+}\r
+\r
+template<typename CT>\r
+inline\r
+CStdStr<CT> operator+(PCWSTR pW, const CStdStr<CT>& str)\r
+{\r
+ CStdStr<CT> strRet(pW);\r
+ strRet.append(str);\r
+ return strRet;\r
+}\r
+\r
+#ifdef SS_INC_COMDEF\r
+ template<typename CT>\r
+ inline\r
+ CStdStr<CT> operator+(const _bstr_t& bstr, const CStdStr<CT>& str)\r
+ {\r
+ return static_cast<const CT*>(bstr) + str;\r
+ }\r
+\r
+ template<typename CT>\r
+ inline\r
+ CStdStr<CT> operator+(const CStdStr<CT>& str, const _bstr_t& bstr)\r
+ {\r
+ return str + static_cast<const CT*>(bstr);\r
+ }\r
+#endif\r
+\r
+// -----------------------------------------------------------------------------\r
+// HOW TO EXPORT CSTDSTRING FROM A DLL\r
+//\r
+// If you want to export CStdStringA and CStdStringW from a DLL, then all you\r
+// need to\r
+// 1. make sure that all components link to the same DLL version\r
+// of the CRT (not the static one).\r
+// 2. Uncomment the 3 lines of code below\r
+// 3. #define 2 macros per the instructions in MS KnowledgeBase\r
+// article Q168958. The macros are:\r
+//\r
+// MACRO DEFINTION WHEN EXPORTING DEFINITION WHEN IMPORTING\r
+// ----- ------------------------ -------------------------\r
+// SSDLLEXP (nothing, just #define it) extern\r
+// SSDLLSPEC __declspec(dllexport) __declspec(dllimport)\r
+//\r
+// Note that these macros must be available to ALL clients who want to \r
+// link to the DLL and use the class. If they \r
+// -----------------------------------------------------------------------------\r
+//#pragma warning(disable:4231) // non-standard extension ("extern template")\r
+// SSDLLEXP template class SSDLLSPEC CStdStr<char>;\r
+// SSDLLEXP template class SSDLLSPEC CStdStr<wchar_t>;\r
+\r
+// =============================================================================\r
+// END OF CStdStr INLINE FUNCTION DEFINITIONS\r
+// =============================================================================\r
+\r
+// Now typedef our class names based upon this humongous template\r
+\r
+typedef CStdStr<char> CStdStringA; // a better std::string\r
+typedef CStdStr<wchar_t> CStdStringW; // a better std::wstring\r
+typedef CStdStr<OLECHAR> CStdStringO; // almost always CStdStringW\r
+\r
+\r
+// New-style format function is a template\r
+\r
+#ifdef SS_SAFE_FORMAT\r
+\r
+template<>\r
+struct FmtArg<CStdStringA>\r
+{\r
+ explicit FmtArg(const CStdStringA& arg) : a_(arg) {}\r
+ PCSTR Val() const { return a_.c_str(); }\r
+ const CStdStringA& a_;\r
+private:\r
+ FmtArg<CStdStringA>& operator=(const FmtArg<CStdStringA>&) { return *this; }\r
+};\r
+template<>\r
+struct FmtArg<CStdStringW>\r
+{\r
+ explicit FmtArg(const CStdStringW& arg) : a_(arg) {}\r
+ PCWSTR Val() const { return a_.c_str(); }\r
+ const CStdStringW& a_;\r
+private:\r
+ FmtArg<CStdStringW>& operator=(const FmtArg<CStdStringW>&) { return *this; }\r
+};\r
+\r
+template<>\r
+struct FmtArg<std::string>\r
+{\r
+ explicit FmtArg(const std::string& arg) : a_(arg) {}\r
+ PCSTR Val() const { return a_.c_str(); }\r
+ const std::string& a_;\r
+private:\r
+ FmtArg<std::string>& operator=(const FmtArg<std::string>&) { return *this; }\r
+};\r
+template<>\r
+struct FmtArg<std::wstring>\r
+{\r
+ explicit FmtArg(const std::wstring& arg) : a_(arg) {}\r
+ PCWSTR Val() const { return a_.c_str(); }\r
+ const std::wstring& a_;\r
+private:\r
+ FmtArg<std::wstring>& operator=(const FmtArg<std::wstring>&) {return *this;}\r
+};\r
+#endif // #ifdef SS_SAFEFORMAT\r
+\r
+#ifndef SS_ANSI\r
+ // SSResourceHandle: our MFC-like resource handle\r
+ inline HMODULE& SSResourceHandle()\r
+ {\r
+ static HMODULE hModuleSS = GetModuleHandle(0);\r
+ return hModuleSS;\r
+ }\r
+#endif\r
+\r
+\r
+\r
+\r
+// In MFC builds, define some global serialization operators\r
+// Special operators that allow us to serialize CStdStrings to CArchives.\r
+// Note that we use an intermediate CString object in order to ensure that\r
+// we use the exact same format.\r
+\r
+#ifdef _MFC_VER\r
+ inline CArchive& AFXAPI operator<<(CArchive& ar, const CStdStringA& strA)\r
+ {\r
+ CString strTemp = strA;\r
+ return ar << strTemp;\r
+ }\r
+ inline CArchive& AFXAPI operator<<(CArchive& ar, const CStdStringW& strW)\r
+ {\r
+ CString strTemp = strW;\r
+ return ar << strTemp;\r
+ }\r
+\r
+ inline CArchive& AFXAPI operator>>(CArchive& ar, CStdStringA& strA)\r
+ {\r
+ CString strTemp;\r
+ ar >> strTemp;\r
+ strA = strTemp;\r
+ return ar;\r
+ }\r
+ inline CArchive& AFXAPI operator>>(CArchive& ar, CStdStringW& strW)\r
+ {\r
+ CString strTemp;\r
+ ar >> strTemp;\r
+ strW = strTemp;\r
+ return ar;\r
+ }\r
+#endif // #ifdef _MFC_VER -- (i.e. is this MFC?)\r
+\r
+\r
+\r
+// -----------------------------------------------------------------------------\r
+// GLOBAL FUNCTION: WUFormat\r
+// CStdStringA WUFormat(UINT nId, ...);\r
+// CStdStringA WUFormat(PCSTR szFormat, ...);\r
+//\r
+// REMARKS:\r
+// This function allows the caller for format and return a CStdStringA\r
+// object with a single line of code.\r
+// -----------------------------------------------------------------------------\r
+#ifdef SS_ANSI\r
+#else\r
+\r
+ inline CStdStringA WUFormatA(UINT nId, ...)\r
+ {\r
+ va_list argList;\r
+ va_start(argList, nId);\r
+\r
+ CStdStringA strFmt;\r
+ CStdStringA strOut;\r
+ if ( strFmt.Load(nId) )\r
+ strOut.FormatV(strFmt, argList);\r
+\r
+ va_end(argList);\r
+ return strOut;\r
+ }\r
+ inline CStdStringA WUFormatA(PCSTR szFormat, ...)\r
+ {\r
+ va_list argList;\r
+ va_start(argList, szFormat);\r
+ CStdStringA strOut;\r
+ strOut.FormatV(szFormat, argList);\r
+ va_end(argList);\r
+ return strOut;\r
+ }\r
+\r
+ inline CStdStringW WUFormatW(UINT nId, ...)\r
+ {\r
+ va_list argList;\r
+ va_start(argList, nId);\r
+\r
+ CStdStringW strFmt;\r
+ CStdStringW strOut;\r
+ if ( strFmt.Load(nId) )\r
+ strOut.FormatV(strFmt, argList);\r
+\r
+ va_end(argList);\r
+ return strOut;\r
+ }\r
+ inline CStdStringW WUFormatW(PCWSTR szwFormat, ...)\r
+ {\r
+ va_list argList;\r
+ va_start(argList, szwFormat);\r
+ CStdStringW strOut;\r
+ strOut.FormatV(szwFormat, argList);\r
+ va_end(argList);\r
+ return strOut;\r
+ }\r
+#endif // #ifdef SS_ANSI\r
+\r
+#ifdef SS_WIN32\r
+ // -------------------------------------------------------------------------\r
+ // FUNCTION: WUSysMessage\r
+ // CStdStringA WUSysMessageA(DWORD dwError, DWORD dwLangId=SS_DEFLANGID);\r
+ // CStdStringW WUSysMessageW(DWORD dwError, DWORD dwLangId=SS_DEFLANGID);\r
+ // \r
+ // DESCRIPTION:\r
+ // This function simplifies the process of obtaining a string equivalent\r
+ // of a system error code returned from GetLastError(). You simply\r
+ // supply the value returned by GetLastError() to this function and the\r
+ // corresponding system string is returned in the form of a CStdStringA.\r
+ //\r
+ // PARAMETERS: \r
+ // dwError - a DWORD value representing the error code to be translated\r
+ // dwLangId - the language id to use. defaults to english.\r
+ //\r
+ // RETURN VALUE: \r
+ // a CStdStringA equivalent of the error code. Currently, this function\r
+ // only returns either English of the system default language strings. \r
+ // -------------------------------------------------------------------------\r
+ #define SS_DEFLANGID MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT)\r
+ inline CStdStringA WUSysMessageA(DWORD dwError, DWORD dwLangId=SS_DEFLANGID)\r
+ {\r
+ CHAR szBuf[512];\r
+\r
+ if ( 0 != ::FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError,\r
+ dwLangId, szBuf, 511, NULL) )\r
+ return WUFormatA("%s (0x%X)", szBuf, dwError);\r
+ else\r
+ return WUFormatA("Unknown error (0x%X)", dwError);\r
+ }\r
+ inline CStdStringW WUSysMessageW(DWORD dwError, DWORD dwLangId=SS_DEFLANGID)\r
+ {\r
+ WCHAR szBuf[512];\r
+\r
+ if ( 0 != ::FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError,\r
+ dwLangId, szBuf, 511, NULL) )\r
+ return WUFormatW(L"%s (0x%X)", szBuf, dwError);\r
+ else\r
+ return WUFormatW(L"Unknown error (0x%X)", dwError);\r
+ }\r
+#endif\r
+\r
+// Define TCHAR based friendly names for some of these functions\r
+\r
+#ifdef UNICODE\r
+ #define CStdString CStdStringW\r
+ #define WUSysMessage WUSysMessageW\r
+ #define WUFormat WUFormatW\r
+#else\r
+ #define CStdString CStdStringA\r
+ #define WUSysMessage WUSysMessageA\r
+ #define WUFormat WUFormatA\r
+#endif\r
+\r
+// ...and some shorter names for the space-efficient\r
+\r
+#define WUSysMsg WUSysMessage\r
+#define WUSysMsgA WUSysMessageA\r
+#define WUSysMsgW WUSysMessageW\r
+#define WUFmtA WUFormatA\r
+#define WUFmtW WUFormatW\r
+#define WUFmt WUFormat\r
+#define WULastErrMsg() WUSysMessage(::GetLastError())\r
+#define WULastErrMsgA() WUSysMessageA(::GetLastError())\r
+#define WULastErrMsgW() WUSysMessageW(::GetLastError())\r
+\r
+\r
+// -----------------------------------------------------------------------------\r
+// FUNCTIONAL COMPARATORS:\r
+// REMARKS:\r
+// These structs are derived from the std::binary_function template. They\r
+// give us functional classes (which may be used in Standard C++ Library\r
+// collections and algorithms) that perform case-insensitive comparisons of\r
+// CStdString objects. This is useful for maps in which the key may be the\r
+// proper string but in the wrong case.\r
+// -----------------------------------------------------------------------------\r
+#define StdStringLessNoCaseW SSLNCW // avoid VC compiler warning 4786\r
+#define StdStringEqualsNoCaseW SSENCW \r
+#define StdStringLessNoCaseA SSLNCA \r
+#define StdStringEqualsNoCaseA SSENCA \r
+\r
+#ifdef UNICODE\r
+ #define StdStringLessNoCase SSLNCW \r
+ #define StdStringEqualsNoCase SSENCW \r
+#else\r
+ #define StdStringLessNoCase SSLNCA \r
+ #define StdStringEqualsNoCase SSENCA \r
+#endif\r
+\r
+struct StdStringLessNoCaseW\r
+ : std::binary_function<CStdStringW, CStdStringW, bool>\r
+{\r
+ inline\r
+ bool operator()(const CStdStringW& sLeft, const CStdStringW& sRight) const\r
+ { return ssicmp(sLeft.c_str(), sRight.c_str()) < 0; }\r
+};\r
+struct StdStringEqualsNoCaseW\r
+ : std::binary_function<CStdStringW, CStdStringW, bool>\r
+{\r
+ inline\r
+ bool operator()(const CStdStringW& sLeft, const CStdStringW& sRight) const\r
+ { return ssicmp(sLeft.c_str(), sRight.c_str()) == 0; }\r
+};\r
+struct StdStringLessNoCaseA\r
+ : std::binary_function<CStdStringA, CStdStringA, bool>\r
+{\r
+ inline\r
+ bool operator()(const CStdStringA& sLeft, const CStdStringA& sRight) const\r
+ { return ssicmp(sLeft.c_str(), sRight.c_str()) < 0; }\r
+};\r
+struct StdStringEqualsNoCaseA\r
+ : std::binary_function<CStdStringA, CStdStringA, bool>\r
+{\r
+ inline\r
+ bool operator()(const CStdStringA& sLeft, const CStdStringA& sRight) const\r
+ { return ssicmp(sLeft.c_str(), sRight.c_str()) == 0; }\r
+};\r
+\r
+// If we had to define our own version of TRACE above, get rid of it now\r
+\r
+#ifdef TRACE_DEFINED_HERE\r
+ #undef TRACE\r
+ #undef TRACE_DEFINED_HERE\r
+#endif\r
+\r
+\r
+// These std::swap specializations come courtesy of Mike Crusader. \r
+\r
+//namespace std\r
+//{\r
+// inline void swap(CStdStringA& s1, CStdStringA& s2) throw()\r
+// {\r
+// s1.swap(s2);\r
+// }\r
+// template<>\r
+// inline void swap(CStdStringW& s1, CStdStringW& s2) throw()\r
+// {\r
+// s1.swap(s2);\r
+// }\r
+//}\r
+\r
+// Turn back on any Borland warnings we turned off.\r
+\r
+#ifdef __BORLANDC__\r
+ #pragma option pop // Turn back on inline function warnings\r
+// #pragma warn +inl // Turn back on inline function warnings\r
+#endif\r
+\r
+#endif // #ifndef STDSTRING_H
\ No newline at end of file
--- /dev/null
+/*
+ *****************************************************************************
+ *
+ * File: stg_common.h
+ *
+ * Description: çÌÏÂÁÌØÎÏÅ ÄÌÑ ×ÓÅÇÏ ÐÒÏÅËÔÁ STG
+ *
+ * $Id: stg_common.h,v 1.1.1.1 2005/10/09 11:00:45 nobunaga Exp $
+ *
+ *****************************************************************************
+ */
+
+#ifndef _STG_COMMON_H_
+#define _STG_COMMON_H_
+
+
+#define LOGIN_LEN (32)
+#define PASSWD_LEN (32)
+
+#endif /* _STG_COMMON_H_ */
+
+/* EOF */
+
--- /dev/null
+#ifndef STG_COMP_STAT_H
+#define STG_COMP_STAT_H
+
+#ifdef LINUX
+#include <stdint.h>
+#endif
+
+#ifdef FREE_BSD5
+#include <inttypes.h>
+#endif
+
+#ifdef FREE_BSD
+#include <sys/inttypes.h>
+#endif
+
+#include "stg_const.h"
+//-----------------------------------------------------------------------------
+struct DAY_STAT
+{
+ DAY_STAT()
+ {
+ lastUpdate = 0;
+ memset(upload, 0, sizeof(uint64_t) * DIR_NUM);
+ memset(download, 0, sizeof(uint64_t) * DIR_NUM);
+ memset(cash, 0, sizeof(double) * DIR_NUM);
+ }
+
+ time_t lastUpdate;
+ uint64_t upload[DIR_NUM];
+ uint64_t download[DIR_NUM];
+ double cash[DIR_NUM];
+};
+//-----------------------------------------------------------------------------
+struct MONTH_STAT
+{
+ DAY_STAT dayStat[31];
+ char notUsed;
+};
+//-----------------------------------------------------------------------------
+
+#endif //STG_COMP_STAT_H
--- /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@ua.fm>
+ */
+
+ /*
+ $Author: nobunaga $
+ $Revision: 1.10 $
+ $Date: 2008/01/11 17:33:50 $
+ */
+
+
+#ifndef STG_CONST_H
+#define STG_CONST_H
+
+#define DIR_NUM (10)
+#define SYS_IFACE_LEN (9)
+#define IFACE_LEN (255)
+#define MAX_IP (5)
+#define USERDATA_NUM (10)
+
+#define LOGIN_LEN (32)
+#define PASSWD_LEN (32)
+#define ADDR_LEN (255)
+#define NOTE_LEN (255)
+#define REALNM_LEN (255)
+#define GROUP_LEN (255)
+#define PHONE_LEN (255)
+#define EMAIL_LEN (255)
+#define USR_IFACE_LEN (255)
+#define USER_DATA_LEN (255)
+#define IP_STRING_LEN (255)
+
+#define ADM_LOGIN_LEN (32)
+#define ADM_PASSWD_LEN (32)
+#define TARIFF_NAME_LEN (32)
+#define SERVER_NAME_LEN (255)
+
+#define DIR_NAME_LEN (16)
+
+#define MAX_MSG_LEN (235)
+#define MAX_MSG_LEN_8 (1030)
+
+#define LOGCASH (1)
+#define NOLOGCASH (0)
+
+#define USERNOCASH (0)
+#define USERDISCONNECT (1)
+
+#define LOGEVENT_CONNECT (0)
+#define LOGEVENT_DISCONNECT (1)
+#define LOGEVENT_NEW_MONTH (2)
+#define LOGEVENT_NO_CASH (3)
+#define LOGEVENT_CONNECT_NO_CASH (4)
+#define LOGEVENT_USER_DOWN (5)
+#define LOGEVENT_DELETED (6)
+
+#define SET_TARIFF_NOW (0)
+#define SET_TARIFF_DELAYED (1)
+#define SET_TARIFF_RECALC (2)
+
+#define CASH_SET (0)
+#define CASH_ADD (1)
+
+#define NO_TARIFF_NAME "*_NO_TARIFF_*"
+#define NO_CORP_NAME "*_NO_CORP_*"
+
+#define mega (1024 * 1024)
+
+#define MONITOR_TIME_DELAY_SEC (60)
+
+#endif
--- /dev/null
+#ifdef LINUX
+#include <stdint.h>
+#endif
+
+#ifdef FREE_BSD5
+#include <inttypes.h>
+#endif
+
+#ifdef FREE_BSD
+#include <sys/inttypes.h>
+#endif
--- /dev/null
+#ifndef STG_MESSAGES_H
+#define STG_MESSAGES_H
+
+/*
+ * Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+ /*
+ $Revision: 1.3 $
+ $Date: 2010/03/04 11:49:52 $
+ */
+
+#include <time.h>
+#include <string>
+
+using namespace std;
+//-----------------------------------------------------------------------------
+struct STG_MSG_HDR
+{
+STG_MSG_HDR()
+ : id(0),
+ ver(0),
+ type(0),
+ lastSendTime(0),
+ creationTime(0),
+ showTime(0),
+ repeat(0),
+ repeatPeriod(0)
+{};
+
+uint64_t id;
+unsigned ver;
+unsigned type;
+unsigned lastSendTime;
+unsigned creationTime;
+unsigned showTime;
+int repeat;
+unsigned repeatPeriod;
+};
+//-----------------------------------------------------------------------------
+struct STG_MSG
+{
+STG_MSG()
+ : header(),
+ text()
+{};
+
+STG_MSG_HDR header;
+string text;
+};
+//-----------------------------------------------------------------------------
+
+#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>
+ */
+
+ /*
+ $Revision: 1.9 $
+ $Date: 2010/10/05 20:41:11 $
+ $Author: faust $
+ */
+
+#ifndef TARIFF_CONF_H
+#define TARIFF_CONF_H
+
+#include <string>
+#include <vector>
+
+#include "resetable.h"
+#include "stg_const.h"
+
+//-----------------------------------------------------------------------------
+enum
+{
+ TRAFF_UP = 0,
+ TRAFF_DOWN,
+ TRAFF_UP_DOWN,
+ TRAFF_MAX
+};
+//-----------------------------------------------------------------------------
+struct DIRPRICE_DATA
+{
+ DIRPRICE_DATA()
+ : hDay(0),
+ mDay(0),
+ hNight(0),
+ mNight(0),
+ priceDayA(0),
+ priceNightA(0),
+ priceDayB(0),
+ priceNightB(0),
+ threshold(0),
+ singlePrice(0),
+ noDiscount(0)
+ {}
+ int hDay;
+ int mDay;
+ int hNight;
+ int mNight;
+ double priceDayA;
+ double priceNightA;
+ double priceDayB;
+ double priceNightB;
+ int threshold;
+ int singlePrice; // Do not use day/night division
+ int noDiscount; // Do not use threshold
+};
+//-----------------------------------------------------------------------------
+struct DIRPRICE_DATA_RES
+{
+ DIRPRICE_DATA_RES & operator= (const DIRPRICE_DATA & dpd)
+ {
+ hDay = dpd.hDay;
+ mDay = dpd.mDay;
+ hNight = dpd.hNight;
+ mNight = dpd.mNight;
+ priceDayA = dpd.priceDayA;
+ priceNightA = dpd.priceNightA;
+ priceDayB = dpd.priceDayB;
+ priceNightB = dpd.priceNightB;
+ threshold = dpd.threshold;
+ singlePrice = dpd.singlePrice;
+ noDiscount = dpd.noDiscount;
+ return *this;
+ };
+
+ DIRPRICE_DATA GetData()
+ {
+ DIRPRICE_DATA dd;
+ dd.hDay = hDay;
+ dd.hNight = hNight;
+ dd.mDay = mDay;
+ dd.mNight = mNight;
+ dd.noDiscount = noDiscount;
+ dd.priceDayA = priceDayA;
+ dd.priceDayB = priceDayB;
+
+ dd.priceNightA = priceNightA;
+ dd.priceNightB = priceNightB;
+ dd.singlePrice = singlePrice;
+ dd.threshold = threshold;
+ return dd;
+ }
+
+ RESETABLE<int> hDay;
+ RESETABLE<int> mDay;
+ RESETABLE<int> hNight;
+ RESETABLE<int> mNight;
+ RESETABLE<double> priceDayA;
+ RESETABLE<double> priceNightA;
+ RESETABLE<double> priceDayB;
+ RESETABLE<double> priceNightB;
+ RESETABLE<int> threshold;
+ RESETABLE<int> singlePrice;
+ RESETABLE<int> noDiscount;
+};
+//-----------------------------------------------------------------------------
+struct TARIFF_CONF
+{
+ double fee; // ÷ÅÌÉÞÉÎÁ ÁÂÏÎÐÌÁÔÙ
+ double free; // îÁ ËÁËÕÀ ÓÕÍÍÕ ÄÅÎÅÇ ÀÚÅÒ ËÁÞÁÅÔ ÂÅÓÐÌÁÔÎÏ
+ int traffType; // UP, DOWN, UP+DOWN, MAX
+ double passiveCost; // óÔÏÉÍÏÓÔØ ÚÁÍÏÒÏÚËÉ
+ std::string name;
+
+ TARIFF_CONF()
+ : fee(0),
+ free(0),
+ traffType(TRAFF_UP_DOWN), // UP-DOWN
+ passiveCost(0),
+ name()
+ {};
+
+ TARIFF_CONF(const std::string & n)
+ : fee(0),
+ free(0),
+ traffType(TRAFF_UP_DOWN), // UP-DOWN
+ passiveCost(0),
+ name(n)
+ {};
+};
+//-----------------------------------------------------------------------------
+struct TARIFF_CONF_RES
+{
+ TARIFF_CONF_RES & operator=(const TARIFF_CONF & tc)
+ {
+ fee = tc.fee;
+ free = tc.free;
+ traffType = tc.traffType;
+ passiveCost = tc.passiveCost;
+ name = tc.name;
+ return *this;
+ };
+
+ TARIFF_CONF GetData()
+ {
+ TARIFF_CONF tc;
+ tc.fee = fee;
+ tc.free = free;
+ tc.name = name;
+ tc.passiveCost = passiveCost;
+ tc.traffType = traffType;
+ return tc;
+ }
+
+ RESETABLE<double> fee;
+ RESETABLE<double> free;
+ RESETABLE<int> traffType;
+ RESETABLE<double> passiveCost;
+ RESETABLE<std::string> name;
+};
+//-----------------------------------------------------------------------------
+struct TARIFF_DATA
+{
+ TARIFF_CONF tariffConf;
+ std::vector<DIRPRICE_DATA> dirPrice;
+
+ TARIFF_DATA()
+ : tariffConf(),
+ dirPrice(DIR_NUM)
+ {}
+
+ TARIFF_DATA(const std::string & name)
+ : tariffConf(name),
+ dirPrice(DIR_NUM)
+ {}
+
+ TARIFF_DATA(const TARIFF_DATA & td)
+ : tariffConf(td.tariffConf),
+ dirPrice(td.dirPrice)
+ {}
+
+ TARIFF_DATA & operator=(const TARIFF_DATA & td)
+ {
+ tariffConf = td.tariffConf;
+ dirPrice = td.dirPrice;
+ return *this;
+ };
+};
+//-----------------------------------------------------------------------------
+struct TARIFF_DATA_RES
+{
+ TARIFF_CONF_RES tariffConf;
+ std::vector<DIRPRICE_DATA_RES> dirPrice;
+
+ TARIFF_DATA_RES()
+ : tariffConf(),
+ dirPrice(DIR_NUM)
+ {}
+
+ TARIFF_DATA GetData()
+ {
+ TARIFF_DATA td;
+ td.tariffConf = tariffConf.GetData();
+ for (int i = 0; i < DIR_NUM; i++)
+ td.dirPrice[i] = dirPrice[i].GetData();
+ return td;
+ }
+};
+//-----------------------------------------------------------------------------
+#endif
--- /dev/null
+ /*
+ $Revision: 1.12 $
+ $Date: 2010/03/11 14:42:05 $
+ $Author: faust $
+ */
+
+#ifndef USER_CONF_H
+#define USER_CONF_H
+
+#include <string>
+#include <vector>
+#include "stg_const.h"
+#include "user_ips.h"
+#include "resetable.h"
+#include "os_int.h"
+
+//-----------------------------------------------------------------------------
+struct USER_CONF
+{
+ USER_CONF()
+ : password(),
+ passive(0),
+ disabled(0),
+ disabledDetailStat(0),
+ alwaysOnline(0),
+ tariffName(),
+ address(),
+ phone(),
+ email(),
+ note(),
+ realName(),
+ corp(),
+ service(),
+ group(),
+ credit(0),
+ nextTariff(),
+ userdata(USERDATA_NUM),
+ creditExpire(0),
+ ips()
+ {};
+
+ std::string password;
+ int passive;
+ int disabled;
+ int disabledDetailStat;
+ int alwaysOnline;
+ std::string tariffName;
+ std::string address;
+ std::string phone;
+ std::string email;
+ std::string note;
+ std::string realName;
+ std::string corp;
+ std::vector<std::string> service;
+ std::string group;
+ double credit;
+ std::string nextTariff;
+ std::vector<std::string> userdata;
+ time_t creditExpire;
+ USER_IPS ips;
+};
+//-----------------------------------------------------------------------------
+struct USER_CONF_RES
+{
+ USER_CONF_RES()
+ : password(),
+ passive(),
+ disabled(),
+ disabledDetailStat(),
+ alwaysOnline(),
+ tariffName(),
+ address(),
+ phone(),
+ email(),
+ note(),
+ realName(),
+ group(),
+ credit(),
+ nextTariff(),
+ userdata(USERDATA_NUM, RESETABLE<std::string>()),
+ creditExpire(),
+ ips()
+ {
+ };
+
+ USER_CONF_RES & operator=(const USER_CONF & uc)
+ {
+ userdata.resize(USERDATA_NUM);
+ password = uc.password;
+ passive = uc.passive;
+ disabled = uc.disabled;
+ disabledDetailStat = uc.disabledDetailStat;
+ alwaysOnline = uc.alwaysOnline;
+ tariffName = uc.tariffName;
+ address = uc.address;
+ phone = uc.phone;
+ email = uc.email;
+ note = uc.note;
+ realName = uc.realName;
+ group = uc.group;
+ credit = uc.credit;
+ nextTariff = uc.nextTariff;
+ for (int i = 0; i < USERDATA_NUM; i++)
+ {
+ userdata[i] = uc.userdata[i];
+ }
+ creditExpire = uc.creditExpire;
+ ips = uc.ips;
+ return *this;
+ };
+ operator USER_CONF() const
+ {
+ USER_CONF uc;
+ uc.password = password;
+ uc.passive = passive;
+ uc.disabled = disabled;
+ uc.disabledDetailStat = disabledDetailStat;
+ uc.alwaysOnline = alwaysOnline;
+ uc.tariffName = tariffName;
+ uc.address = address;
+ uc.phone = phone;
+ uc.email = email;
+ uc.note = note;
+ uc.realName = realName;
+ uc.group = group;
+ uc.credit = credit;
+ uc.nextTariff = nextTariff;
+ for (int i = 0; i < USERDATA_NUM; i++)
+ {
+ uc.userdata[i] = userdata[i];
+ }
+ uc.creditExpire = creditExpire;
+ uc.ips = ips;
+ return uc;
+ }
+ //-------------------------------------------------------------------------
+
+ RESETABLE<std::string> password;
+ RESETABLE<int> passive;
+ RESETABLE<int> disabled;
+ RESETABLE<int> disabledDetailStat;
+ RESETABLE<int> alwaysOnline;
+ RESETABLE<std::string> tariffName;
+ RESETABLE<std::string> address;
+ RESETABLE<std::string> phone;
+ RESETABLE<std::string> email;
+ RESETABLE<std::string> note;
+ RESETABLE<std::string> realName;
+ RESETABLE<std::string> group;
+ RESETABLE<double> credit;
+ RESETABLE<std::string> nextTariff;
+ std::vector<RESETABLE<std::string> > userdata;
+ RESETABLE<time_t> creditExpire;
+ RESETABLE<USER_IPS> ips;
+};
+//-----------------------------------------------------------------------------
+#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>
+ */
+
+ /*
+ $Revision: 1.22 $
+ $Date: 2010/03/04 11:49:53 $
+ $Author: faust $
+ */
+
+#ifndef USER_IPS_H
+#define USER_IPS_H
+
+#include <vector>
+//#include <algorithm>
+#include <string>
+#include <iostream>
+#include <sstream>
+#include <cstring>
+/////////////////////////
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "common.h"
+#include "os_int.h"
+
+using namespace std;
+
+//-------------------------------------------------------------------------
+struct IP_MASK
+{
+IP_MASK() : ip(0), mask(0) {}
+IP_MASK(const IP_MASK & ipm) : ip(ipm.ip), mask(ipm.mask) {}
+uint32_t ip;
+uint32_t mask;
+};
+//-------------------------------------------------------------------------
+class USER_IPS
+{
+ friend std::ostream & operator<< (ostream & o, const USER_IPS & i);
+ //friend stringstream & operator<< (stringstream & s, const USER_IPS & i);
+ friend const USER_IPS StrToIPS(const string & ipsStr) throw(string);
+
+public:
+ USER_IPS();
+ USER_IPS(const USER_IPS &);
+ USER_IPS & operator=(const USER_IPS &);
+ const IP_MASK & operator[](int idx) const;
+ std::string GetIpStr() const;
+ bool IsIPInIPS(uint32_t ip) const;
+ bool OnlyOneIP() const;
+ int Count() const;
+ void Add(const IP_MASK &im);
+ void Erase();
+
+private:
+ uint32_t CalcMask(unsigned int msk) const;
+ std::vector<IP_MASK> ips;
+};
+//-------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+inline
+USER_IPS::USER_IPS()
+ : ips()
+{}
+//-----------------------------------------------------------------------------
+inline
+USER_IPS::USER_IPS(const USER_IPS & i)
+ : ips(i.ips)
+{}
+//-----------------------------------------------------------------------------
+inline
+USER_IPS & USER_IPS::operator=(const USER_IPS & i)
+{
+ips = i.ips;
+return *this;
+}
+//-----------------------------------------------------------------------------
+inline
+const IP_MASK & USER_IPS::operator[](int idx) const
+{
+return ips[idx];
+}
+//-----------------------------------------------------------------------------
+inline
+std::string USER_IPS::GetIpStr() const
+{
+if (ips.empty())
+ {
+ return "";
+ }
+
+if (ips[0].ip == 0)
+ {
+ return "*";
+ }
+
+std::vector<IP_MASK>::const_iterator it(ips.begin());
+std::stringstream s;
+s << inet_ntostring(it->ip);
+++it;
+for (; it != ips.end(); ++it)
+ {
+ s << "," << inet_ntostring(it->ip);
+ }
+return s.str();
+}
+//-----------------------------------------------------------------------------
+inline
+int USER_IPS::Count() const
+{
+return ips.size();
+}
+//-----------------------------------------------------------------------------
+inline
+bool USER_IPS::IsIPInIPS(uint32_t ip) const
+{
+if (ips.empty())
+ {
+ return false;
+ }
+
+if (ips.front().ip == 0)
+ return true;
+
+for (std::vector<IP_MASK>::const_iterator it(ips.begin()); it != ips.end(); ++it)
+ {
+ uint32_t mask(CalcMask(it->mask));
+ if ((ip & mask) == (it->ip & mask))
+ return true;
+ }
+return false;
+}
+//-----------------------------------------------------------------------------
+inline
+bool USER_IPS::OnlyOneIP() const
+{
+if (ips.size() == 1 && ips.front().mask == 32)
+ return true;
+
+return false;
+}
+//-----------------------------------------------------------------------------
+inline
+uint32_t USER_IPS::CalcMask(unsigned int msk) const
+{
+if (msk > 32)
+ return 0;
+return htonl(0xFFffFFff << (32 - msk));
+}
+//-----------------------------------------------------------------------------
+inline
+void USER_IPS::Add(const IP_MASK &im)
+{
+ips.push_back(im);
+}
+//-----------------------------------------------------------------------------
+inline
+void USER_IPS::Erase()
+{
+ips.erase(ips.begin(), ips.end());
+}
+//-----------------------------------------------------------------------------
+inline
+std::ostream & operator<<(std::ostream & o, const USER_IPS & i)
+{
+return o << i.GetIpStr();
+}
+//-----------------------------------------------------------------------------
+/*inline
+stringstream & operator<<(std::stringstream & s, const USER_IPS & i)
+{
+s << i.GetIpStr();
+return s;
+}*/
+//-----------------------------------------------------------------------------
+inline
+const USER_IPS StrToIPS(const std::string & ipsStr) throw(std::string)
+{
+USER_IPS ips;
+char * paddr;
+IP_MASK im;
+std::vector<std::string> ipMask;
+std::string err;
+if (ipsStr.empty())
+ {
+ err = "Incorrect IP address.";
+ throw(err);
+ }
+
+if (ipsStr[0] == '*' && ipsStr.size() == 1)
+ {
+ im.ip = 0;
+ im.mask = 0;
+ ips.ips.push_back(im);
+ return ips;
+ }
+
+char * str = new char[ipsStr.size() + 1];
+strcpy(str, ipsStr.c_str());
+char * pstr = str;
+while ((paddr = strtok(pstr, ",")))
+ {
+ pstr = NULL;
+ ipMask.push_back(paddr);
+ }
+
+delete[] str;
+
+for (unsigned int i = 0; i < ipMask.size(); i++)
+ {
+ char str[128];
+ char * strIp;
+ char * strMask;
+ strcpy(str, ipMask[i].c_str());
+ strIp = strtok(str, "/");
+ if (strIp == NULL)
+ {
+ err = "Incorrect IP address " + ipsStr;
+ throw(err);
+ }
+ strMask = strtok(NULL, "/");
+
+ im.ip = inet_addr(strIp);
+ if (im.ip == INADDR_NONE)
+ {
+ err = "Incorrect IP address: " + std::string(strIp);
+ throw(err);
+ }
+
+ im.mask = 32;
+ if (strMask != NULL)
+ {
+ int m = 0;
+ if (str2x(strMask, m) != 0)
+ {
+ err = "Incorrect mask: " + std::string(strMask);
+ throw(err);
+ }
+ im.mask = m;
+
+ if (im.mask > 32)
+ {
+ err = "Incorrect mask: " + std::string(strMask);
+ throw(err);
+ }
+
+ if ((im.ip & ips.CalcMask(im.mask)) != im.ip)
+ {
+ err = "Address does'n match mask: " + std::string(strIp) + "/" + std::string(strMask);
+ throw(err);
+ }
+ }
+ ips.ips.push_back(im);
+ }
+
+return ips;
+}
+//-------------------------------------------------------------------------
+#endif //USER_IPS_H
+
+
--- /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>
+ */
+
+ /*
+ $Revision: 1.15 $
+ $Date: 2010/03/11 14:42:05 $
+ $Author: faust $
+ */
+
+#ifndef USER_STAT_H
+#define USER_STAT_H
+
+#include <ctime>
+
+#include "os_int.h"
+#include "resetable.h"
+#include "user_traff.h"
+//-----------------------------------------------------------------------------
+struct IP_DIR_PAIR
+{
+ #ifdef TRAFF_STAT_WITH_PORTS
+ IP_DIR_PAIR(uint32_t _ip,
+ int _dir,
+ uint16_t _port)
+ : ip(_ip),
+ dir(_dir),
+ port(_port)
+ {}
+ #else
+ IP_DIR_PAIR(uint32_t _ip,
+ int _dir)
+ : ip(_ip),
+ dir(_dir)
+ {}
+ #endif
+ //------------------------
+ bool operator<(const IP_DIR_PAIR & idp) const
+ {
+ if (ip < idp.ip)
+ return true;
+
+ if (ip > idp.ip)
+ return false;
+
+ #ifdef TRAFF_STAT_WITH_PORTS
+ if (port < idp.port)
+ return true;
+
+ if (port > idp.port)
+ return false;
+ #endif
+
+ if (dir < idp.dir)
+ return true;
+
+ return false;
+ }
+ //------------------------
+ uint32_t ip;
+ int dir;
+ #ifdef TRAFF_STAT_WITH_PORTS
+ uint16_t port;
+ #endif
+};
+//-----------------------------------------------------------------------------
+struct STAT_NODE
+{
+ STAT_NODE(uint64_t _up,
+ uint64_t _down,
+ double _cash)
+ : up(_up),
+ down(_down),
+ cash(_cash)
+ {}
+ uint64_t up;
+ uint64_t down;
+ double cash;
+};
+//-----------------------------------------------------------------------------
+struct USER_STAT
+{
+ //USER_STAT & operator= (const USER_STAT_RES & usr);
+ USER_STAT()
+ : up(),
+ down(),
+ cash(0),
+ freeMb(0),
+ lastCashAdd(0),
+ lastCashAddTime(0),
+ passiveTime(0),
+ lastActivityTime(0)
+ {};
+
+ DIR_TRAFF up;
+ DIR_TRAFF down;
+ double cash;
+ double freeMb;
+ double lastCashAdd;
+ time_t lastCashAddTime;
+ time_t passiveTime;
+ time_t lastActivityTime;
+};
+//-----------------------------------------------------------------------------
+struct USER_STAT_RES
+{
+ USER_STAT_RES()
+ : cash(),
+ freeMb(),
+ lastCashAdd(),
+ lastCashAddTime(),
+ passiveTime(),
+ lastActivityTime(),
+ up(),
+ down()
+ {}
+
+ USER_STAT_RES & operator= (const USER_STAT & us)
+ {
+ cash = us.cash;
+ freeMb = us.freeMb;
+ lastCashAdd = us.lastCashAdd;
+ lastCashAddTime = us.lastCashAddTime;
+ passiveTime = us.passiveTime;
+ lastActivityTime = us.lastActivityTime;
+ up = us.up;
+ down = us.down;
+ return * this;
+ };
+ operator USER_STAT()
+ {
+ USER_STAT us;
+ us.cash = cash;
+ us.freeMb = freeMb;
+ us.lastCashAdd = lastCashAdd;
+ us.lastCashAddTime = lastCashAddTime;
+ us.passiveTime = passiveTime;
+ us.lastActivityTime = lastActivityTime;
+ us.up = up;
+ us.down = down;
+ return us;
+ };
+
+ RESETABLE<double> cash;
+ RESETABLE<double> freeMb;
+ RESETABLE<double> lastCashAdd;
+ RESETABLE<time_t> lastCashAddTime;
+ RESETABLE<time_t> passiveTime;
+ RESETABLE<time_t> lastActivityTime;
+ RESETABLE<DIR_TRAFF> up;
+ RESETABLE<DIR_TRAFF> down;
+};
+//-----------------------------------------------------------------------------
+#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>
+ */
+
+/*
+ $Revision: 1.7 $
+ $Date: 2010/10/07 19:48:52 $
+ $Author: faust $
+ */
+
+#ifndef USER_TRAFF_H
+#define USER_TRAFF_H
+
+#include <iostream>
+#include <vector>
+
+#include "stg_const.h"
+#include "os_int.h"
+
+enum TRAFF_DIRECTION {TRAFF_UPLOAD, TRAFF_DOWNLOAD};
+
+class DIR_TRAFF
+{
+ friend std::ostream & operator<< (std::ostream & o, const DIR_TRAFF & traff);
+
+public:
+ //-------------------------------------------------------------------------
+ DIR_TRAFF();
+ DIR_TRAFF(const DIR_TRAFF & ts);
+ DIR_TRAFF & operator=(const DIR_TRAFF & ts);
+ ~DIR_TRAFF();
+ uint64_t operator[](int idx) const;
+ uint64_t & operator[](int idx);
+ DIR_TRAFF operator+(const DIR_TRAFF & ts);
+
+private:
+ std::vector<uint64_t> traff;
+};
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+inline DIR_TRAFF::DIR_TRAFF()
+ : traff(DIR_NUM, 0)
+{
+}
+//-----------------------------------------------------------------------------
+inline DIR_TRAFF::DIR_TRAFF(const DIR_TRAFF & ts)
+ : traff(ts.traff)
+{
+}
+//-----------------------------------------------------------------------------
+inline DIR_TRAFF::~DIR_TRAFF()
+{
+}
+//-----------------------------------------------------------------------------
+inline DIR_TRAFF & DIR_TRAFF::operator=(const DIR_TRAFF & ts)
+{
+traff = ts.traff;
+return *this;
+};
+//-----------------------------------------------------------------------------
+inline uint64_t & DIR_TRAFF::operator[](int idx)
+{
+return traff[idx];
+};
+//-----------------------------------------------------------------------------
+inline uint64_t DIR_TRAFF::operator[](int idx) const
+{
+return traff[idx];
+};
+//-----------------------------------------------------------------------------
+inline DIR_TRAFF DIR_TRAFF::operator+(const DIR_TRAFF & ts)
+{
+for (int i = 0; i < DIR_NUM; i++)
+ {
+ traff[i] = traff[i] + ts.traff[i];
+ }
+return *this;
+};
+//-----------------------------------------------------------------------------
+inline std::ostream & operator<<(std::ostream & o, const DIR_TRAFF & traff)
+{
+bool first = true;
+for (size_t i = 0; i < DIR_NUM; ++i)
+ {
+ if (first)
+ first = false;
+ else
+ o << ",";
+ o << traff[i];
+ }
+return o;
+}
+//-----------------------------------------------------------------------------
+#endif
--- /dev/null
+#ifndef UTIME_H
+#define UTIME_H
+
+/*
+ * 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: 22.12.2007
+ */
+
+/*
+ * Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+ /*
+ $Revision: 1.6 $
+ $Date: 2009/08/05 11:40:30 $
+ $Author: faust $
+ */
+
+#include <sys/time.h>
+#include <time.h>
+
+#ifdef FREE_BSD
+typedef long suseconds_t;
+#endif
+
+struct UTIME: public timeval
+{
+ UTIME()
+ {
+ tv_sec = 0;
+ tv_usec = 0;
+ }
+
+ UTIME(time_t t)
+ {
+ tv_sec = t;
+ tv_usec = 0;
+ }
+
+ UTIME(long long a, long long b)
+ {
+ tv_sec = a;
+ tv_usec = b;
+ }
+
+ bool operator<(const UTIME & rhs) const
+ {
+ if (tv_sec < rhs.tv_sec)
+ return true;
+ else if (tv_sec > rhs.tv_sec)
+ return false;
+ else if (tv_usec < rhs.tv_usec)
+ return true;
+ return false;
+ }
+
+ bool operator<=(const UTIME & rhs) const
+ {
+ if (tv_sec < rhs.tv_sec)
+ return true;
+ else if (tv_sec > rhs.tv_sec)
+ return false;
+ else if (tv_usec < rhs.tv_usec)
+ return true;
+ else if (tv_usec > rhs.tv_usec)
+ return false;
+ return true;
+ }
+
+ bool operator>(const UTIME & rhs) const
+ {
+ if (tv_sec > rhs.tv_sec)
+ return true;
+ else if (tv_sec < rhs.tv_sec)
+ return false;
+ else if (tv_usec > rhs.tv_usec)
+ return true;
+ return false;
+ }
+
+ bool operator>=(const UTIME & rhs) const
+ {
+ if (tv_sec > rhs.tv_sec)
+ return true;
+ else if (tv_sec < rhs.tv_sec)
+ return false;
+ else if (tv_usec > rhs.tv_usec)
+ return true;
+ else if (tv_usec < rhs.tv_usec)
+ return false;
+ return true;
+ }
+
+ bool operator==(const UTIME & rhs) const
+ {
+ //cout << tv_sec << "." << tv_usec << " " << rhs.tv_sec << "." << rhs.tv_usec << endl;
+ //cout << (tv_sec == rhs.tv_sec) << " " << (tv_usec == rhs.tv_usec) << endl;
+ return (tv_sec == rhs.tv_sec) && (tv_usec == rhs.tv_usec);
+ }
+
+ UTIME operator+(const UTIME & rhs)
+ {
+ // TODO optimize
+ long long a, b;
+ /*a = tv_sec * 1000000 + tv_usec;
+ b = rhs.tv_sec * 1000000 + rhs.tv_usec;
+ return UTIME((a + b) / 1000000, (a + b) % 1000000);*/
+ a = tv_sec + rhs.tv_sec;
+ b = tv_usec + rhs.tv_usec;
+ if (b > 1000000)
+ {
+ ++a;
+ b -= 1000000;
+ }
+ return UTIME(a, b);
+ }
+
+ UTIME operator-(const UTIME & rhs)
+ {
+ // TODO optimize
+ long long a, b;
+ /*a = tv_sec * 1000000 + tv_usec;
+ b = rhs.tv_sec * 1000000 + rhs.tv_usec;
+ return UTIME((a - b) / 1000000, (a - b) % 1000000);*/
+ a = tv_sec - rhs.tv_sec;
+ b = tv_usec - rhs.tv_usec;
+ if (a >= 0)
+ {
+ if (b >= 0)
+ {
+ return UTIME(a, b);
+ }
+ else
+ {
+ return UTIME(--a, b + 1000000);
+ }
+ }
+ else
+ {
+ if (b >= 0)
+ {
+ return UTIME(++a, 1000000 - b);
+ }
+ else
+ {
+ return UTIME(a, b);
+ }
+ }
+ }
+
+ time_t GetSec() const
+ {
+ return tv_sec;
+ }
+
+ suseconds_t GetUSec() const
+ {
+ return tv_usec;
+ }
+};
+
+
+#endif //UTIME_H
+
--- /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 Mamontiv <faust@stargazer.dp.ua>
+ */
+
+ /*
+ $Revision: 1.5 $
+ $Date: 2009/08/05 09:24:01 $
+ */
+
+#define SERVER_VERSION "2.406"
--- /dev/null
+#ifndef vpn_stg_packets_h\r
+#define vpn_stg_packets_h\r
+\r
+#define VS_MAGIC "VS01"\r
+\r
+enum \r
+{\r
+GET_LOGIN,\r
+GET_LOGIN_ANS,\r
+VS_ALIVE,\r
+VS_ALIVE_ANS,\r
+VS_DISCONNECT\r
+}\r
+\r
+\r
+struct VS_GET_LOGIN\r
+{\r
+char magic[4];\r
+STG_PACKET_TYPES type;\r
+char login[32];\r
+//char password[32];\r
+};\r
+\r
+struct VS_CHECK_LOGIN_ANS\r
+{\r
+char magic[4];\r
+STG_PACKET_TYPES type;\r
+char login[32];\r
+char password[32];\r
+uint32_t ip;\r
+};\r
+\r
+struct VS_ALIVE\r
+{\r
+char magic[4];\r
+STG_PACKET_TYPES type;\r
+char login[32];\r
+uint32_t ip;\r
+};\r
+\r
+struct VS_ALIVE_ANS\r
+{\r
+char magic[4];\r
+STG_PACKET_TYPES type;\r
+char login[32];\r
+uint32_t ip;\r
+};\r
+\r
+struct VS_DISCONNECT\r
+{\r
+char magic[4];\r
+STG_PACKET_TYPES type;\r
+char login[32];\r
+uint32_t ip;\r
+};\r
+\r
+\r
+#endif\r
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.12 2009/03/03 15:49:34 faust Exp $
+###############################################################################
+
+include ../../Makefile.conf
+
+PROG = convertor
+
+SRCS = ./main.cpp \
+ ./settings.cpp
+
+STGLIBS = -lstg_logger \
+ -lstg_common \
+ -ldotconfpp \
+ -lstg_crypto
+
+LIBS += $(LIB_THREAD)
+
+ifeq ($(OS),linux)
+LIBS += -ldl
+else
+LIBS += -lc
+endif
+
+SEARCH_DIRS = -I $(DIR_INCLUDE)
+
+OBJS = $(notdir $(patsubst %.cpp, %.o, $(patsubst %.c, %.o, $(SRCS))))
+
+CXXFLAGS += -Wall
+LDFLAGS += -Wl,-E -L$(DIR_LIB) -Wl,-rpath,$(DIR_LIB)
+
+vpath %.so $(DIR_LIB)
+
+.PHONY: all clean distclean libs plugins install uninstall
+all: libs plugins $(PROG) ../../Makefile.conf
+
+libs:
+ $(MAKE) -C $(DIR_LIBSRC)
+
+plugins: libs
+ $(MAKE) -C $(DIR_PLUGINS)
+
+$(PROG): $(OBJS) $(STGLIBS)
+ $(CC) $^ $(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*
+ $(MAKE) -C $(DIR_LIBSRC) clean
+ $(MAKE) -C $(DIR_PLUGINS) clean
+
+distclean: clean
+ rm -f ../../Makefile.conf
+
+ifneq ($(MAKECMDGOALS),distclean)
+ifneq ($(MAKECMDGOALS),clean)
+ifneq ($(MAKECMDGOALS),uninstall)
+-include deps
+endif
+endif
+endif
+
+deps: $(SRCS) ../../Makefile.conf
+ $(MAKE) -C $(DIR_LIBSRC) includes
+ @>deps ;\
+ for file in $(SRCS); do\
+ echo "`$(CC) $(CXXFLAGS) $(SEARCH_DIRS) -MM $$file` Makefile" >> deps ;\
+ echo -e '\t$$(CC) -c $$< $(CXXFLAGS) $(SEARCH_DIRS) $(DEFS)' >> deps ;\
+ done
+
+
--- /dev/null
+#!/bin/sh
+
+# $Revision: 1.20 $
+# $Author: faust $
+# $Date: 2010/04/14 08:58:43 $
+######################################################
+
+OS=unknown
+sys=`uname -s`
+release=`uname -r | cut -b1`
+BUILD_DIR=`pwd`
+CONFFILE="../../Makefile.conf"
+PREFIX="/"
+BIN_MODE=0755
+DATA_MODE=0644
+OWNER=root
+VAR_DIR="./inst/var/stargazer"
+DEFS="-DDEBUG"
+MAKEOPTS="-j1"
+CXXFLAGS="$CXXFLAGS -g3 -W -Wall -I/usr/local/include"
+LDFLAGS="$LDFLAGS -L/usr/local/lib"
+
+if [ "$sys" = "Linux" ]
+then
+ OS=linux
+ release=""
+ MAKE="make"
+fi
+
+if [ "$sys" = "FreeBSD" ]
+then
+ case $release in
+ 4) OS=bsd;;
+ 5) OS=bsd5;;
+ 6) OS=bsd5;;
+ 7) OS=bsd7;;
+ 8) OS=bsd7;;
+ *) OS=unknown;;
+ esac
+ MAKE="gmake"
+fi
+
+if [ "$OS" = "unknown" ]
+then
+ echo "#############################################################################"
+ echo "# Sorry, but convertor currently supported by Linux, FreeBSD 4.x, 5.x, 6.x #"
+ echo "#############################################################################"
+ exit 1
+fi
+
+echo "#############################################################################"
+echo " Building convertor for $sys $release"
+echo "#############################################################################"
+
+STG_LIBS="stg_logger.lib
+ stg_locker.lib
+ crypto.lib
+ common.lib
+ conffiles.lib
+ dotconfpp.lib"
+
+PLUGINS="store/files"
+
+if [ "$OS" = "linux" ]
+then
+ DEFS="$DEFS -DLINUX"
+ SHELL="/bin/bash"
+ LIB_THREAD=-lpthread
+else
+ if [ "$OS" = "bsd" ]
+ then
+ DEFS="$DEFS -DFREE_BSD"
+ LIB_THREAD=-lc_r
+ else
+ DEFS="$DEFS -DFREE_BSD5"
+ if [ "$OS" = "bsd7" ]
+ then
+ LIB_THREAD=-lpthread
+ else
+ LIB_THREAD=-lc_r
+ fi
+ fi
+ SHELL="/usr/local/bin/bash"
+fi
+
+echo -n "Checking endianess... "
+echo "int main() { int probe = 0x00000001; return *(char *)&probe; }" > build_check.c
+gcc $CXXFLAGS $LDFLAGS -L/usr/lib/mysql -L/usr/local/lib/mysql build_check.c -o fake > /dev/null 2> /dev/null
+if [ $? != 0 ]
+then
+ echo "FAIL!"
+ echo "Endianess checking failed"
+ exit;
+else
+ ./fake
+ if [ $? = 1 ]
+ then
+ ARCH=le
+ CXXFLAGS="$CXXFLAGS -DARCH_LE"
+ echo "Little Endian"
+ else
+ ARCH=be
+ CXXFLAGS="$CXXFLAGS -DARCH_BE"
+ echo "Big Endian"
+ fi
+fi
+rm -f fake
+
+echo -n "Checking for -lfbclient... "
+gcc $CXXFLAGS $LDFLAGS build_check.c -lfbclient $LIB_THREAD -o fake > /dev/null 2> /dev/null
+if [ $? != 0 ]
+then
+ CHECK_FBCLIENT=no
+ echo "no"
+else
+ CHECK_FBCLIENT=yes
+ echo "yes"
+fi
+rm -f fake
+
+echo -n "Checking for mysql_config... "
+MYSQL_VERSION=`mysql_config --version 2> /dev/null`
+if [ $? != 0 ]
+then
+ echo "no";
+ echo -n "Checking for -lmysqlclient... "
+ gcc $CXXFLAGS $LDFLAGS build_check.c -lmysqlclient_r $LIB_THREAD -o fake > /dev/null 2> /dev/null
+ if [ $? != 0 ]
+ then
+ CHECK_MYSQLCLIENT=no
+ echo "no"
+ else
+ CHECK_MYSQLCLIENT=yes
+ echo "yes"
+ fi
+ rm -f fake
+else
+ echo "yes"
+ echo -n "Checking for mysql_config --cflags... "
+ MYSQL_CFLAGS=`mysql_config --cflags 2> /dev/null`
+ if [ $? != 0 ]
+ then
+ CHECK_MYSQLCLIENT=no
+ echo "no"
+ else
+ #CXXFLAGS="$CXXFLAGS $MYSQL_CFLAGS"
+ echo "[$MYSQL_CFLAGS]"
+ echo -n "Checking for mysql_config --libs_r... "
+ MYSQL_LDFLAGS=`mysql_config --libs_r 2> /dev/null`
+ if [ $? != 0 ]
+ then
+ CHECK_MYSQLCLIENT=no
+ echo "no"
+ else
+ CHECK_MYSQLCLIENT=yes
+ #LDFLAGS="$LDFLAGS $MYSQL_LDFLAGS"
+ echo "[$MYSQL_LDFLAGS]"
+ fi
+ fi
+fi
+
+echo -n "Checking for pg_config... "
+PG_VERSION=`pg_config --version 2> /dev/null`
+if [ $? != 0 ]
+then
+ echo "no";
+ echo -n "Checking for -lpq... "
+ gcc $CXXFLAGS $LDFLAGS build_check.c -lpq $LIB_THREAD -o fake > /dev/null 2> /dev/null
+ if [ $? != 0 ]
+ then
+ CHECK_PQ=no
+ echo "no"
+ else
+ CHECK_PQ=yes
+ echo "yes"
+ fi
+ rm -f fake
+else
+ echo "yes";
+ echo -n "Checking for pg_config --includedir... "
+ PG_CFLAGS=`pg_config --includedir 2> /dev/null`
+ if [ $? != 0 ]
+ then
+ CHECK_PQ=no
+ echo "no"
+ else
+ echo "[$PG_CFLAGS]"
+ echo -n "Checking for pg_config --libdir... "
+ PG_LDFLAGS=`pg_config --libdir 2> /dev/null`
+ if [ $? != 0 ]
+ then
+ CHECK_PQ=no
+ echo "no"
+ else
+ CHECK_PQ=yes
+ echo "[$PG_LDFLAGS]"
+ fi
+ fi
+fi
+
+rm -f build_check.c
+
+if [ "$CHECK_FBCLIENT" = "yes" ]
+then
+ STG_LIBS="$STG_LIBS
+ ibpp.lib"
+ PLUGINS="$PLUGINS
+ store/firebird"
+fi
+
+if [ "$CHECK_PQ" = "yes" ]
+then
+ PLUGINS="$PLUGINS
+ store/postgresql"
+fi
+
+if [ "$CHECK_MYSQLCLIENT" = "yes" ]
+then
+ PLUGINS="$PLUGINS
+ store/mysql"
+fi
+
+echo "OS=$OS" > $CONFFILE
+echo "STG_TIME=yes" >> $CONFFILE
+echo "DIR_BUILD=$BUILD_DIR" >> $CONFFILE
+echo "DIR_LIB=\$(DIR_BUILD)/../../lib" >> $CONFFILE
+echo "DIR_LIBSRC=\$(DIR_BUILD)/../../stglibs" >> $CONFFILE
+echo "DIR_INCLUDE=\$(DIR_BUILD)/../../include" >> $CONFFILE
+echo "DIR_MOD=\$(DIR_BUILD)/../stargazer/modules" >> $CONFFILE
+echo "DIR_PLUGINS=\$(DIR_BUILD)/../stargazer/plugins" >> $CONFFILE
+echo "ARCH=$ARCH" >> $CONFFILE
+echo "CHECK_FBCLIENT=$CHECK_FBCLIENT" >> $CONFFILE
+echo "DEFS=$DEFS" >> $CONFFILE
+echo -n "STG_LIBS=" >> $CONFFILE
+for lib in $STG_LIBS
+do
+ echo -n "$lib " >> $CONFFILE
+done
+echo "" >> $CONFFILE
+echo -n "PLUGINS=" >> $CONFFILE
+for plugin in $PLUGINS
+do
+ echo -n "$plugin " >> $CONFFILE
+done
+echo "" >> $CONFFILE
+echo "SHELL=$SHELL" >> $CONFFILE
+echo "CXXFLAGS=$CXXFLAGS" >> $CONFFILE
+echo "LDFLAGS=$LDFLAGS" >> $CONFFILE
+echo "LIB_THREAD=$LIB_THREAD" >> $CONFFILE
+echo "PREFIX=$PREFIX" >> $CONFFILE
+echo "BIN_MODE=$BIN_MODE" >> $CONFFILE
+echo "DATA_MODE=$DATA_MODE" >> $CONFFILE
+echo "OWNER=$OWNER" >> $CONFFILE
+echo "VAR_DIR=$VAR_DIR" >> $CONFFILE
+
+mkdir -p ../stargazer/modules
+
+$MAKE $MAKEOPTS
+
--- /dev/null
+################################################################################
+# æÁÊÌ ÎÁÓÔÒÏÅË ËÏÎ×ÅÒÔÏÒÁ stargazer #
+################################################################################
+
+# ðÕÔØ Ë ÄÉÒÅËÔÏÒÉÉ, × ËÏÔÏÒÏÊ ÎÁÈÏÄÑÔÓÑ ÍÏÄÕÌÉ ÓÅÒ×ÅÒÁ
+ModulesPath = ../stargazer/modules
+
+################################################################################
+# Store module
+# îÁÓÔÒÏÊËÉ ÐÌÁÇÉÎÁ ÒÁÂÏÔÁÀÝÅÇÏ Ó âä ÓÅÒ×ÅÒÁ
+
+# ÷ÔÏÒÏÊ ÐÁÒÁÍÅÔÒ - ÜÔÏ ÉÍÑ ÍÏÄÕÌÑ ÂÅÚ mod_ × ÎÁÞÁÌÅ É .so × ËÏÎÃÅ
+# ô.Å. ÐÏÌÎÏÅ ÉÍÑ ÍÏÄÕÌÑ mod_store_files.so
+<SourceStoreModule store_files>
+
+ # òÁÂÏÞÁÑ ÄÉÒÅËÔÏÒÉÑ ÓÅÒ×ÅÒÁ, ÔÕÔ ÓÏÄÅÒÖÁÔÓÑ ÄÁÎÎÙÅ Ï ÔÁÒÉÆÁÈ, ÐÏÌØÚÏ×ÁÔÅÌÑÈ,
+ # ÁÄÍÉÎÉÓÔÒÁÔÏÒÁÈ É Ô.Ä.
+ WorkDir = /var/stargazer
+
+
+ # ÷ÌÁÄÅÌÅÃ, ÇÒÕÐÐÁ É ÐÒÁ×Á ÄÏÓÔÕÐÁ ÎÁ ÆÁÊÌÙ ÓÔÁÔÉÓÔÉËÉ (stat) ÐÏÌØÚÏ×ÁÔÅÌÑ
+ ConfOwner = root
+ ConfGroup = wheel
+ ConfMode = 600
+
+
+ # ÷ÌÁÄÅÌÅÃ, ÇÒÕÐÐÁ É ÐÒÁ×Á ÄÏÓÔÕÐÁ ÎÁ ÆÁÊÌÙ ËÏÎÆÉÇÕÒÁÃÉÉ (conf) ÐÏÌØÚÏ×ÁÔÅÌÑ
+ StatOwner = root
+ StatGroup = wheel
+ StatMode = 640
+
+ # ÷ÌÁÄÅÌÅÃ, ÇÒÕÐÐÁ É ÐÒÁ×Á ÄÏÓÔÕÐÁ ÎÁ ÌÏÇ-ÆÁÊÌÙ (log) ÐÏÌØÚÏ×ÁÔÅÌÑ
+ UserLogOwner = root
+ UserLogGroup = wheel
+ UserLogMode = 640
+
+</SourceStoreModule>
+
+#<DestStoreModule store_firebird>
+# server = localhost
+# database = /var/stargazer/stargazer.fdb
+# user = stg
+# password = 123456
+#</DestStoreModule>
+
+<DestStoreModule store_postgresql>
+ server = localhost
+ database = stargazer
+ user = stg
+ password = 123456
+</DestStoreModule>
+
+#<DestStoreModule store_mysql>
+# # éÍÑ ÐÏÌØÚÏ×ÁÔÅÌÑ âä
+# dbuser = stg
+#
+# # ðÁÒÏÌØ ÐÏÌØÚÏ×ÁÔÅÌÑ âä
+# rootdbpass = 123456
+#
+# # éÍÑ âä ÎÁ ÓÅÒ×ÅÒÅ
+# dbname = stg
+#
+# # áÄÒÅÓ ÓÅÒ×ÅÒÁ âä
+# dbhost = localhost
+#</DestStoreModule>
+
--- /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>
+ */
+
+ /*
+ $Revision: 1.11 $
+ $Date: 2010/03/25 12:32:30 $
+ $Author: faust $
+ */
+
+#include <dlfcn.h>
+
+#include <string>
+#include <vector>
+#include <iostream>
+#include <ctime>
+#include <algorithm>
+
+#include "common.h"
+#include "base_store.h"
+#include "settings.h"
+#include "conffiles.h"
+
+#include "user_stat.h"
+#include "user_conf.h"
+#include "corp_conf.h"
+#include "service_conf.h"
+#include "admin_conf.h"
+#include "tariff_conf.h"
+#include "base_settings.h"
+#include "stg_message.h"
+
+using namespace std;
+
+volatile time_t stgTime = time(NULL);
+
+int main(int argc, char **argv)
+{
+printfd(__FILE__, "Start\n");
+
+BASE_STORE * fromStore = NULL;
+BASE_STORE * toStore = NULL;
+
+SETTINGS * settings = NULL;
+
+string modulePath;
+
+MODULE_SETTINGS fromStoreSettings;
+MODULE_SETTINGS toStoreSettings;
+
+ADMIN_CONF ac;
+USER_CONF uc;
+USER_STAT us;
+STG_MSG msg;
+TARIFF_DATA td;
+CORP_CONF cc;
+SERVICE_CONF sc;
+vector<STG_MSG_HDR> hdrs;
+vector<STG_MSG_HDR>::iterator mit;
+
+void * src_lh;
+void * dst_lh;
+
+if (argc == 2)
+ settings = new SETTINGS(argv[1]);
+else
+ settings = new SETTINGS();
+
+if (settings->ReadSettings())
+{
+ printfd(__FILE__, "Error reading settings\n");
+ delete settings;
+ return -1;
+}
+
+fromStoreSettings = settings->GetSourceStoreModuleSettings();
+toStoreSettings = settings->GetDestStoreModuleSettings();
+modulePath = settings->GetModulesPath();
+
+string sourcePlugin(modulePath + "/mod_" + fromStoreSettings.moduleName + ".so");
+string destPlugin(modulePath + "/mod_" + toStoreSettings.moduleName + ".so");
+
+src_lh = dlopen(sourcePlugin.c_str(), RTLD_NOW);
+if (!src_lh)
+ {
+ printfd(__FILE__, "Source storage plugin loading failed: %s\n", dlerror());
+ delete settings;
+ return -1;
+ }
+
+dst_lh = dlopen(destPlugin.c_str(), RTLD_NOW);
+if (!dst_lh)
+ {
+ printfd(__FILE__, "Destination storage plugin loading failed: %s\n", dlerror());
+ delete settings;
+ return -1;
+ }
+
+BASE_STORE * (*GetSourceStore)();
+BASE_STORE * (*GetDestStore)();
+GetSourceStore = (BASE_STORE * (*)())dlsym(src_lh, "GetStore");
+if (!GetSourceStore)
+ {
+ printfd(__FILE__, "Source storage plugin loading failed. GetStore not found: %s\n", dlerror());
+ delete settings;
+ return -1;
+ }
+GetDestStore = (BASE_STORE * (*)())dlsym(dst_lh, "GetStore");
+if (!GetDestStore)
+ {
+ printfd(__FILE__, "Storage plugin (firebird) loading failed. GetStore not found: %s\n", dlerror());
+ delete settings;
+ return -1;
+ }
+
+fromStore = GetSourceStore();
+toStore = GetDestStore();
+
+vector<string> entities;
+vector<string> ready;
+vector<string>::const_iterator it;
+fromStore->SetSettings(fromStoreSettings);
+fromStore->ParseSettings();
+toStore->SetSettings(toStoreSettings);
+toStore->ParseSettings();
+
+printfd(__FILE__, "Importing admins:\n");
+entities.erase(entities.begin(), entities.end());
+ready.erase(ready.begin(), ready.end());
+if (fromStore->GetAdminsList(&entities))
+ {
+ printfd(__FILE__, "Error getting admins list: %s\n", fromStore->GetStrError().c_str());
+ dlclose(src_lh);
+ dlclose(dst_lh);
+ delete settings;
+ return -1;
+ }
+if (toStore->GetAdminsList(&ready))
+ {
+ printfd(__FILE__, "Error getting admins list: %s\n", toStore->GetStrError().c_str());
+ dlclose(src_lh);
+ dlclose(dst_lh);
+ delete settings;
+ return -1;
+ }
+for (it = entities.begin(); it != entities.end(); ++it)
+ {
+ printfd(__FILE__, "\t - %s\n", it->c_str());
+ if (find(ready.begin(), ready.end(), *it) == ready.end())
+ if (toStore->AddAdmin(*it))
+ {
+ printfd(__FILE__, "Error adding admin: %s\n", toStore->GetStrError().c_str());
+ dlclose(src_lh);
+ dlclose(dst_lh);
+ delete settings;
+ return -1;
+ }
+ if (fromStore->RestoreAdmin(&ac, *it))
+ {
+ printfd(__FILE__, "Error getting admin's confi: %s\n", fromStore->GetStrError().c_str());
+ dlclose(src_lh);
+ dlclose(dst_lh);
+ delete settings;
+ return -1;
+ }
+ ac.login = *it;
+ if (toStore->SaveAdmin(ac))
+ {
+ printfd(__FILE__, "Error saving admin's conf: %s\n", toStore->GetStrError().c_str());
+ dlclose(src_lh);
+ dlclose(dst_lh);
+ delete settings;
+ return -1;
+ }
+ }
+
+printfd(__FILE__, "Importing tariffs:\n");
+entities.erase(entities.begin(), entities.end());
+ready.erase(ready.begin(), ready.end());
+if (fromStore->GetTariffsList(&entities))
+ {
+ printfd(__FILE__, "Error getting tariffs list: %s\n", fromStore->GetStrError().c_str());
+ dlclose(src_lh);
+ dlclose(dst_lh);
+ delete settings;
+ return -1;
+ }
+if (toStore->GetTariffsList(&ready))
+ {
+ printfd(__FILE__, "Error getting tariffs list: %s\n", toStore->GetStrError().c_str());
+ dlclose(src_lh);
+ dlclose(dst_lh);
+ delete settings;
+ return -1;
+ }
+for (it = entities.begin(); it != entities.end(); ++it)
+ {
+ printfd(__FILE__, "\t - %s\n", it->c_str());
+ if (find(ready.begin(), ready.end(), *it) == ready.end())
+ if (toStore->AddTariff(*it))
+ {
+ printfd(__FILE__, "Error adding tariff: %s\n", toStore->GetStrError().c_str());
+ dlclose(src_lh);
+ dlclose(dst_lh);
+ delete settings;
+ return -1;
+ }
+ if (fromStore->RestoreTariff(&td, *it))
+ {
+ printfd(__FILE__, "Error getting tariff's data: %s\n", fromStore->GetStrError().c_str());
+ dlclose(src_lh);
+ dlclose(dst_lh);
+ delete settings;
+ return -1;
+ }
+ if (toStore->SaveTariff(td, *it))
+ {
+ printfd(__FILE__, "Error saving tariff's data: %s\n", toStore->GetStrError().c_str());
+ dlclose(src_lh);
+ dlclose(dst_lh);
+ delete settings;
+ return -1;
+ }
+ }
+
+printfd(__FILE__, "Importing services:\n");
+entities.erase(entities.begin(), entities.end());
+ready.erase(ready.begin(), ready.end());
+if (fromStore->GetServicesList(&entities))
+ {
+ printfd(__FILE__, "Error getting service list: %s\n", fromStore->GetStrError().c_str());
+ dlclose(src_lh);
+ dlclose(dst_lh);
+ delete settings;
+ return -1;
+ }
+if (toStore->GetServicesList(&ready))
+ {
+ printfd(__FILE__, "Error getting service list: %s\n", toStore->GetStrError().c_str());
+ dlclose(src_lh);
+ dlclose(dst_lh);
+ delete settings;
+ return -1;
+ }
+for (it = entities.begin(); it != entities.end(); ++it)
+ {
+ printfd(__FILE__, "\t - %s\n", it->c_str());
+ if (find(ready.begin(), ready.end(), *it) == ready.end())
+ if (toStore->AddService(*it))
+ {
+ printfd(__FILE__, "Error adding service: %s\n", toStore->GetStrError().c_str());
+ dlclose(src_lh);
+ dlclose(dst_lh);
+ delete settings;
+ return -1;
+ }
+ if (fromStore->RestoreService(&sc, *it))
+ {
+ printfd(__FILE__, "Error getting service's data: %s\n", fromStore->GetStrError().c_str());
+ dlclose(src_lh);
+ dlclose(dst_lh);
+ delete settings;
+ return -1;
+ }
+ if (toStore->SaveService(sc))
+ {
+ printfd(__FILE__, "Error saving service's data: %s\n", toStore->GetStrError().c_str());
+ dlclose(src_lh);
+ dlclose(dst_lh);
+ delete settings;
+ return -1;
+ }
+ }
+
+printfd(__FILE__, "Importing corporations:\n");
+entities.erase(entities.begin(), entities.end());
+ready.erase(ready.begin(), ready.end());
+if (fromStore->GetCorpsList(&entities))
+ {
+ printfd(__FILE__, "Error getting corporations list: %s\n", fromStore->GetStrError().c_str());
+ dlclose(src_lh);
+ dlclose(dst_lh);
+ delete settings;
+ return -1;
+ }
+if (toStore->GetCorpsList(&ready))
+ {
+ printfd(__FILE__, "Error getting corporations list: %s\n", toStore->GetStrError().c_str());
+ dlclose(src_lh);
+ dlclose(dst_lh);
+ delete settings;
+ return -1;
+ }
+for (it = entities.begin(); it != entities.end(); ++it)
+ {
+ printfd(__FILE__, "\t - %s\n", it->c_str());
+ if (find(ready.begin(), ready.end(), *it) == ready.end())
+ if (toStore->AddCorp(*it))
+ {
+ printfd(__FILE__, "Error adding corporation: %s\n", toStore->GetStrError().c_str());
+ dlclose(src_lh);
+ dlclose(dst_lh);
+ delete settings;
+ return -1;
+ }
+ if (fromStore->RestoreCorp(&cc, *it))
+ {
+ printfd(__FILE__, "Error getting corporation's data: %s\n", fromStore->GetStrError().c_str());
+ dlclose(src_lh);
+ dlclose(dst_lh);
+ delete settings;
+ return -1;
+ }
+ if (toStore->SaveCorp(cc))
+ {
+ printfd(__FILE__, "Error saving corporation's data: %s\n", toStore->GetStrError().c_str());
+ dlclose(src_lh);
+ dlclose(dst_lh);
+ delete settings;
+ return -1;
+ }
+ }
+
+printfd(__FILE__, "Importing users:\n");
+entities.erase(entities.begin(), entities.end());
+ready.erase(ready.begin(), ready.end());
+if (fromStore->GetUsersList(&entities))
+ {
+ printfd(__FILE__, "Error getting users list: %s\n", fromStore->GetStrError().c_str());
+ dlclose(src_lh);
+ dlclose(dst_lh);
+ delete settings;
+ return -1;
+ }
+if (toStore->GetUsersList(&ready))
+ {
+ printfd(__FILE__, "Error getting users list: %s\n", toStore->GetStrError().c_str());
+ dlclose(src_lh);
+ dlclose(dst_lh);
+ delete settings;
+ return -1;
+ }
+sort(ready.begin(), ready.end());
+for (it = entities.begin(); it != entities.end(); ++it)
+ {
+ printfd(__FILE__, "\t - %s\n", it->c_str());
+ if (!binary_search(ready.begin(), ready.end(), *it)) {
+ if (toStore->AddUser(*it))
+ {
+ printfd(__FILE__, "Error adding user: %s\n", toStore->GetStrError().c_str());
+ dlclose(src_lh);
+ dlclose(dst_lh);
+ delete settings;
+ return -1;
+ }
+ } else {
+ printfd(__FILE__, "\t\t(adding passed)\n");
+ }
+ if (fromStore->RestoreUserConf(&uc, *it))
+ {
+ printfd(__FILE__, "Error getting user's conf: %s\n", fromStore->GetStrError().c_str());
+ dlclose(src_lh);
+ dlclose(dst_lh);
+ delete settings;
+ return -1;
+ }
+ if (fromStore->RestoreUserStat(&us, *it))
+ {
+ printfd(__FILE__, "Error getting user's stat: %s\n", fromStore->GetStrError().c_str());
+ dlclose(src_lh);
+ dlclose(dst_lh);
+ delete settings;
+ return -1;
+ }
+ if (toStore->SaveUserConf(uc, *it))
+ {
+ printfd(__FILE__, "Error saving user's conf: %s\n", toStore->GetStrError().c_str());
+ dlclose(src_lh);
+ dlclose(dst_lh);
+ delete settings;
+ return -1;
+ }
+ if (toStore->SaveUserStat(us, *it))
+ {
+ printfd(__FILE__, "Error saving user's stat: %s\n", toStore->GetStrError().c_str());
+ dlclose(src_lh);
+ dlclose(dst_lh);
+ delete settings;
+ return -1;
+ }
+ hdrs.erase(hdrs.begin(), hdrs.end());
+ if (fromStore->GetMessageHdrs(&hdrs, *it))
+ {
+ printfd(__FILE__, "Error getting user's messages: %s\n", fromStore->GetStrError().c_str());
+ dlclose(src_lh);
+ dlclose(dst_lh);
+ delete settings;
+ return -1;
+ }
+ for (mit = hdrs.begin(); mit != hdrs.end(); ++mit)
+ {
+ if (fromStore->GetMessage(mit->id, &msg, *it))
+ {
+ printfd(__FILE__, "Error getting message for a user: %s\n", fromStore->GetStrError().c_str());
+ dlclose(src_lh);
+ dlclose(dst_lh);
+ delete settings;
+ return -1;
+ }
+ printfd(__FILE__, "\t\t * %s\n", msg.text.c_str());
+ if (toStore->AddMessage(&msg, *it))
+ {
+ printfd(__FILE__, "Error adding message to a user: %s\n", toStore->GetStrError().c_str());
+ dlclose(src_lh);
+ dlclose(dst_lh);
+ delete settings;
+ return -1;
+ }
+ }
+
+ }
+
+dlclose(src_lh);
+dlclose(dst_lh);
+printfd(__FILE__, "Done\n");
+delete settings;
+return 0;
+}
--- /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>
+ */
+
+/*
+$Revision: 1.6 $
+$Date: 2009/06/22 16:26:54 $
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <string>
+
+using namespace std;
+
+#include "settings.h"
+#include "common.h"
+
+//-----------------------------------------------------------------------------
+SETTINGS::SETTINGS(const char * cf)
+{
+confFile = string(cf);
+}
+//-----------------------------------------------------------------------------
+SETTINGS::~SETTINGS()
+{
+
+}
+//-----------------------------------------------------------------------------
+/*
+int SETTINGS::ParseYesNo(const string & value, bool * val)
+{
+if (0 == strcasecmp(value.c_str(), "yes"))
+ {
+ *val = true;
+ return 0;
+ }
+if (0 == strcasecmp(value.c_str(), "no"))
+ {
+ *val = false;
+ return 0;
+ }
+
+strError = "Incorrect value \'" + value + "\'.";
+return -1;
+}
+//-----------------------------------------------------------------------------
+int SETTINGS::ParseInt(const string & value, int * val)
+{
+char *res;
+*val = strtol(value.c_str(), &res, 10);
+if (*res != 0)
+ {
+ strError = "Cannot convert \'" + value + "\' to integer.";
+ return -1;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int SETTINGS::ParseIntInRange(const string & value, int min, int max, int * val)
+{
+if (ParseInt(value, val) != 0)
+ return -1;
+
+if (*val < min || *val > max)
+ {
+ strError = "Value \'" + value + "\' out of range.";
+ return -1;
+ }
+
+return 0;
+}
+*/
+//-----------------------------------------------------------------------------
+int SETTINGS::ParseModuleSettings(const DOTCONFDocumentNode * node, vector<PARAM_VALUE> * params)
+{
+/*if (!node)
+ return 0;*/
+const DOTCONFDocumentNode * childNode;
+PARAM_VALUE pv;
+const char * value;
+
+pv.param = node->getName();
+
+if (node->getValue(1))
+ {
+ strError = "Unexpected value \'" + string(node->getValue(1)) + "\'.";
+ return -1;
+ }
+
+value = node->getValue(0);
+
+if (!value)
+ {
+ strError = "Module name expected.";
+ return -1;
+ }
+
+childNode = node->getChildNode();
+while (childNode)
+ {
+ pv.param = childNode->getName();
+ int i = 0;
+ while ((value = childNode->getValue(i)) != NULL)
+ {
+ //printfd(__FILE__, "--> param=\'%s\' value=\'%s\'\n", childNode->getName(), value);
+ pv.value.push_back(value);
+ i++;
+ }
+ params->push_back(pv);
+ pv.value.clear();
+ childNode = childNode->getNextNode();
+ }
+
+/*for (unsigned i = 0; i < params->size(); i++)
+ {
+ printfd(__FILE__, "param \'%s\'\n", (*params)[i].param.c_str());
+ for (unsigned j = 0; j < (*params)[i].value.size(); j++)
+ {
+ printfd(__FILE__, "value \'%s\'\n", (*params)[i].value[j].c_str());
+ }
+ }*/
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+string SETTINGS::GetStrError() const
+{
+return strError;
+}
+//-----------------------------------------------------------------------------
+int SETTINGS::ReadSettings()
+{
+const char * requiredOptions[] = {
+ "ModulesPath",
+ "SourceStoreModule",
+ "DestStoreModule",
+ NULL
+ };
+int sourceStoreModulesCount = 0;
+int destStoreModulesCount = 0;
+
+DOTCONFDocument conf(DOTCONFDocument::CASEINSENSITIVE);
+conf.setRequiredOptionNames(requiredOptions);
+
+//printfd(__FILE__, "Conffile: %s\n", confFile.c_str());
+
+if(conf.setContent(confFile.c_str()) != 0)
+ {
+ strError = "Cannot read file " + confFile + ".";
+ return -1;
+ }
+
+const DOTCONFDocumentNode * node = conf.getFirstNode();
+
+while (node)
+ {
+ if (strcasecmp(node->getName(), "ModulesPath") == 0)
+ {
+ modulesPath = node->getValue(0);
+ //printfd(__FILE__, "ModulesPath: %s\n", logFile.c_str());
+ }
+
+ if (strcasecmp(node->getName(), "SourceStoreModule") == 0)
+ {
+ // íÙ ×ÎÕÔÒÉ ÓÅËÃÉÉ StoreModule
+ //printfd(__FILE__, "StoreModule\n");
+
+ if (node->getValue(1))
+ {
+ // StoreModule ÄÏÌÖÅÎ ÉÍÅÔØ 1 ÁÔÒÉÂÕÔ
+ strError = "Unexpected \'" + string(node->getValue(1)) + "\'.";
+ return -1;
+ }
+
+ if (sourceStoreModulesCount)
+ {
+ // äÏÌÖÅÎ ÂÙÔØ ÔÏÌØËÏ ÏÄÉÎ ÍÏÄÕÌØ StoreModule!
+ strError = "Should be only one source StoreModule.";
+ return -1;
+ }
+ sourceStoreModulesCount++;
+
+ //storeModuleSettings.clear(); //TODO To make constructor
+ //printfd(__FILE__, "StoreModule %s\n", node->getValue());
+ sourceStoreModuleSettings.moduleName = node->getValue(0);
+ ParseModuleSettings(node, &sourceStoreModuleSettings.moduleParams);
+ }
+
+ if (strcasecmp(node->getName(), "DestStoreModule") == 0)
+ {
+ // íÙ ×ÎÕÔÒÉ ÓÅËÃÉÉ StoreModule
+ //printfd(__FILE__, "StoreModule\n");
+
+ if (node->getValue(1))
+ {
+ // StoreModule ÄÏÌÖÅÎ ÉÍÅÔØ 1 ÁÔÒÉÂÕÔ
+ strError = "Unexpected \'" + string(node->getValue(1)) + "\'.";
+ return -1;
+ }
+
+ if (destStoreModulesCount)
+ {
+ // äÏÌÖÅÎ ÂÙÔØ ÔÏÌØËÏ ÏÄÉÎ ÍÏÄÕÌØ StoreModule!
+ strError = "Should be only one dest StoreModule.";
+ return -1;
+ }
+ destStoreModulesCount++;
+
+ //storeModuleSettings.clear(); //TODO To make constructor
+ //printfd(__FILE__, "StoreModule %s\n", node->getValue());
+ destStoreModuleSettings.moduleName = node->getValue(0);
+ ParseModuleSettings(node, &destStoreModuleSettings.moduleParams);
+ }
+
+ node = node->getNextNode();
+ }
+
+//sort(modulesSettings.begin(), modulesSettings.end());
+//modulesSettings.erase(unique(modulesSettings.begin(), modulesSettings.end()), modulesSettings.end());
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int SETTINGS::Reload ()
+{
+return ReadSettings();
+}
+//-----------------------------------------------------------------------------
+const MODULE_SETTINGS & SETTINGS::GetSourceStoreModuleSettings() const
+{
+return sourceStoreModuleSettings;
+}
+//-----------------------------------------------------------------------------
+const MODULE_SETTINGS & SETTINGS::GetDestStoreModuleSettings() const
+{
+return destStoreModuleSettings;
+}
+//-----------------------------------------------------------------------------
+const string & SETTINGS::GetModulesPath() const
+{
+return modulesPath;
+}
+//-----------------------------------------------------------------------------
+
--- /dev/null
+ /*
+ $Revision: 1.6 $
+ $Date: 2009/06/22 16:26:54 $
+ */
+
+/*
+ * 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>
+ */
+
+#ifndef settingsh_h
+#define settingsh_h 1
+
+#include <sys/types.h>
+#include <vector>
+#include <dotconfpp.h>
+
+#include "common.h"
+#include "base_settings.h"
+#include "stg_logger.h"
+
+using namespace std;
+
+//-----------------------------------------------------------------------------
+class SETTINGS
+{
+public:
+ SETTINGS(const char * cf = "./convertor.conf");
+ ~SETTINGS();
+ int Reload();
+ int ReadSettings();
+
+ string GetStrError() const;
+
+ const string & GetConfDir() const;
+
+ const string & GetModulesPath() const;
+ const MODULE_SETTINGS & GetSourceStoreModuleSettings() const;
+ const MODULE_SETTINGS & GetDestStoreModuleSettings() const;
+
+private:
+
+ //int ParseInt(const string & value, int * val);
+ //int ParseIntInRange(const string & value, int min, int max, int * val);
+ //int ParseYesNo(const string & value, bool * val);
+
+ int ParseModuleSettings(const DOTCONFDocumentNode * dirNameNode, vector<PARAM_VALUE> * params);
+
+ string strError;
+ //////////settings
+ string modulesPath;
+ string confFile;
+
+ MODULE_SETTINGS sourceStoreModuleSettings;
+ MODULE_SETTINGS destStoreModuleSettings;
+};
+//-----------------------------------------------------------------------------
+#endif
+
--- /dev/null
+#!/usr/bin/expect
+
+# login_cvs host password
+
+set user [lindex $argv 0]
+set pass [lindex $argv 1]
+set host [lindex $argv 2]
+set cvsroot [lindex $argv 3]
+set module [lindex $argv 4]
+set dir [lindex $argv 5]
+
+set timeout 30
+
+send_user "checkout module $module";
+
+spawn ssh $user@$host
+expect {
+ "(yes/no)? " {
+ send "yes\r"
+ send_user "Key accepted";
+ }
+ "assword:" {
+ close
+ send_user "Key accepting dont needed";
+ }
+ }
+
+spawn cvs -d :ext:$user@$host:$cvsroot co -N -d $dir $module
+expect {
+ "assword:" {
+ send "$pass\r"
+ expect {
+ "assword:" {
+ send_user "<h3><font color=red>cvs checkout $module failed. Incorrect password</font></h3>";
+ exit 1
+ }
+ "aborted" {
+ send_user "<h3><font color=red>cvs checkout $module failed.</font></h3>";
+ exit 1
+ }
+ expect eof {
+ if {[lindex [wait] 3]} {
+ send_user "<h3><font color=red>cvs checkout $module failed.</font></h3>"
+ exit 1
+ }
+ }
+ }
+ }
+
+ "aborted" {
+ send_user "<h3><font color=red>cvs checkout $module failed.</font></h3>";
+ exit 1
+ }
+ }
+
+
+
+
--- /dev/null
+#!/bin/bash
+
+
+cvs_host=stgteam.dp.ua
+cvs_user=<user>
+cvs_pass=<password>
+
+#arc_name=stg-2.4-`date "+%Y.%m.%d-%H.%M.%S"`.tgz
+#arc_name=stg-2.4-`date "+%Y.%m.%d-%H.%M.%S"`.tgz
+src_dir=stg-2.4-`date "+%Y.%m.%d-%H.%M.%S"`
+arc_name=$src_dir.tar.gz
+
+#mkdir $src_dir
+
+./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stgincludes include $src_dir
+
+./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/common.lib $src_dir
+./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/ibpp.lib $src_dir
+./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/common_settings.lib $src_dir
+./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/conffiles.lib $src_dir
+./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/crypto.lib $src_dir
+./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/stg_logger.lib $src_dir
+./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/stg_locker.lib $src_dir
+./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/hostallow.lib $src_dir
+./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/pinger.lib $src_dir
+./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/dotconfpp.lib $src_dir
+./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/ia_auth_c.lib $src_dir
+./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/script_executer.lib $src_dir
+./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/srvconf.lib $src_dir
+
+./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/Makefile $src_dir
+./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/Makefile.in $src_dir
+./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stargazer convertor $src_dir/projects
+./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stargazer stargazer $src_dir/projects
+
+./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/sgauth sgauth $src_dir/projects
+./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/sgconf sgconf $src_dir/projects
+./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/rscriptd rscriptd $src_dir/projects
+./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stargazer rlm_stg $src_dir/projects
+
+./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stgplugins plugins/store/firebird $src_dir/projects/stargazer
+./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stg3plugins max_mods/mysql $src_dir/projects/stargazer/plugins/store
+mv $src_dir/projects/stargazer/plugins/store/max_mods/mysql $src_dir/projects/stargazer/plugins/store/
+rm -rf $src_dir/projects/stargazer/plugins/store/max_mods
+rm -rf $src_dir/projects/stargazer/plugins/other/userstat
+rm -rf $src_dir/projects/stargazer/plugins/authorization/stress
+rm -rf $src_dir/projects/stargazer/plugins/store/db
+rm -rf $src_dir/projects/stargazer/plugins/configuration/rpcconfig
+
+rm -f $src_dir/include/lp2_blocks.h
+rm -f $src_dir/include/stdstring.h
+
+mkdir -p $src_dir/lib
+
+rm -fr $(find $src_dir/ -name CVS -type d)
+
+rm -fr $src_dir/projects/stargazer/inst/var/stargazer/users/CVS
+
+tar -czf $arc_name $src_dir
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.5 2009/03/03 15:49:34 faust Exp $
+###############################################################################
+
+include ../../Makefile.conf
+
+LIB_NAME = rlm_stg
+
+PROG = $(LIB_NAME).so
+
+SRCS = ./rlm_stg.cpp \
+ ./stg_client.cpp
+
+STGLIBS = -lstg_common \
+ -lstg_crypto
+
+LIBS += $(LIB_THREAD)
+
+ifeq ($(OS),linux)
+LIBS += -ldl
+else
+LIBS += -lintl \
+ -lc
+endif
+
+SEARCH_DIRS = -I $(DIR_INCLUDE)
+
+OBJS = $(notdir $(patsubst %.cpp, %.o, $(patsubst %.c, %.o, $(SRCS))))
+
+CXXFLAGS += -Wall -fPIC -I./
+LDFLAGS += -shared -L$(DIR_LIB) -Wl,-rpath,$(PREFIX)/usr/lib/stg
+
+vpath %.so $(DIR_LIB)
+
+.PHONY: all clean distclean libs install uninstall install-bin uninstall-bin
+all: libs $(PROG) ../../Makefile.conf
+
+libs:
+ $(MAKE) -C $(DIR_LIBSRC)
+
+$(PROG): $(OBJS) $(STGLIBS)
+ $(CC) $^ $(LDFLAGS) -o $(PROG) $(LIBS)
+
+clean:
+ rm -f deps $(PROG) *.o tags *.*~ .OS
+ rm -f .OS
+ rm -f core*
+ $(MAKE) -C $(DIR_LIBSRC) clean
+
+distclean: clean
+ rm -f ../../Makefile.conf
+
+install: install-bin
+
+install-bin:
+ mkdir -m $(BIN_MODE) -p $(PREFIX)/usr/lib
+ install -m $(BIN_MODE) -o $(OWNER) -s $(PROG) $(PREFIX)/usr/lib/$(PROG)
+ $(MAKE) -C $(DIR_LIBSRC) install
+
+uninstall: uninstall-bin
+
+uninstall-bin:
+ rm -f $(PREFIX)/usr/sbin/$(PROG)
+
+ifneq ($(MAKECMDGOALS),distclean)
+ifneq ($(MAKECMDGOALS),clean)
+ifneq ($(MAKECMDGOALS),uninstall)
+-include deps
+endif
+endif
+endif
+
+deps: $(SRCS) ../../Makefile.conf
+ $(MAKE) -C $(DIR_LIBSRC) includes
+ @>deps ;\
+ for file in $(SRCS); do\
+ echo "`$(CC) $(CXXFLAGS) $(SEARCH_DIRS) -MM $$file` Makefile" >> deps ;\
+ echo -e '\t$$(CC) -c $$< $(CXXFLAGS) $(SEARCH_DIRS) $(DEFS)' >> deps ;\
+ done
+
+
--- /dev/null
+#!/bin/sh
+
+# $Author: faust $
+# $Revision: 1.13 $
+# $Date: 2010/04/14 08:58:44 $
+######################################################
+
+OS=unknown
+sys=`uname -s`
+release=`uname -r | cut -b1`
+BUILD_DIR=`pwd`
+CONFFILE="../../Makefile.conf"
+PREFIX="/"
+BIN_MODE=0755
+OWNER=root
+
+if [ -z $1 ]
+then
+ MAKEOPTS="-j1"
+else
+ if [ "$1" = "debug" ]
+ then
+ DEFS="-DDEBUG"
+ MAKEOPTS="-j1"
+ CXXFLAGS="$CXXFLAGS -g3 -W -Wall"
+ else
+ MAKEOPTS="-j1"
+ fi
+fi
+
+CXXFLAGS="$CXXFLAGS -I/usr/local/include"
+LDFLAGS="$LDFLAGS -L/usr/local/lib"
+
+if [ "$sys" = "Linux" ]
+then
+ OS=linux
+ release=""
+ MAKE="make"
+fi
+
+if [ "$sys" = "FreeBSD" ]
+then
+ case $release in
+ 4) OS=bsd;;
+ 5) OS=bsd5;;
+ 6) OS=bsd5;;
+ 7) OS=bsd7;;
+ 8) OS=bsd7;;
+ *) OS=unknown;;
+ esac
+ MAKE="gmake"
+fi
+
+if [ "$OS" = "unknown" ]
+then
+ echo "#############################################################################"
+ echo "# Sorry, but rlm_stg currently supported by Linux, FreeBSD 4.x, 5.x, 6.x #"
+ echo "#############################################################################"
+ exit 1
+fi
+
+echo "#############################################################################"
+echo " Building rlm_stg for $sys $release"
+echo "#############################################################################"
+
+STG_LIBS="crypto.lib common.lib"
+
+if [ "$OS" = "linux" ]
+then
+ DEFS="$DEFS -DLINUX"
+ LIB_THREAD=-lpthread
+ SHELL="/bin/bash"
+else
+ if [ "$OS" = "bsd" ]
+ then
+ DEFS="$DEFS -DFREE_BSD"
+ else
+ DEFS="$DEFS -DFREE_BSD5"
+ if [ "$OS" = "bsd7" ]
+ then
+ LIB_THREAD=-lpthread
+ else
+ LIB_THREAD=-lc_r
+ fi
+ fi
+ SHELL="/usr/local/bin/bash"
+fi
+
+echo -n "Checking endianess... "
+echo "int main() { int probe = 0x00000001; return *(char *)&probe; }" > build_check.c
+gcc $CXXFLAGS $LDFLAGS build_check.c -o fake > /dev/null 2> /dev/null
+if [ $? != 0 ]
+then
+ echo "FAIL!"
+ echo "Endianess checking failed"
+ exit;
+else
+ ./fake
+ if [ $? = 1 ]
+ then
+ ARCH=le
+ CXXFLAGS="$CXXFLAGS -DARCH_LE"
+ echo "Little Endian"
+ else
+ ARCH=be
+ CXXFLAGS="$CXXFLAGS -DARCH_BE"
+ echo "Big Endian"
+ fi
+fi
+rm -f fake
+
+echo "OS=$OS" > $CONFFILE
+echo "STG_TIME=yes" >> $CONFFILE
+echo "DIR_BUILD=$BUILD_DIR" >> $CONFFILE
+echo "DIR_LIB=\$(DIR_BUILD)/../../lib" >> $CONFFILE
+echo "DIR_LIBSRC=\$(DIR_BUILD)/../../stglibs" >> $CONFFILE
+echo "DIR_INCLUDE=\$(DIR_BUILD)/../../include" >> $CONFFILE
+echo "ARCH=$ARCH" >> $CONFFILE
+echo "DEFS=$DEFS" >> $CONFFILE
+echo -n "STG_LIBS=" >> $CONFFILE
+for lib in $STG_LIBS
+do
+ echo -n "$lib " >> $CONFFILE
+done
+echo "" >> $CONFFILE
+echo "CXXFLAGS=$CXXFLAGS" >> $CONFFILE
+echo "LDFLAGS=$LDFLAGS" >> $CONFFILE
+echo "LIB_THREAD=$LIB_THREAD" >> $CONFFILE
+echo "PREFIX=$PREFIX" >> $CONFFILE
+echo "BIN_MODE=$BIN_MODE" >> $CONFFILE
+echo "DATA_MODE=$DATA_MODE" >> $CONFFILE
+echo "OWNER=$OWNER" >> $CONFFILE
+echo "SHELL=$SHELL" >> $CONFFILE
+$MAKE $MAKEOPTS
+
--- /dev/null
+int main() { int probe = 0x00000001; return *(char *)&probe; }
--- /dev/null
+/* Default Database File Names */
+
+#define RADIUS_DIR RADDBDIR
+#define RADACCT_DIR RADIR
+#define RADLOG_DIR LOGDIR
+
+#define RADIUS_DICTIONARY "dictionary"
+#define RADIUS_CLIENTS "clients"
+#define RADIUS_NASLIST "naslist"
+#define RADIUS_REALMS "realms"
+
+#define RADUTMP LOGDIR "/radutmp"
+#define SRADUTMP LOGDIR "/sradutmp"
+#define RADWTMP LOGDIR "/radwtmp"
+#define SRADWTMP LOGDIR "/sradwtmp"
+
+/* Hack for funky ascend ports on MAX 4048 (and probably others)
+ The "NAS-Port-Id" value is "xyyzz" where "x" = 1 for digital, 2 for analog;
+ "yy" = line number (1 for first PRI/T1/E1, 2 for second, so on);
+ "zz" = channel number (on the PRI or Channelized T1/E1).
+ This should work with normal terminal servers, unless you have a TS with
+ more than 9999 ports ;^).
+ The "ASCEND_CHANNELS_PER_LINE" is the number of channels for each line into
+ the unit. For my US/PRI that's 23. A US/T1 would be 24, and a
+ European E1 would be 30 (I think ... never had one ;^).
+ This will NOT change the "NAS-Port-Id" reported in the detail log. This
+ is simply to fix the dynamic IP assignments a la Cistron.
+ You can change the default of 23 with an argument to ./configure.
+ WARNING: This hack works for me, but I only have one PRI!!! I've not
+ tested it on 2 or more (or with models other than the Max 4048)
+ Use at your own risk!
+ -- dgreer@austintx.com
+*/
+#ifdef ASCEND_PORT_HACK
+# ifndef ASCEND_CHANNELS_PER_LINE
+# define ASCEND_CHANNELS_PER_LINE 23
+# endif
+#endif
--- /dev/null
+#ifndef _CONFFILE_H
+#define _CONFFILE_H
+
+/*
+ * conffile.h Defines for the conffile parsing routines.
+ *
+ * Version: $Id: conffile.h,v 1.1 2010/08/14 04:13:52 faust Exp $
+ *
+ */
+
+#include <freeradius/ident.h>
+RCSIDH(conffile_h, "$Id: conffile.h,v 1.1 2010/08/14 04:13:52 faust Exp $")
+
+#include <stddef.h>
+#include <freeradius/token.h>
+
+/*
+ * Export the minimum amount of information about these structs
+ */
+typedef struct conf_item CONF_ITEM;
+typedef struct conf_pair CONF_PAIR;
+typedef struct conf_part CONF_SECTION;
+typedef struct conf_data CONF_DATA;
+
+/*
+ * Instead of putting the information into a configuration structure,
+ * the configuration file routines MAY just parse it directly into
+ * user-supplied variables.
+ */
+#define PW_TYPE_STRING_PTR 100
+#define PW_TYPE_BOOLEAN 101
+#define PW_TYPE_SUBSECTION 102
+#define PW_TYPE_FILENAME 103
+
+typedef struct CONF_PARSER {
+ const char *name;
+ int type; /* PW_TYPE_STRING, etc. */
+ size_t offset; /* relative pointer within "base" */
+ void *data; /* absolute pointer if base is NULL */
+ const char *dflt; /* default as it would appear in radiusd.conf */
+} CONF_PARSER;
+
+/* This preprocessor trick will be useful in initializing CONF_PARSER struct */
+#define XStringify(x) #x
+#define Stringify(x) XStringify(x)
+
+void cf_pair_free(CONF_PAIR **cp);
+int cf_pair_replace(CONF_SECTION *cs, CONF_PAIR *cp,
+ const char *value);
+void cf_section_free(CONF_SECTION **cp);
+int cf_item_parse(CONF_SECTION *cs, const char *name,
+ int type, void *data, const char *dflt);
+int cf_section_parse(CONF_SECTION *, void *base,
+ const CONF_PARSER *variables);
+void cf_section_parse_free(CONF_SECTION *cs, void *base);
+const CONF_PARSER *cf_section_parse_table(CONF_SECTION *cs);
+CONF_SECTION *cf_file_read(const char *file);
+int cf_file_include(const char *file, CONF_SECTION *cs);
+
+CONF_PAIR *cf_pair_find(const CONF_SECTION *, const char *name);
+CONF_PAIR *cf_pair_find_next(const CONF_SECTION *, CONF_PAIR *, const char *name);
+CONF_SECTION *cf_section_find(const char *name);
+CONF_SECTION *cf_section_sub_find(const CONF_SECTION *, const char *name);
+CONF_SECTION *cf_section_sub_find_name2(const CONF_SECTION *, const char *name1, const char *name2);
+const char *cf_section_value_find(const CONF_SECTION *, const char *attr);
+CONF_SECTION *cf_top_section(CONF_SECTION *cs);
+
+void *cf_data_find(CONF_SECTION *, const char *);
+int cf_data_add(CONF_SECTION *, const char *, void *, void (*)(void *));
+
+const char *cf_pair_attr(CONF_PAIR *pair);
+const char *cf_pair_value(CONF_PAIR *pair);
+VALUE_PAIR *cf_pairtovp(CONF_PAIR *pair);
+const char *cf_section_name1(const CONF_SECTION *);
+const char *cf_section_name2(const CONF_SECTION *);
+int dump_config(CONF_SECTION *cs);
+CONF_SECTION *cf_subsection_find_next(CONF_SECTION *section,
+ CONF_SECTION *subsection,
+ const char *name1);
+CONF_SECTION *cf_section_find_next(CONF_SECTION *section,
+ CONF_SECTION *subsection,
+ const char *name1);
+int cf_section_lineno(CONF_SECTION *section);
+int cf_pair_lineno(CONF_PAIR *pair);
+const char *cf_pair_filename(CONF_PAIR *pair);
+const char *cf_section_filename(CONF_SECTION *section);
+CONF_ITEM *cf_item_find_next(CONF_SECTION *section, CONF_ITEM *item);
+int cf_item_is_section(CONF_ITEM *item);
+int cf_item_is_pair(CONF_ITEM *item);
+CONF_PAIR *cf_itemtopair(CONF_ITEM *item);
+CONF_SECTION *cf_itemtosection(CONF_ITEM *item);
+CONF_ITEM *cf_pairtoitem(CONF_PAIR *cp);
+CONF_ITEM *cf_sectiontoitem(CONF_SECTION *cs);
+int cf_section_template(CONF_SECTION *cs, CONF_SECTION *_template);
+void cf_log_err(CONF_ITEM *ci, const char *fmt, ...)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 2, 3)))
+#endif
+;
+void cf_log_info(CONF_SECTION *cs, const char *fmt, ...)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 2, 3)))
+#endif
+;
+void cf_log_module(CONF_SECTION *cs, const char *fmt, ...)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 2, 3)))
+#endif
+;
+CONF_ITEM *cf_reference_item(const CONF_SECTION *parentcs,
+ CONF_SECTION *outercs,
+ const char *ptr);
+extern int cf_log_config;
+extern int cf_log_modules;
+
+extern int cf_pair2xml(FILE *fp, CONF_PAIR *cp);
+extern int cf_section2xml(FILE *fp, CONF_SECTION *cs);
+extern int cf_pair2file(FILE *fp, CONF_PAIR *cp);
+extern int cf_section2file(FILE *fp, CONF_SECTION *cs);
+
+/*
+ * Big magic.
+ */
+int cf_section_migrate(CONF_SECTION *dst, CONF_SECTION *src);
+
+#endif /* _CONFFILE_H */
--- /dev/null
+#ifndef FR_EVENT_H
+#define FR_EVENT_H
+
+/*
+ * event.h Simple event queue
+ *
+ * Version: $Id: event.h,v 1.1 2010/08/14 04:13:52 faust Exp $
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2007 The FreeRADIUS server project
+ * Copyright 2007 Alan DeKok <aland@deployingradius.com>
+ */
+
+#include <freeradius/ident.h>
+RCSIDH(event_h, "$Id: event.h,v 1.1 2010/08/14 04:13:52 faust Exp $")
+
+typedef struct fr_event_list_t fr_event_list_t;
+typedef struct fr_event_t fr_event_t;
+
+typedef void (*fr_event_callback_t)(void *);
+typedef void (*fr_event_status_t)(struct timeval *);
+typedef void (*fr_event_fd_handler_t)(fr_event_list_t *el, int sock, void *ctx);
+
+fr_event_list_t *fr_event_list_create(fr_event_status_t status);
+void fr_event_list_free(fr_event_list_t *el);
+
+int fr_event_list_num_elements(fr_event_list_t *el);
+
+int fr_event_insert(fr_event_list_t *el,
+ fr_event_callback_t callback,
+ void *ctx, struct timeval *when, fr_event_t **ev_p);
+int fr_event_delete(fr_event_list_t *el, fr_event_t **ev_p);
+
+int fr_event_run(fr_event_list_t *el, struct timeval *when);
+
+int fr_event_now(fr_event_list_t *el, struct timeval *when);
+
+int fr_event_fd_insert(fr_event_list_t *el, int type, int fd,
+ fr_event_fd_handler_t handler, void *ctx);
+int fr_event_fd_delete(fr_event_list_t *el, int type, int fd);
+int fr_event_loop(fr_event_list_t *el);
+void fr_event_loop_exit(fr_event_list_t *el, int code);
+
+#endif /* FR_HASH_H */
--- /dev/null
+#ifndef LIBRADIUS_H
+#define LIBRADIUS_H
+
+/*
+ * libradius.h Structures and prototypes
+ * for the radius library.
+ *
+ * Version: $Id: libradius.h,v 1.1 2010/08/14 04:13:52 faust Exp $
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008 The FreeRADIUS server project
+ */
+
+#include <freeradius/ident.h>
+RCSIDH(libradius_h, "$Id: libradius.h,v 1.1 2010/08/14 04:13:52 faust Exp $")
+
+#include <errno.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include "os_int.h"
+
+#include <netinet/in.h>
+#include <sys/socket.h>
+
+#include <freeradius/radius.h>
+#include <freeradius/token.h>
+#include <freeradius/hash.h>
+
+#ifdef SIZEOF_UNSIGNED_INT
+#if SIZEOF_UNSIGNED_INT != 4
+#error FATAL: sizeof(unsigned int) != 4
+#endif
+#endif
+
+/*
+ * Include for modules.
+ */
+#include <freeradius/sha1.h>
+#include <freeradius/md4.h>
+
+#define EAP_START 2
+
+#define AUTH_VECTOR_LEN 16
+#define CHAP_VALUE_LENGTH 16
+#define MAX_STRING_LEN 254 /* RFC2138: string 0-253 octets */
+
+# define VENDOR(x) ((x >> 16) & 0xffff)
+
+#ifdef _LIBRADIUS
+# define AUTH_HDR_LEN 20
+# define VENDORPEC_USR 429
+#define VENDORPEC_LUCENT 4846
+#define VENDORPEC_STARENT 8164
+# define DEBUG if (fr_debug_flag && fr_log_fp) fr_printf_log
+# define debug_pair(vp) do { if (fr_debug_flag && fr_log_fp) { \
+ fputc('\t', fr_log_fp); \
+ vp_print(fr_log_fp, vp); \
+ fputc('\n', fr_log_fp); \
+ } \
+ } while(0)
+# define TAG_VALID(x) ((x) > 0 && (x) < 0x20)
+# define TAG_VALID_ZERO(x) ((x) < 0x20)
+# define TAG_ANY -128 /* minimum signed char */
+#endif
+
+#if defined(__GNUC__)
+# define PRINTF_LIKE(n) __attribute__ ((format(printf, n, n+1)))
+# define NEVER_RETURNS __attribute__ ((noreturn))
+# define UNUSED __attribute__ ((unused))
+# define BLANK_FORMAT " " /* GCC_LINT whines about empty formats */
+#else
+# define PRINTF_LIKE(n) /* ignore */
+# define NEVER_RETURNS /* ignore */
+# define UNUSED /* ignore */
+# define BLANK_FORMAT ""
+#endif
+
+typedef struct attr_flags {
+ unsigned int addport : 1; /* add NAS-Port to IP address */
+ unsigned int has_tag : 1; /* tagged attribute */
+ unsigned int do_xlat : 1; /* strvalue is dynamic */
+ unsigned int unknown_attr : 1; /* not in dictionary */
+ unsigned int array : 1; /* pack multiples into 1 attr */
+ unsigned int has_value : 1; /* has a value */
+ unsigned int has_value_alias : 1; /* has a value alias */
+ unsigned int has_tlv : 1; /* has sub attributes */
+ unsigned int is_tlv : 1; /* is a sub attribute */
+ unsigned int encoded : 1; /* has been put into packet */
+
+ int8_t tag; /* tag for tunneled attributes */
+ uint8_t encrypt; /* encryption method */
+} ATTR_FLAGS;
+
+/*
+ * Values of the encryption flags.
+ */
+#define FLAG_ENCRYPT_NONE (0)
+#define FLAG_ENCRYPT_USER_PASSWORD (1)
+#define FLAG_ENCRYPT_TUNNEL_PASSWORD (2)
+#define FLAG_ENCRYPT_ASCEND_SECRET (3)
+
+typedef struct dict_attr {
+ unsigned int attr;
+ int type;
+ int vendor;
+ ATTR_FLAGS flags;
+ char name[1];
+} DICT_ATTR;
+
+typedef struct dict_value {
+ unsigned int attr;
+ int value;
+ char name[1];
+} DICT_VALUE;
+
+typedef struct dict_vendor {
+ int vendorpec;
+ int type; /* length of type data */
+ int length; /* length of length data */
+ int flags;
+ char name[1];
+} DICT_VENDOR;
+
+typedef union value_pair_data {
+ char strvalue[MAX_STRING_LEN];
+ uint8_t octets[MAX_STRING_LEN];
+ struct in_addr ipaddr;
+ struct in6_addr ipv6addr;
+ uint32_t date;
+ uint32_t integer;
+ int32_t sinteger;
+ uint8_t filter[32];
+ uint8_t ifid[8]; /* struct? */
+ uint8_t ipv6prefix[18]; /* struct? */
+ uint8_t ether[6];
+ uint8_t *tlv;
+} VALUE_PAIR_DATA;
+
+typedef struct value_pair {
+ const char *name;
+ int attribute;
+ int vendor;
+ int type;
+ size_t length; /* of data */
+ FR_TOKEN _operator;
+ ATTR_FLAGS flags;
+ struct value_pair *next;
+ uint32_t lvalue;
+ VALUE_PAIR_DATA data;
+} VALUE_PAIR;
+#define vp_strvalue data.strvalue
+#define vp_octets data.octets
+#define vp_ipv6addr data.ipv6addr
+#define vp_ifid data.ifid
+#define vp_ipv6prefix data.ipv6prefix
+#define vp_filter data.filter
+#define vp_ether data.ether
+#define vp_signed data.sinteger
+#define vp_tlv data.tlv
+
+#if 0
+#define vp_ipaddr data.ipaddr.s_addr
+#define vp_date data.date
+#define vp_integer data.integer
+#else
+/*
+ * These are left as lvalue until we audit the source for code
+ * that prints to vp_strvalue for integer/ipaddr/date types.
+ */
+#define vp_ipaddr lvalue
+#define vp_date lvalue
+#define vp_integer lvalue
+#endif
+
+
+typedef struct fr_ipaddr_t {
+ int af; /* address family */
+ union {
+ struct in_addr ip4addr;
+ struct in6_addr ip6addr; /* maybe defined in missing.h */
+ } ipaddr;
+} fr_ipaddr_t;
+
+/*
+ * vector: Request authenticator from access-request packet
+ * Put in there by rad_decode, and must be put in the
+ * response RADIUS_PACKET as well before calling rad_send
+ *
+ * verified: Filled in by rad_decode for accounting-request packets
+ *
+ * data,data_len: Used between rad_recv and rad_decode.
+ */
+typedef struct radius_packet {
+ int sockfd;
+ fr_ipaddr_t src_ipaddr;
+ fr_ipaddr_t dst_ipaddr;
+ uint16_t src_port;
+ uint16_t dst_port;
+ int id;
+ unsigned int code;
+ uint32_t hash;
+ uint8_t vector[AUTH_VECTOR_LEN];
+ time_t timestamp;
+ uint8_t *data;
+ int data_len;
+ VALUE_PAIR *vps;
+ ssize_t offset;
+} RADIUS_PACKET;
+
+/*
+ * Printing functions.
+ */
+int fr_utf8_char(const uint8_t *str);
+void fr_print_string(const char *in, size_t inlen,
+ char *out, size_t outlen);
+int vp_prints_value(char *out, size_t outlen,
+ VALUE_PAIR *vp, int delimitst);
+const char *vp_print_name(char *buffer, size_t bufsize, int attr);
+int vp_prints(char *out, size_t outlen, VALUE_PAIR *vp);
+void vp_print(FILE *, VALUE_PAIR *);
+void vp_printlist(FILE *, VALUE_PAIR *);
+#define fprint_attr_val vp_print
+
+/*
+ * Dictionary functions.
+ */
+int dict_addvendor(const char *name, int value);
+int dict_addattr(const char *name, int vendor, int type, int value, ATTR_FLAGS flags);
+int dict_addvalue(const char *namestr, const char *attrstr, int value);
+int dict_init(const char *dir, const char *fn);
+void dict_free(void);
+DICT_ATTR *dict_attrbyvalue(unsigned int attr);
+DICT_ATTR *dict_attrbyname(const char *attr);
+DICT_VALUE *dict_valbyattr(unsigned int attr, int val);
+DICT_VALUE *dict_valbyname(unsigned int attr, const char *val);
+int dict_vendorbyname(const char *name);
+DICT_VENDOR *dict_vendorbyvalue(int vendor);
+
+#if 1 /* FIXME: compat */
+#define dict_attrget dict_attrbyvalue
+#define dict_attrfind dict_attrbyname
+#define dict_valfind dict_valbyname
+/*#define dict_valget dict_valbyattr almost but not quite*/
+#endif
+
+/* get around diffrent ctime_r styles */
+#ifdef CTIMERSTYLE
+#if CTIMERSTYLE == SOLARISSTYLE
+#define CTIME_R(a,b,c) ctime_r(a,b,c)
+#else
+#define CTIME_R(a,b,c) ctime_r(a,b)
+#endif
+#else
+#define CTIME_R(a,b,c) ctime_r(a,b)
+#endif
+
+/* md5.c */
+
+void fr_md5_calc(uint8_t *, const uint8_t *, unsigned int);
+
+/* hmac.c */
+
+void fr_hmac_md5(const uint8_t *text, int text_len,
+ const uint8_t *key, int key_len,
+ unsigned char *digest);
+
+/* hmacsha1.c */
+
+void fr_hmac_sha1(const uint8_t *text, int text_len,
+ const uint8_t *key, int key_len,
+ uint8_t *digest);
+
+/* radius.c */
+int rad_send(RADIUS_PACKET *, const RADIUS_PACKET *, const char *secret);
+int rad_packet_ok(RADIUS_PACKET *packet, int flags);
+RADIUS_PACKET *rad_recv(int fd, int flags);
+ssize_t rad_recv_header(int sockfd, fr_ipaddr_t *src_ipaddr, int *src_port,
+ int *code);
+void rad_recv_discard(int sockfd);
+int rad_verify(RADIUS_PACKET *packet, RADIUS_PACKET *original,
+ const char *secret);
+int rad_decode(RADIUS_PACKET *packet, RADIUS_PACKET *original, const char *secret);
+int rad_encode(RADIUS_PACKET *packet, const RADIUS_PACKET *original,
+ const char *secret);
+int rad_sign(RADIUS_PACKET *packet, const RADIUS_PACKET *original,
+ const char *secret);
+
+RADIUS_PACKET *rad_alloc(int newvector);
+RADIUS_PACKET *rad_alloc_reply(RADIUS_PACKET *);
+void rad_free(RADIUS_PACKET **);
+int rad_pwencode(char *encpw, size_t *len, const char *secret,
+ const uint8_t *vector);
+int rad_pwdecode(char *encpw, size_t len, const char *secret,
+ const uint8_t *vector);
+int rad_tunnel_pwencode(char *encpw, size_t *len, const char *secret,
+ const uint8_t *vector);
+int rad_tunnel_pwdecode(uint8_t *encpw, size_t *len,
+ const char *secret, const uint8_t *vector);
+int rad_chap_encode(RADIUS_PACKET *packet, uint8_t *output,
+ int id, VALUE_PAIR *password);
+VALUE_PAIR *rad_attr2vp(const RADIUS_PACKET *packet, const RADIUS_PACKET *original,
+ const char *secret, int attribute, int length,
+ const uint8_t *data);
+int rad_vp2attr(const RADIUS_PACKET *packet,
+ const RADIUS_PACKET *original, const char *secret,
+ const VALUE_PAIR *vp, uint8_t *ptr);
+
+/* valuepair.c */
+VALUE_PAIR *pairalloc(DICT_ATTR *da);
+VALUE_PAIR *paircreate(int attr, int type);
+void pairfree(VALUE_PAIR **);
+void pairbasicfree(VALUE_PAIR *pair);
+VALUE_PAIR *pairfind(VALUE_PAIR *, int);
+void pairdelete(VALUE_PAIR **, int);
+void pairadd(VALUE_PAIR **, VALUE_PAIR *);
+void pairreplace(VALUE_PAIR **first, VALUE_PAIR *add);
+int paircmp(VALUE_PAIR *check, VALUE_PAIR *data);
+VALUE_PAIR *paircopyvp(const VALUE_PAIR *vp);
+VALUE_PAIR *paircopy(VALUE_PAIR *vp);
+VALUE_PAIR *paircopy2(VALUE_PAIR *vp, int attr);
+void pairmove(VALUE_PAIR **to, VALUE_PAIR **from);
+void pairmove2(VALUE_PAIR **to, VALUE_PAIR **from, int attr);
+VALUE_PAIR *pairparsevalue(VALUE_PAIR *vp, const char *value);
+VALUE_PAIR *pairmake(const char *attribute, const char *value, int _operator);
+VALUE_PAIR *pairread(const char **ptr, FR_TOKEN *eol);
+FR_TOKEN userparse(const char *buffer, VALUE_PAIR **first_pair);
+VALUE_PAIR *readvp2(FILE *fp, int *pfiledone, const char *errprefix);
+
+/*
+ * Error functions.
+ */
+#ifdef _LIBRADIUS
+void fr_strerror_printf(const char *, ...)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 1, 2)))
+#endif
+;
+#endif
+void fr_perror(const char *, ...)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 1, 2)))
+#endif
+;
+extern const char *fr_strerror(void);
+extern int fr_dns_lookups; /* 0 = no dns lookups */
+extern int fr_debug_flag; /* 0 = no debugging information */
+extern int fr_max_attributes; /* per incoming packet */
+#define FR_MAX_PACKET_CODE (52)
+extern const char *fr_packet_codes[FR_MAX_PACKET_CODE];
+extern FILE *fr_log_fp;
+void fr_printf_log(const char *, ...)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 1, 2)))
+#endif
+;
+
+/*
+ * Several handy miscellaneous functions.
+ */
+const char * ip_ntoa(char *, uint32_t);
+char *ifid_ntoa(char *buffer, size_t size, uint8_t *ifid);
+uint8_t *ifid_aton(const char *ifid_str, uint8_t *ifid);
+int rad_lockfd(int fd, int lock_len);
+int rad_lockfd_nonblock(int fd, int lock_len);
+int rad_unlockfd(int fd, int lock_len);
+void fr_bin2hex(const uint8_t *bin, char *hex, size_t len);
+size_t fr_hex2bin(const char *hex, uint8_t *bin, size_t len);
+#ifndef HAVE_CLOSEFROM
+int closefrom(int fd);
+#endif
+int fr_ipaddr_cmp(const fr_ipaddr_t *a, const fr_ipaddr_t *b);
+
+int ip_hton(const char *src, int af, fr_ipaddr_t *dst);
+const char *ip_ntoh(const fr_ipaddr_t *src, char *dst, size_t cnt);
+int fr_ipaddr2sockaddr(const fr_ipaddr_t *ipaddr, int port,
+ struct sockaddr_storage *sa, socklen_t *salen);
+int fr_sockaddr2ipaddr(const struct sockaddr_storage *sa, socklen_t salen,
+ fr_ipaddr_t *ipaddr, int * port);
+
+
+#ifdef ASCEND_BINARY
+/* filters.c */
+int ascend_parse_filter(VALUE_PAIR *pair);
+void print_abinary(VALUE_PAIR *vp, char *buffer, size_t len);
+#endif /*ASCEND_BINARY*/
+
+/* random numbers in isaac.c */
+/* context of random number generator */
+typedef struct fr_randctx {
+ uint32_t randcnt;
+ uint32_t randrsl[256];
+ uint32_t randmem[256];
+ uint32_t randa;
+ uint32_t randb;
+ uint32_t randc;
+} fr_randctx;
+
+void fr_isaac(fr_randctx *ctx);
+void fr_randinit(fr_randctx *ctx, int flag);
+uint32_t fr_rand(void); /* like rand(), but better. */
+void fr_rand_seed(const void *, size_t ); /* seed the random pool */
+
+
+/* crypt wrapper from crypt.c */
+int fr_crypt_check(const char *key, const char *salt);
+
+/* rbtree.c */
+typedef struct rbtree_t rbtree_t;
+typedef struct rbnode_t rbnode_t;
+
+rbtree_t *rbtree_create(int (*Compare)(const void *, const void *),
+ void (*freeNode)(void *),
+ int replace_flag);
+void rbtree_free(rbtree_t *tree);
+int rbtree_insert(rbtree_t *tree, void *Data);
+rbnode_t *rbtree_insertnode(rbtree_t *tree, void *Data);
+void rbtree_delete(rbtree_t *tree, rbnode_t *Z);
+int rbtree_deletebydata(rbtree_t *tree, const void *data);
+rbnode_t *rbtree_find(rbtree_t *tree, const void *Data);
+void *rbtree_finddata(rbtree_t *tree, const void *Data);
+int rbtree_num_elements(rbtree_t *tree);
+void *rbtree_min(rbtree_t *tree);
+void *rbtree_node2data(rbtree_t *tree, rbnode_t *node);
+
+/* callback order for walking */
+typedef enum { PreOrder, InOrder, PostOrder } RBTREE_ORDER;
+
+/*
+ * The callback should be declared as:
+ * int callback(void *context, void *data)
+ *
+ * The "context" is some user-defined context.
+ * The "data" is the pointer to the user data in the node,
+ * NOT the node itself.
+ *
+ * It should return 0 if all is OK, and !0 for any error.
+ * The walking will stop on any error.
+ */
+int rbtree_walk(rbtree_t *tree, RBTREE_ORDER order, int (*callback)(void *, void *), void *context);
+
+/*
+ * FIFOs
+ */
+typedef struct fr_fifo_t fr_fifo_t;
+typedef void (*fr_fifo_free_t)(void *);
+fr_fifo_t *fr_fifo_create(int max_entries, fr_fifo_free_t freeNode);
+void fr_fifo_free(fr_fifo_t *fi);
+int fr_fifo_push(fr_fifo_t *fi, void *data);
+void *fr_fifo_pop(fr_fifo_t *fi);
+void *fr_fifo_peek(fr_fifo_t *fi);
+int fr_fifo_num_elements(fr_fifo_t *fi);
+
+#include <freeradius/packet.h>
+
+#endif /*LIBRADIUS_H*/
--- /dev/null
+/*
+ * module.h Interface to the RADIUS module system.
+ *
+ * Version: $Id: modules.h,v 1.1 2010/08/14 04:13:52 faust Exp $
+ *
+ */
+
+#ifndef RADIUS_MODULES_H
+#define RADIUS_MODULES_H
+
+#include <freeradius/ident.h>
+RCSIDH(modules_h, "$Id: modules.h,v 1.1 2010/08/14 04:13:52 faust Exp $")
+
+#include "conffile.h"
+
+typedef int (*packetmethod)(void *instance, REQUEST *request);
+
+enum {
+ RLM_COMPONENT_AUTH = 0,
+ RLM_COMPONENT_AUTZ, /* 1 */
+ RLM_COMPONENT_PREACCT, /* 2 */
+ RLM_COMPONENT_ACCT, /* 3 */
+ RLM_COMPONENT_SESS, /* 4 */
+ RLM_COMPONENT_PRE_PROXY, /* 5 */
+ RLM_COMPONENT_POST_PROXY, /* 6 */
+ RLM_COMPONENT_POST_AUTH, /* 7 */
+#ifdef WITH_COA
+ RLM_COMPONENT_RECV_COA, /* 8 */
+ RLM_COMPONENT_SEND_COA, /* 9 */
+#endif
+ RLM_COMPONENT_COUNT /* 8 / 10: How many components are there */
+};
+
+#define RLM_TYPE_THREAD_SAFE (0 << 0)
+#define RLM_TYPE_THREAD_UNSAFE (1 << 0)
+#define RLM_TYPE_CHECK_CONFIG_SAFE (1 << 1)
+#define RLM_TYPE_HUP_SAFE (1 << 2)
+
+#define RLM_MODULE_MAGIC_NUMBER ((uint32_t) (0xf4ee4ad2))
+#define RLM_MODULE_INIT RLM_MODULE_MAGIC_NUMBER
+
+typedef struct module_t {
+ uint32_t magic; /* may later be opaque struct */
+ const char *name;
+ int type;
+ int (*instantiate)(CONF_SECTION *mod_cs, void **instance);
+ int (*detach)(void *instance);
+ packetmethod methods[RLM_COMPONENT_COUNT];
+} module_t;
+
+enum {
+ RLM_MODULE_REJECT, /* immediately reject the request */
+ RLM_MODULE_FAIL, /* module failed, don't reply */
+ RLM_MODULE_OK, /* the module is OK, continue */
+ RLM_MODULE_HANDLED, /* the module handled the request, so stop. */
+ RLM_MODULE_INVALID, /* the module considers the request invalid. */
+ RLM_MODULE_USERLOCK, /* reject the request (user is locked out) */
+ RLM_MODULE_NOTFOUND, /* user not found */
+ RLM_MODULE_NOOP, /* module succeeded without doing anything */
+ RLM_MODULE_UPDATED, /* OK (pairs modified) */
+ RLM_MODULE_NUMCODES /* How many return codes there are */
+};
+
+int setup_modules(int, CONF_SECTION *);
+int detach_modules(void);
+int module_hup(CONF_SECTION *modules);
+int module_authorize(int type, REQUEST *request);
+int module_authenticate(int type, REQUEST *request);
+int module_preacct(REQUEST *request);
+int module_accounting(int type, REQUEST *request);
+int module_checksimul(int type, REQUEST *request, int maxsimul);
+int module_pre_proxy(int type, REQUEST *request);
+int module_post_proxy(int type, REQUEST *request);
+int module_post_auth(int type, REQUEST *request);
+#ifdef WITH_COA
+int module_recv_coa(int type, REQUEST *request);
+int module_send_coa(int type, REQUEST *request);
+#define MODULE_NULL_COA_FUNCS ,NULL,NULL
+#else
+#define MODULE_NULL_COA_FUNCS
+#endif
+int indexed_modcall(int comp, int idx, REQUEST *request);
+
+/*
+ * For now, these are strongly tied together.
+ */
+int virtual_servers_load(CONF_SECTION *config);
+void virtual_servers_free(time_t when);
+
+
+#endif /* RADIUS_MODULES_H */
--- /dev/null
+#ifndef RADIUSD_H
+#define RADIUSD_H
+/*
+ * radiusd.h Structures, prototypes and global variables
+ * for the FreeRADIUS server.
+ *
+ * Version: $Id: radiusd.h,v 1.1 2010/08/14 04:13:52 faust Exp $
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 1999,2000,2002,2003,2004,2005,2006,2007,2008 The FreeRADIUS server project
+ *
+ */
+
+#include <freeradius/ident.h>
+RCSIDH(radiusd_h, "$Id: radiusd.h,v 1.1 2010/08/14 04:13:52 faust Exp $")
+
+#include "libradius.h"
+#include <freeradius/radpaths.h>
+#include "conf.h"
+#include "conffile.h"
+#include "event.h"
+
+typedef struct auth_req REQUEST;
+
+#ifdef HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
+
+#ifndef NDEBUG
+#define REQUEST_MAGIC (0xdeadbeef)
+#endif
+
+/*
+ * New defines for minimizing the size of the server, to strip
+ * out functionality. In order to ensure that people don't have
+ * to re-run "configure", after "cvs update", we play some
+ * special games with the defines. i.e. any top-level "configure"
+ * option should set both WITH_FOO and WITHOUT_FOO. After a few
+ * weeks, the WITHOUT_FOO can be deleted from the configure script.
+ */
+#ifndef WITHOUT_PROXY
+#define WITH_PROXY (1)
+#endif
+
+#ifndef WITHOUT_DETAIL
+#define WITH_DETAIL (1)
+#endif
+
+#ifndef WITHOUT_SESSION_MGMT
+#define WITH_SESSION_MGMT (1)
+#endif
+
+#ifndef WITHOUT_UNLANG
+#define WITH_UNLANG (1)
+#endif
+
+#ifndef WITHOUT_ACCOUNTING
+#define WITH_ACCOUNTING (1)
+#else
+#ifdef WITH_SESSION_MGMT
+#error WITH_SESSION_MGMT is defined, but WITH_ACCOUNTING is not. Session management requires accounting.
+#endif
+#ifdef WITH_DETAIL
+#error WITH_DETAIL is defined, but WITH_ACCOUNTING is not. Detail file reading requires accounting.
+#endif
+#endif
+
+#ifndef WITHOUT_DYNAMIC_CLIENTS
+#define WITH_DYNAMIC_CLIENTS (1)
+#endif
+
+#ifndef WITHOUT_STATS
+#define WITH_STATS
+#endif
+
+#ifndef WITHOUT_COMMAND_SOCKET
+#ifdef HAVE_SYS_UN_H
+#define WITH_COMMAND_SOCKET (1)
+#endif
+#endif
+
+#ifndef WITHOUT_COA
+#define WITH_COA (1)
+#ifndef WITH_PROXY
+#error WITH_COA requires WITH_PROXY
+#endif
+#endif
+
+#include "stats.h"
+#include "realms.h"
+
+
+/*
+ * See util.c
+ */
+typedef struct request_data_t request_data_t;
+
+typedef struct radclient {
+ fr_ipaddr_t ipaddr;
+ int prefix;
+ char *longname;
+ char *secret;
+ char *shortname;
+ int message_authenticator;
+ char *nastype;
+ char *login;
+ char *password;
+ char *server;
+ int number; /* internal use only */
+ const CONF_SECTION *cs;
+#ifdef WITH_STATS
+ fr_stats_t *auth;
+#ifdef WITH_ACCOUNTING
+ fr_stats_t *acct;
+#endif
+#endif
+
+#ifdef WITH_DYNAMIC_CLIENTS
+ int lifetime;
+ int dynamic; /* was dynamically defined */
+ time_t created;
+ time_t last_new_client;
+ char *client_server;
+#endif
+} RADCLIENT;
+
+/*
+ * Types of listeners.
+ *
+ * Ordered by priority!
+ */
+typedef enum RAD_LISTEN_TYPE {
+ RAD_LISTEN_NONE = 0,
+#ifdef WITH_PROXY
+ RAD_LISTEN_PROXY,
+#endif
+ RAD_LISTEN_AUTH,
+#ifdef WITH_ACCOUNTING
+ RAD_LISTEN_ACCT,
+#endif
+#ifdef WITH_DETAIL
+ RAD_LISTEN_DETAIL,
+#endif
+#ifdef WITH_VMPS
+ RAD_LISTEN_VQP,
+#endif
+#ifdef WITH_DHCP
+ RAD_LISTEN_DHCP,
+#endif
+#ifdef WITH_COMMAND_SOCKET
+ RAD_LISTEN_COMMAND,
+#endif
+#ifdef WITH_COA
+ RAD_LISTEN_COA,
+#endif
+ RAD_LISTEN_MAX
+} RAD_LISTEN_TYPE;
+
+
+/*
+ * For listening on multiple IP's and ports.
+ */
+typedef struct rad_listen_t rad_listen_t;
+typedef void (*radlog_func_t)(int, int, REQUEST *, const char *, ...);
+
+#define REQUEST_DATA_REGEX (0xadbeef00)
+#define REQUEST_MAX_REGEX (8)
+
+struct auth_req {
+#ifndef NDEBUG
+ uint32_t magic; /* for debugging only */
+#endif
+ RADIUS_PACKET *packet;
+#ifdef WITH_PROXY
+ RADIUS_PACKET *proxy;
+#endif
+ RADIUS_PACKET *reply;
+#ifdef WITH_PROXY
+ RADIUS_PACKET *proxy_reply;
+#endif
+ VALUE_PAIR *config_items;
+ VALUE_PAIR *username;
+ VALUE_PAIR *password;
+
+ struct main_config_t *root;
+
+ request_data_t *data;
+ RADCLIENT *client;
+#ifdef HAVE_PTHREAD_H
+ pthread_t child_pid;
+#endif
+ time_t timestamp;
+ int number; /* internal server number */
+
+ rad_listen_t *listener;
+#ifdef WITH_PROXY
+ rad_listen_t *proxy_listener;
+#endif
+
+
+ int simul_max; /* see modcall.c && xlat.c */
+#ifdef WITH_SESSION_MGMT
+ int simul_count;
+ int simul_mpp; /* WEIRD: 1 is false, 2 is true */
+#endif
+
+ int options; /* miscellanous options */
+ const char *module; /* for debugging unresponsive children */
+ const char *component; /* ditto */
+
+ struct timeval received;
+ struct timeval when; /* to wake up */
+ int delay;
+
+ int master_state;
+ int child_state;
+ RAD_LISTEN_TYPE priority;
+
+ fr_event_t *ev;
+ struct timeval next_when;
+ fr_event_callback_t next_callback;
+
+ int in_request_hash;
+
+ const char *server;
+ REQUEST *parent;
+ radlog_func_t radlog; /* logging function, if set */
+#ifdef WITH_COA
+ REQUEST *coa;
+ int num_coa_requests;
+#endif
+}; /* REQUEST typedef */
+
+#define RAD_REQUEST_OPTION_NONE (0)
+#define RAD_REQUEST_OPTION_DEBUG (1)
+#define RAD_REQUEST_OPTION_DEBUG2 (2)
+#define RAD_REQUEST_OPTION_DEBUG3 (3)
+#define RAD_REQUEST_OPTION_DEBUG4 (4)
+
+#define REQUEST_ACTIVE (1)
+#define REQUEST_STOP_PROCESSING (2)
+#define REQUEST_COUNTED (3)
+
+#define REQUEST_QUEUED (1)
+#define REQUEST_RUNNING (2)
+#define REQUEST_PROXIED (3)
+#define REQUEST_REJECT_DELAY (4)
+#define REQUEST_CLEANUP_DELAY (5)
+#define REQUEST_DONE (6)
+
+/*
+ * Function handler for requests.
+ */
+typedef int (*RAD_REQUEST_FUNP)(REQUEST *);
+
+typedef struct radclient_list RADCLIENT_LIST;
+
+typedef struct pair_list {
+ const char *name;
+ VALUE_PAIR *check;
+ VALUE_PAIR *reply;
+ int lineno;
+ int order;
+ struct pair_list *next;
+ struct pair_list *lastdefault;
+} PAIR_LIST;
+
+
+typedef int (*rad_listen_recv_t)(rad_listen_t *, RAD_REQUEST_FUNP *, REQUEST **);
+typedef int (*rad_listen_send_t)(rad_listen_t *, REQUEST *);
+typedef int (*rad_listen_print_t)(rad_listen_t *, char *, size_t);
+typedef int (*rad_listen_encode_t)(rad_listen_t *, REQUEST *);
+typedef int (*rad_listen_decode_t)(rad_listen_t *, REQUEST *);
+
+struct rad_listen_t {
+ struct rad_listen_t *next; /* should be rbtree stuff */
+
+ /*
+ * For normal sockets.
+ */
+ RAD_LISTEN_TYPE type;
+ int fd;
+ const char *server;
+ int status;
+
+ rad_listen_recv_t recv;
+ rad_listen_send_t send;
+ rad_listen_encode_t encode;
+ rad_listen_decode_t decode;
+ rad_listen_print_t print;
+
+ void *data;
+
+#ifdef WITH_STATS
+ fr_stats_t stats;
+#endif
+};
+
+#define RAD_LISTEN_STATUS_INIT (0)
+#define RAD_LISTEN_STATUS_KNOWN (1)
+#define RAD_LISTEN_STATUS_CLOSED (2)
+#define RAD_LISTEN_STATUS_FINISH (3)
+
+typedef enum radlog_dest_t {
+ RADLOG_STDOUT = 0,
+ RADLOG_FILES,
+ RADLOG_SYSLOG,
+ RADLOG_STDERR,
+ RADLOG_NULL,
+ RADLOG_NUM_DEST
+} radlog_dest_t;
+
+typedef struct main_config_t {
+ struct main_config *next;
+ int refcount;
+ fr_ipaddr_t myip; /* from the command-line only */
+ int port; /* from the command-line only */
+ int log_auth;
+ int log_auth_badpass;
+ int log_auth_goodpass;
+ int allow_core_dumps;
+ int debug_level;
+ int proxy_requests;
+ int reject_delay;
+ int status_server;
+ int max_request_time;
+ int cleanup_delay;
+ int max_requests;
+#ifdef DELETE_BLOCKED_REQUESTS
+ int kill_unresponsive_children;
+#endif
+ char *log_file;
+ char *checkrad;
+ const char *pid_file;
+ rad_listen_t *listen;
+ int syslog_facility;
+ int radlog_fd;
+ radlog_dest_t radlog_dest;
+ CONF_SECTION *config;
+ const char *name;
+ const char *auth_badpass_msg;
+ const char *auth_goodpass_msg;
+} MAIN_CONFIG_T;
+
+#define DEBUG if(debug_flag)log_debug
+#define DEBUG2 if (debug_flag > 1)log_debug
+#define DEBUG3 if (debug_flag > 2)log_debug
+#define DEBUG4 if (debug_flag > 3)log_debug
+
+#if __GNUC__ >= 3
+#define RDEBUG(fmt, ...) if(request && request->radlog) request->radlog(L_DBG, 1, request, fmt, ## __VA_ARGS__)
+#define RDEBUG2(fmt, ...) if(request && request->radlog) request->radlog(L_DBG, 2, request, fmt, ## __VA_ARGS__)
+#define RDEBUG3(fmt, ...) if(request && request->radlog) request->radlog(L_DBG, 3, request, fmt, ## __VA_ARGS__)
+#define RDEBUG4(fmt, ...) if(request && request->radlog) request->radlog(L_DBG, 4, request, fmt, ## __VA_ARGS__)
+#else
+#define RDEBUG DEBUG
+#define RDEBUG2 DEBUG2
+#define RDEBUG3 DEBUG3
+#define RDEBUG4 DEBUG4
+#endif
+
+#define SECONDS_PER_DAY 86400
+#define MAX_REQUEST_TIME 30
+#define CLEANUP_DELAY 5
+#define MAX_REQUESTS 256
+#define RETRY_DELAY 5
+#define RETRY_COUNT 3
+#define DEAD_TIME 120
+
+#define L_DBG 1
+#define L_AUTH 2
+#define L_INFO 3
+#define L_ERR 4
+#define L_PROXY 5
+#define L_ACCT 6
+#define L_CONS 128
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+/*
+ * This definition of true as NOT false is definitive. :) Making
+ * it '1' can cause problems on stupid platforms. See articles
+ * on C portability for more information.
+ */
+#define TRUE (!FALSE)
+#endif
+
+/* for paircompare_register */
+typedef int (*RAD_COMPARE_FUNC)(void *instance, REQUEST *,VALUE_PAIR *, VALUE_PAIR *, VALUE_PAIR *, VALUE_PAIR **);
+
+typedef enum request_fail_t {
+ REQUEST_FAIL_UNKNOWN = 0,
+ REQUEST_FAIL_NO_THREADS, /* no threads to handle it */
+ REQUEST_FAIL_DECODE, /* rad_decode didn't like it */
+ REQUEST_FAIL_PROXY, /* call to proxy modules failed */
+ REQUEST_FAIL_PROXY_SEND, /* proxy_send didn't like it */
+ REQUEST_FAIL_NO_RESPONSE, /* we weren't told to respond, so we reject */
+ REQUEST_FAIL_HOME_SERVER, /* the home server didn't respond */
+ REQUEST_FAIL_HOME_SERVER2, /* another case of the above */
+ REQUEST_FAIL_HOME_SERVER3, /* another case of the above */
+ REQUEST_FAIL_NORMAL_REJECT, /* authentication failure */
+ REQUEST_FAIL_SERVER_TIMEOUT /* the server took too long to process the request */
+} request_fail_t;
+
+/*
+ * Global variables.
+ *
+ * We really shouldn't have this many.
+ */
+extern const char *progname;
+extern int debug_flag;
+extern const char *radacct_dir;
+extern const char *radlog_dir;
+extern const char *radlib_dir;
+extern const char *radius_dir;
+extern const char *radius_libdir;
+extern uint32_t expiration_seconds;
+extern int log_stripped_names;
+extern int log_auth_detail;
+extern const char *radiusd_version;
+void radius_signal_self(int flag);
+
+#define RADIUS_SIGNAL_SELF_NONE (0)
+#define RADIUS_SIGNAL_SELF_HUP (1 << 0)
+#define RADIUS_SIGNAL_SELF_TERM (1 << 1)
+#define RADIUS_SIGNAL_SELF_EXIT (1 << 2)
+#define RADIUS_SIGNAL_SELF_DETAIL (1 << 3)
+#define RADIUS_SIGNAL_SELF_NEW_FD (1 << 4)
+#define RADIUS_SIGNAL_SELF_MAX (1 << 5)
+
+
+/*
+ * Function prototypes.
+ */
+
+/* acct.c */
+int rad_accounting(REQUEST *);
+
+/* session.c */
+int rad_check_ts(uint32_t nasaddr, unsigned int port, const char *user,
+ const char *sessionid);
+int session_zap(REQUEST *request, uint32_t nasaddr,
+ unsigned int port, const char *user,
+ const char *sessionid, uint32_t cliaddr,
+ char proto,int session_time);
+
+/* radiusd.c */
+#undef debug_pair
+void debug_pair(VALUE_PAIR *);
+void debug_pair_list(VALUE_PAIR *);
+int log_err (char *);
+
+/* util.c */
+void (*reset_signal(int signo, void (*func)(int)))(int);
+void request_free(REQUEST **request);
+int rad_mkdir(char *directory, int mode);
+int rad_checkfilename(const char *filename);
+void *rad_malloc(size_t size); /* calls exit(1) on error! */
+REQUEST *request_alloc(void);
+REQUEST *request_alloc_fake(REQUEST *oldreq);
+REQUEST *request_alloc_coa(REQUEST *request);
+int request_data_add(REQUEST *request,
+ void *unique_ptr, int unique_int,
+ void *opaque, void (*free_opaque)(void *));
+void *request_data_get(REQUEST *request,
+ void *unique_ptr, int unique_int);
+void *request_data_reference(REQUEST *request,
+ void *unique_ptr, int unique_int);
+int rad_copy_string(char *dst, const char *src);
+int rad_copy_variable(char *dst, const char *from);
+
+/* client.c */
+RADCLIENT_LIST *clients_init(void);
+void clients_free(RADCLIENT_LIST *clients);
+RADCLIENT_LIST *clients_parse_section(CONF_SECTION *section);
+void client_free(RADCLIENT *client);
+int client_add(RADCLIENT_LIST *clients, RADCLIENT *client);
+#ifdef WITH_DYNAMIC_CLIENTS
+void client_delete(RADCLIENT_LIST *clients, RADCLIENT *client);
+RADCLIENT *client_create(RADCLIENT_LIST *clients, REQUEST *request);
+#endif
+RADCLIENT *client_find(const RADCLIENT_LIST *clients,
+ const fr_ipaddr_t *ipaddr);
+RADCLIENT *client_findbynumber(const RADCLIENT_LIST *clients,
+ int number);
+RADCLIENT *client_find_old(const fr_ipaddr_t *ipaddr);
+int client_validate(RADCLIENT_LIST *clients, RADCLIENT *master,
+ RADCLIENT *c);
+RADCLIENT *client_read(const char *filename, int in_server, int flag);
+
+
+/* files.c */
+int pairlist_read(const char *file, PAIR_LIST **list, int complain);
+void pairlist_free(PAIR_LIST **);
+
+/* version.c */
+void version(void);
+
+/* log.c */
+int vradlog(int, const char *, va_list ap);
+int radlog(int, const char *, ...)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 2, 3)))
+#endif
+;
+int log_debug(const char *, ...)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 1, 2)))
+#endif
+;
+void vp_listdebug(VALUE_PAIR *vp);
+void radlog_request(int lvl, int priority, REQUEST *request, const char *msg, ...)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 4, 5)))
+#endif
+;
+
+/* auth.c */
+char *auth_name(char *buf, size_t buflen, REQUEST *request, int do_cli);
+int rad_authenticate (REQUEST *);
+int rad_postauth(REQUEST *);
+
+/* exec.c */
+int radius_exec_program(const char *, REQUEST *, int,
+ char *user_msg, int msg_len,
+ VALUE_PAIR *input_pairs,
+ VALUE_PAIR **output_pairs,
+ int shell_escape);
+
+/* timestr.c */
+int timestr_match(char *, time_t);
+
+/* valuepair.c */
+int paircompare_register(int attr, int otherattr,
+ RAD_COMPARE_FUNC func,
+ void *instance);
+void paircompare_unregister(int attr, RAD_COMPARE_FUNC func);
+int paircompare(REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check,
+ VALUE_PAIR **reply);
+void pairxlatmove(REQUEST *, VALUE_PAIR **to, VALUE_PAIR **from);
+int radius_compare_vps(REQUEST *request, VALUE_PAIR *check, VALUE_PAIR *vp);
+int radius_callback_compare(REQUEST *req, VALUE_PAIR *request,
+ VALUE_PAIR *check, VALUE_PAIR *check_pairs,
+ VALUE_PAIR **reply_pairs);
+int radius_find_compare(int attribute);
+VALUE_PAIR *radius_paircreate(REQUEST *request, VALUE_PAIR **vps,
+ int attribute, int type);
+VALUE_PAIR *radius_pairmake(REQUEST *request, VALUE_PAIR **vps,
+ const char *attribute, const char *value,
+ int _operator);
+
+/* xlat.c */
+typedef size_t (*RADIUS_ESCAPE_STRING)(char *out, size_t outlen, const char *in);
+
+int radius_xlat(char * out, int outlen, const char *fmt,
+ REQUEST * request, RADIUS_ESCAPE_STRING func);
+typedef size_t (*RAD_XLAT_FUNC)(void *instance, REQUEST *, char *, char *, size_t, RADIUS_ESCAPE_STRING func);
+int xlat_register(const char *module, RAD_XLAT_FUNC func,
+ void *instance);
+void xlat_unregister(const char *module, RAD_XLAT_FUNC func);
+void xlat_free(void);
+
+/* threads.c */
+extern int thread_pool_init(CONF_SECTION *cs, int *spawn_flag);
+extern int thread_pool_addrequest(REQUEST *, RAD_REQUEST_FUNP);
+extern pid_t rad_fork(void);
+extern pid_t rad_waitpid(pid_t pid, int *status);
+extern int total_active_threads(void);
+extern void thread_pool_lock(void);
+extern void thread_pool_unlock(void);
+extern void thread_pool_queue_stats(int *array);
+
+#ifndef HAVE_PTHREAD_H
+#define rad_fork(n) fork()
+#define rad_waitpid(a,b) waitpid(a,b, 0)
+#endif
+
+/* mainconfig.c */
+/* Define a global config structure */
+extern struct main_config_t mainconfig;
+
+int read_mainconfig(int reload);
+int free_mainconfig(void);
+void hup_mainconfig(void);
+void fr_suid_down(void);
+void fr_suid_up(void);
+void fr_suid_down_permanent(void);
+
+/* listen.c */
+void listen_free(rad_listen_t **head);
+int listen_init(CONF_SECTION *cs, rad_listen_t **head);
+rad_listen_t *proxy_new_listener(fr_ipaddr_t *ipaddr, int exists);
+RADCLIENT *client_listener_find(const rad_listen_t *listener,
+ const fr_ipaddr_t *ipaddr, int src_port);
+#ifdef WITH_STATS
+RADCLIENT_LIST *listener_find_client_list(const fr_ipaddr_t *ipaddr,
+ int port);
+rad_listen_t *listener_find_byipaddr(const fr_ipaddr_t *ipaddr, int port);
+#endif
+
+/* event.c */
+int radius_event_init(CONF_SECTION *cs, int spawn_flag);
+void radius_event_free(void);
+int radius_event_process(void);
+void radius_handle_request(REQUEST *request, RAD_REQUEST_FUNP fun);
+int received_request(rad_listen_t *listener,
+ RADIUS_PACKET *packet, REQUEST **prequest,
+ RADCLIENT *client);
+REQUEST *received_proxy_response(RADIUS_PACKET *packet);
+void event_new_fd(rad_listen_t *listener);
+
+/* evaluate.c */
+int radius_evaluate_condition(REQUEST *request, int modreturn, int depth,
+ const char **ptr, int evaluate_it, int *presult);
+int radius_update_attrlist(REQUEST *request, CONF_SECTION *cs,
+ VALUE_PAIR *input_vps, const char *name);
+void radius_pairmove(REQUEST *request, VALUE_PAIR **to, VALUE_PAIR *from);
+#endif /*RADIUSD_H*/
--- /dev/null
+#ifndef REALMS_H
+#define REALMS_H
+
+/*
+ * realms.h Structures, prototypes and global variables
+ * for realms
+ *
+ * Version: $Id: realms.h,v 1.1 2010/08/14 04:13:52 faust Exp $
+ *
+ */
+
+#include <freeradius/ident.h>
+RCSIDH(realms_h, "$Id: realms.h,v 1.1 2010/08/14 04:13:52 faust Exp $")
+
+#define HOME_TYPE_INVALID (0)
+#define HOME_TYPE_AUTH (1)
+#define HOME_TYPE_ACCT (2)
+#ifdef WITH_COA
+#define HOME_TYPE_COA (3)
+#endif
+
+#define HOME_PING_CHECK_NONE (0)
+#define HOME_PING_CHECK_STATUS_SERVER (1)
+#define HOME_PING_CHECK_REQUEST (2)
+
+#define HOME_STATE_ALIVE (0)
+#define HOME_STATE_ZOMBIE (1)
+#define HOME_STATE_IS_DEAD (2)
+
+typedef struct home_server {
+ const char *name;
+
+ const char *hostname;
+ const char *server; /* for internal proxying */
+
+ fr_ipaddr_t ipaddr;
+
+ int port;
+ int type; /* auth/acct */
+
+ /*
+ * Maybe also have list of source IP/ports, && socket?
+ */
+
+ const char *secret;
+
+ fr_event_t *ev;
+ struct timeval when;
+
+ int response_window;
+ int no_response_fail;
+ int max_outstanding; /* don't overload it */
+ int currently_outstanding;
+ int message_authenticator;
+
+ struct timeval revive_time;
+ struct timeval zombie_period_start;
+ int zombie_period; /* unresponsive for T, mark it dead */
+
+ int state;
+
+ int ping_check;
+ const char *ping_user_name;
+ const char *ping_user_password;
+
+ int ping_interval;
+ int num_pings_to_alive;
+ int num_received_pings;
+ int ping_timeout;
+
+ int revive_interval; /* if it doesn't support pings */
+ CONF_SECTION *cs;
+#ifdef WITH_COA
+ int coa_irt;
+ int coa_mrc;
+ int coa_mrt;
+ int coa_mrd;
+#endif
+#ifdef WITH_STATS
+ int number;
+
+ fr_ipaddr_t src_ipaddr; /* preferred source IP address */
+
+ fr_stats_t stats;
+
+ fr_stats_ema_t ema;
+#endif
+} home_server;
+
+
+typedef enum home_pool_type_t {
+ HOME_POOL_INVALID = 0,
+ HOME_POOL_LOAD_BALANCE,
+ HOME_POOL_FAIL_OVER,
+ HOME_POOL_CLIENT_BALANCE,
+ HOME_POOL_CLIENT_PORT_BALANCE,
+ HOME_POOL_KEYED_BALANCE
+} home_pool_type_t;
+
+
+typedef struct home_pool_t {
+ const char *name;
+ home_pool_type_t type;
+
+ int server_type;
+ CONF_SECTION *cs;
+
+ const char *virtual_server; /* for pre/post-proxy */
+
+ home_server *fallback;
+
+ int num_home_servers;
+ home_server *servers[1];
+} home_pool_t;
+
+
+typedef struct _realm {
+ const char *name;
+
+ int striprealm;
+
+ home_pool_t *auth_pool;
+ home_pool_t *acct_pool;
+} REALM;
+
+int realms_init(CONF_SECTION *config);
+void realms_free(void);
+REALM *realm_find(const char *name); /* name is from a packet */
+REALM *realm_find2(const char *name); /* ... with name taken from realm_find */
+
+home_server *home_server_ldb(const char *realmname, home_pool_t *pool, REQUEST *request);
+home_server *home_server_find(fr_ipaddr_t *ipaddr, int port);
+int home_server_create_listeners(void *head);
+#ifdef WITH_COA
+home_server *home_server_byname(const char *name, int type);
+#endif
+#ifdef WITH_STATS
+home_server *home_server_bynumber(int number);
+#endif
+home_pool_t *home_pool_byname(const char *name, int type);
+
+#endif /* REALMS_H */
--- /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>
+ */
+
+/*
+ * FreeRADIUS module for data access via Stargazer
+ *
+ * $Revision: 1.8 $
+ * $Date: 2010/08/14 04:15:08 $
+ *
+ */
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+extern "C" {
+//#include <freeradius/libradius.h>
+#include "radiusd.h"
+#include "modules.h"
+//#include <freeradius/conffile.h>
+}
+
+#include "stg_client.h"
+#include "common.h"
+
+STG_CLIENT * cli;
+volatile time_t stgTime;
+
+/*
+ * Define a structure for our module configuration.
+ *
+ * These variables do not need to be in a structure, but it's
+ * a lot cleaner to do so, and a pointer to the structure can
+ * be used as the instance handle.
+ */
+typedef struct rlm_stg_t {
+ char * server;
+ char * password;
+ uint32_t port;
+ uint32_t localPort;
+} rlm_stg_t;
+
+/*
+ * A mapping of configuration file names to internal variables.
+ *
+ * Note that the string is dynamically allocated, so it MUST
+ * be freed. When the configuration file parse re-reads the string,
+ * it free's the old one, and strdup's the new one, placing the pointer
+ * to the strdup'd string into 'config.string'. This gets around
+ * buffer over-flows.
+ */
+static CONF_PARSER module_config[] = {
+ { "password", PW_TYPE_STRING_PTR, offsetof(rlm_stg_t,password), NULL, NULL},
+ { "server", PW_TYPE_STRING_PTR, offsetof(rlm_stg_t,server), NULL, NULL},
+ { "port", PW_TYPE_INTEGER, offsetof(rlm_stg_t,port), NULL, "5555" },
+ { "local_port", PW_TYPE_INTEGER, offsetof(rlm_stg_t,localPort), NULL, "0" },
+
+ { NULL, -1, 0, NULL, NULL } /* end the list */
+};
+
+/*
+ * Do any per-module initialization that is separate to each
+ * configured instance of the module. e.g. set up connections
+ * to external databases, read configuration files, set up
+ * dictionary entries, etc.
+ *
+ * If configuration information is given in the config section
+ * that must be referenced in later calls, store a handle to it
+ * in *instance otherwise put a null pointer there.
+ */
+static int stg_instantiate(CONF_SECTION *conf, void **instance)
+{
+ rlm_stg_t *data;
+
+ /*
+ * Set up a storage area for instance data
+ */
+ DEBUG("rlm_stg: stg_instantiate()");
+ data = (rlm_stg_t *)rad_malloc(sizeof(rlm_stg_t));
+ if (!data) {
+ return -1;
+ }
+ memset(data, 0, sizeof(rlm_stg_t));
+
+ /*
+ * If the configuration parameters can't be parsed, then
+ * fail.
+ */
+ if (cf_section_parse(conf, data, module_config) < 0) {
+ free(data);
+ return -1;
+ }
+
+ cli = new STG_CLIENT();
+ cli->SetServer(data->server);
+ cli->SetPort(data->port);
+ cli->SetLocalPort(data->localPort);
+ cli->SetPassword(data->password);
+ if (cli->Start()) {
+ DEBUG("rlm_stg: stg_instantiate() error: '%s'", cli->GetError().c_str());
+ return -1;
+ }
+
+ *instance = data;
+
+ return 0;
+}
+
+/*
+ * Find the named user in this modules database. Create the set
+ * of attribute-value pairs to check and reply with for this user
+ * from the database. The authentication code only needs to check
+ * the password, the rest is done here.
+ */
+static int stg_authorize(void *instance, REQUEST *request)
+{
+ VALUE_PAIR *uname;
+ VALUE_PAIR *pwd;
+ VALUE_PAIR *svc;
+ DEBUG("rlm_stg: stg_authorize()");
+
+ /* quiet the compiler */
+ instance = instance;
+ request = request;
+
+ uname = pairfind(request->packet->vps, PW_USER_NAME);
+ if (uname) {
+ DEBUG("rlm_stg: stg_authorize() user name defined as '%s'", uname->vp_strvalue);
+ } else {
+ DEBUG("rlm_stg: stg_authorize() user name undefined");
+ return RLM_MODULE_FAIL;
+ }
+ if (request->username) {
+ DEBUG("rlm_stg: stg_authorize() request username field: '%s'", request->username->vp_strvalue);
+ }
+ if (request->password) {
+ DEBUG("rlm_stg: stg_authorize() request password field: '%s'", request->password->vp_strvalue);
+ }
+ // Here we need to define Framed-Protocol
+ svc = pairfind(request->packet->vps, PW_SERVICE_TYPE);
+ if (svc) {
+ DEBUG("rlm_stg: stg_authorize() Service-Type defined as '%s'", svc->vp_strvalue);
+ if (cli->Authorize((const char *)request->username->vp_strvalue, (const char *)svc->vp_strvalue)) {
+ DEBUG("rlm_stg: stg_authorize() stg status: '%s'", cli->GetError().c_str());
+ return RLM_MODULE_REJECT;
+ }
+ } else {
+ DEBUG("rlm_stg: stg_authorize() Service-Type undefined");
+ if (cli->Authorize((const char *)request->username->vp_strvalue, "")) {
+ DEBUG("rlm_stg: stg_authorize() stg status: '%s'", cli->GetError().c_str());
+ return RLM_MODULE_REJECT;
+ }
+ }
+ pwd = pairmake("Cleartext-Password", cli->GetUserPassword().c_str(), T_OP_SET);
+ pairadd(&request->config_items, pwd);
+ //pairadd(&request->reply->vps, uname);
+
+ return RLM_MODULE_UPDATED;
+}
+
+/*
+ * Authenticate the user with the given password.
+ */
+static int stg_authenticate(void *instance, REQUEST *request)
+{
+ /* quiet the compiler */
+ VALUE_PAIR *svc;
+ instance = instance;
+ request = request;
+ DEBUG("rlm_stg: stg_authenticate()");
+ svc = pairfind(request->packet->vps, PW_SERVICE_TYPE);
+ if (svc) {
+ DEBUG("rlm_stg: stg_authenticate() Service-Type defined as '%s'", svc->vp_strvalue);
+ if (cli->Authenticate((char *)request->username->vp_strvalue, (const char *)svc->vp_strvalue)) {
+ DEBUG("rlm_stg: stg_authenticate() stg status: '%s'", cli->GetError().c_str());
+ return RLM_MODULE_REJECT;
+ }
+ } else {
+ DEBUG("rlm_stg: stg_authenticate() Service-Type undefined");
+ if (cli->Authenticate((char *)request->username->vp_strvalue, "")) {
+ DEBUG("rlm_stg: stg_authenticate() stg status: '%s'", cli->GetError().c_str());
+ return RLM_MODULE_REJECT;
+ }
+ }
+
+ return RLM_MODULE_NOOP;
+}
+
+/*
+ * Massage the request before recording it or proxying it
+ */
+static int stg_preacct(void *instance, REQUEST *request)
+{
+ /* quiet the compiler */
+ instance = instance;
+ request = request;
+ DEBUG("rlm_stg: stg_preacct()");
+
+ return RLM_MODULE_OK;
+}
+
+/*
+ * Write accounting information to this modules database.
+ */
+static int stg_accounting(void *instance, REQUEST *request)
+{
+ /* quiet the compiler */
+ VALUE_PAIR * sttype;
+ VALUE_PAIR * svc;
+ VALUE_PAIR * sessid;
+ svc = pairfind(request->packet->vps, PW_SERVICE_TYPE);
+ instance = instance;
+ request = request;
+ DEBUG("rlm_stg: stg_accounting()");
+
+ sessid = pairfind(request->packet->vps, PW_ACCT_SESSION_ID);
+ if (!sessid) {
+ DEBUG("rlm_stg: stg_accounting() Acct-Session-ID undefined");
+ return RLM_MODULE_FAIL;
+ }
+ sttype = pairfind(request->packet->vps, PW_ACCT_STATUS_TYPE);
+ if (sttype) {
+ DEBUG("Acct-Status-Type := %s", sttype->vp_strvalue);
+ if (svc) {
+ DEBUG("rlm_stg: stg_accounting() Service-Type defined as '%s'", svc->vp_strvalue);
+ if (cli->Account((const char *)sttype->vp_strvalue, (const char *)request->username->vp_strvalue, (const char *)svc->vp_strvalue, (const char *)sessid->vp_strvalue)) {
+ DEBUG("rlm_stg: stg_accounting error: '%s'", cli->GetError().c_str());
+ return RLM_MODULE_FAIL;
+ }
+ } else {
+ DEBUG("rlm_stg: stg_accounting() Service-Type undefined");
+ if (cli->Account((const char *)sttype->vp_strvalue, (const char *)request->username->vp_strvalue, "", (const char *)sessid->vp_strvalue)) {
+ DEBUG("rlm_stg: stg_accounting error: '%s'", cli->GetError().c_str());
+ return RLM_MODULE_FAIL;
+ }
+ }
+ } else {
+ DEBUG("Acct-Status-Type := NULL");
+ }
+
+ return RLM_MODULE_OK;
+}
+
+/*
+ * See if a user is already logged in. Sets request->simul_count to the
+ * current session count for this user and sets request->simul_mpp to 2
+ * if it looks like a multilink attempt based on the requested IP
+ * address, otherwise leaves request->simul_mpp alone.
+ *
+ * Check twice. If on the first pass the user exceeds his
+ * max. number of logins, do a second pass and validate all
+ * logins by querying the terminal server (using eg. SNMP).
+ */
+static int stg_checksimul(void *instance, REQUEST *request)
+{
+ instance = instance;
+ DEBUG("rlm_stg: stg_checksimul()");
+
+ request->simul_count=0;
+
+ return RLM_MODULE_OK;
+}
+
+static int stg_postauth(void *instance, REQUEST *request)
+{
+ instance = instance;
+ VALUE_PAIR *fia;
+ VALUE_PAIR *svc;
+ struct in_addr fip;
+ DEBUG("rlm_stg: stg_postauth()");
+ svc = pairfind(request->packet->vps, PW_SERVICE_TYPE);
+ if (svc) {
+ DEBUG("rlm_stg: stg_postauth() Service-Type defined as '%s'", svc->vp_strvalue);
+ if (cli->PostAuthenticate((const char *)request->username->vp_strvalue, (const char *)svc->vp_strvalue)) {
+ DEBUG("rlm_stg: stg_postauth() error: '%s'", cli->GetError().c_str());
+ return RLM_MODULE_FAIL;
+ }
+ } else {
+ DEBUG("rlm_stg: stg_postauth() Service-Type undefined");
+ if (cli->PostAuthenticate((const char *)request->username->vp_strvalue, "")) {
+ DEBUG("rlm_stg: stg_postauth() error: '%s'", cli->GetError().c_str());
+ return RLM_MODULE_FAIL;
+ }
+ }
+ if (strncmp((const char *)svc->vp_strvalue, "Framed-User", 11) == 0) {
+ fip.s_addr = cli->GetFramedIP();
+ DEBUG("rlm_stg: stg_postauth() ip = '%s'", inet_ntostring(fip.s_addr).c_str());
+ fia = pairmake("Framed-IP-Address", inet_ntostring(fip.s_addr).c_str(), T_OP_SET);
+ pairadd(&request->reply->vps, fia);
+ }
+
+ return RLM_MODULE_UPDATED;
+}
+
+static int stg_detach(void *instance)
+{
+ DEBUG("rlm_stg: stg_detach()");
+ cli->Stop();
+ delete cli;
+ free(((struct rlm_stg_t *)instance)->server);
+ free(((struct rlm_stg_t *)instance)->password);
+ free(instance);
+ return 0;
+}
+
+/*
+ * The module name should be the only globally exported symbol.
+ * That is, everything else should be 'static'.
+ *
+ * If the module needs to temporarily modify it's instantiation
+ * data, the type should be changed to RLM_TYPE_THREAD_UNSAFE.
+ * The server will then take care of ensuring that the module
+ * is single-threaded.
+ */
+module_t rlm_stg = {
+ RLM_MODULE_INIT,
+ "stg",
+ RLM_TYPE_THREAD_SAFE, /* type */
+ stg_instantiate, /* instantiation */
+ stg_detach, /* detach */
+ {
+ stg_authenticate, /* authentication */
+ stg_authorize, /* authorization */
+ stg_preacct, /* preaccounting */
+ stg_accounting, /* accounting */
+ stg_checksimul, /* checksimul */
+ NULL, /* pre-proxy */
+ NULL, /* post-proxy */
+ stg_postauth /* post-auth */
+ },
+};
--- /dev/null
+#ifndef FR_STATS_H
+#define FR_STATS_H
+
+/*
+ * stats.h Structures and functions for statistics.
+ *
+ * Version: $Id: stats.h,v 1.1 2010/08/14 04:13:52 faust Exp $
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2005,2006,2007,2008 The FreeRADIUS server project
+ */
+
+#include <freeradius/ident.h>
+RCSIDH(stats_h, "$Id: stats.h,v 1.1 2010/08/14 04:13:52 faust Exp $")
+
+#ifdef WITH_STATS_64BIT
+typedef uint64_t fr_uint_t;
+#else
+typedef uint32_t fr_uint_t;
+#endif
+
+#ifdef WITH_STATS
+typedef struct fr_stats_t {
+ fr_uint_t total_requests;
+ fr_uint_t total_invalid_requests;
+ fr_uint_t total_dup_requests;
+ fr_uint_t total_responses;
+ fr_uint_t total_access_accepts;
+ fr_uint_t total_access_rejects;
+ fr_uint_t total_access_challenges;
+ fr_uint_t total_malformed_requests;
+ fr_uint_t total_bad_authenticators;
+ fr_uint_t total_packets_dropped;
+ fr_uint_t total_no_records;
+ fr_uint_t total_unknown_types;
+} fr_stats_t;
+
+typedef struct fr_stats_ema_t {
+ int window;
+
+ int f1, f10;
+ int ema1, ema10;
+
+} fr_stats_ema_t;
+
+extern fr_stats_t radius_auth_stats;
+extern fr_stats_t radius_acct_stats;
+#ifdef WITH_PROXY
+extern fr_stats_t proxy_auth_stats;
+extern fr_stats_t proxy_acct_stats;
+#endif
+
+void radius_stats_init(int flag);
+void request_stats_final(REQUEST *request);
+void request_stats_reply(REQUEST *request);
+void radius_stats_ema(fr_stats_ema_t *ema,
+ struct timeval *start, struct timeval *end);
+
+#define RAD_STATS_INC(_x) _x++
+#ifdef WITH_ACCOUNTING
+#define RAD_STATS_TYPE_INC(_listener, _x) if (_listener->type == RAD_LISTEN_AUTH) { \
+ radius_auth_stats._x++; \
+ } else if (_listener->type == RAD_LISTEN_ACCT) { \
+ radius_acct_stats._x++; } \
+ _listener->stats._x++
+
+#define RAD_STATS_CLIENT_INC(_listener, _client, _x) if (_listener->type == RAD_LISTEN_AUTH) \
+ _client->auth->_x++; \
+ else if (_listener->type == RAD_LISTEN_ACCT) \
+ _client->acct->_x++
+
+#else /* WITH_ACCOUNTING */
+
+#define RAD_STATS_TYPE_INC(_listener, _x) { radius_auth_stats._x++; _listener->stats._x++; }
+
+#define RAD_STATS_CLIENT_INC(_listener, _client, _x) _client->auth->_x++
+
+#endif /* WITH_ACCOUNTING */
+
+
+#else /* WITH_STATS */
+#define request_stats_init(_x)
+#define request_stats_final(_x)
+
+#define RAD_STATS_INC(_x)
+#define RAD_STATS_TYPE_INC(_listener, _x)
+#define RAD_STATS_CLIENT_INC(_listener, _client, _x)
+
+#endif
+
+#endif /* FR_STATS_H */
--- /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>
+ */
+
+/*
+ * Realization of data access via Stargazer for RADIUS
+ *
+ * $Revision: 1.8 $
+ * $Date: 2010/04/16 12:30:02 $
+ *
+ */
+
+#include <netdb.h>
+#include <sys/types.h>
+#include <unistd.h> // close
+#include <cstring>
+
+#include "stg_client.h"
+
+using namespace std;
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+STG_CLIENT::STG_CLIENT()
+ : port(0),
+ localPort(0),
+ sock(0)
+{
+}
+//-----------------------------------------------------------------------------
+STG_CLIENT::~STG_CLIENT()
+{
+}
+//-----------------------------------------------------------------------------
+void STG_CLIENT::SetServer(const string & host)
+{
+STG_CLIENT::host = host;
+}
+//-----------------------------------------------------------------------------
+void STG_CLIENT::SetPort(uint16_t port)
+{
+STG_CLIENT::port = port;
+}
+//-----------------------------------------------------------------------------
+void STG_CLIENT::SetLocalPort(uint16_t port)
+{
+STG_CLIENT::localPort = port;
+}
+//-----------------------------------------------------------------------------
+void STG_CLIENT::SetPassword(const string & password)
+{
+STG_CLIENT::password = password;
+}
+//-----------------------------------------------------------------------------
+uint32_t STG_CLIENT::GetFramedIP() const
+{
+return framedIP;
+}
+//-----------------------------------------------------------------------------
+void STG_CLIENT::InitEncrypt()
+{
+unsigned char keyL[RAD_PASSWORD_LEN];
+memset(keyL, 0, RAD_PASSWORD_LEN);
+strncpy((char *)keyL, password.c_str(), RAD_PASSWORD_LEN);
+Blowfish_Init(&ctx, keyL, RAD_PASSWORD_LEN);
+}
+//-----------------------------------------------------------------------------
+int STG_CLIENT::PrepareNet()
+{
+sock = socket(AF_INET, SOCK_DGRAM, 0);
+if (sock == -1)
+ {
+ errorStr = "Socket create error";
+ return -1;
+ }
+
+struct hostent * he = NULL;
+he = gethostbyname(host.c_str());
+if (he == NULL)
+ {
+ errorStr = "gethostbyname error";
+ return -1;
+ }
+
+if (localPort != 0)
+ {
+ struct sockaddr_in localAddr;
+ localAddr.sin_family = AF_INET;
+ localAddr.sin_port = htons(localPort);
+ localAddr.sin_addr.s_addr = inet_addr("0.0.0.0");;
+
+ if (bind(sock, (struct sockaddr *)&localAddr, sizeof(localAddr)))
+ {
+ errorStr = "Bind failed";
+ return -1;
+ }
+ }
+
+outerAddr.sin_family = AF_INET;
+outerAddr.sin_port = htons(port);
+outerAddr.sin_addr.s_addr = *(uint32_t *)he->h_addr;
+
+outerAddrLen = sizeof(struct sockaddr_in);
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+void STG_CLIENT::FinalizeNet()
+{
+close(sock);
+}
+//-----------------------------------------------------------------------------
+int STG_CLIENT::Start()
+{
+InitEncrypt();
+
+return PrepareNet();
+}
+//-----------------------------------------------------------------------------
+int STG_CLIENT::Stop()
+{
+FinalizeNet();
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+string STG_CLIENT::GetUserPassword() const
+{
+return userPassword;
+}
+//-----------------------------------------------------------------------------
+int STG_CLIENT::Send(const RAD_PACKET & packet)
+{
+char buf[RAD_MAX_PACKET_LEN];
+
+Encrypt(buf, (char *)&packet, sizeof(RAD_PACKET) / 8);
+
+int res = sendto(sock, buf, sizeof(RAD_PACKET), 0, (struct sockaddr *)&outerAddr, outerAddrLen);
+
+if (res == -1)
+ errorStr = "Error sending data";
+
+return res;
+}
+//-----------------------------------------------------------------------------
+int STG_CLIENT::RecvData(RAD_PACKET * packet)
+{
+char buf[RAD_MAX_PACKET_LEN];
+int res;
+
+outerAddrLen = sizeof(struct sockaddr_in);
+
+res = recvfrom(sock, buf, RAD_MAX_PACKET_LEN, 0, (struct sockaddr *)&outerAddr, &outerAddrLen);
+if (res == -1)
+ {
+ errorStr = "Error receiving data";
+ return -1;
+ }
+
+Decrypt((char *)packet, buf, res / 8);
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int STG_CLIENT::Request(RAD_PACKET * packet, const std::string & login, const std::string & svc, uint8_t packetType)
+{
+int res;
+
+memcpy((void *)&packet->magic, (void *)RAD_ID, RAD_MAGIC_LEN);
+packet->protoVer[0] = '0';
+packet->protoVer[1] = '1';
+packet->packetType = packetType;
+packet->ip = 0;
+strncpy((char *)packet->login, login.c_str(), RAD_LOGIN_LEN);
+strncpy((char *)packet->service, svc.c_str(), RAD_SERVICE_LEN);
+
+res = Send(*packet);
+if (res == -1)
+ return -1;
+
+res = RecvData(packet);
+if (res == -1)
+ return -1;
+
+if (strncmp((char *)packet->magic, RAD_ID, RAD_MAGIC_LEN))
+ {
+ errorStr = "Magic invalid. Wanted: '";
+ errorStr += RAD_ID;
+ errorStr += "', got: '";
+ errorStr += (char *)packet->magic;
+ errorStr += "'";
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int STG_CLIENT::Authorize(const string & login, const string & svc)
+{
+RAD_PACKET packet;
+
+userPassword = "";
+
+if (Request(&packet, login, svc, RAD_AUTZ_PACKET))
+ return -1;
+
+if (packet.packetType != RAD_ACCEPT_PACKET)
+ return -1;
+
+userPassword = (char *)packet.password;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int STG_CLIENT::Authenticate(const string & login, const string & svc)
+{
+RAD_PACKET packet;
+
+userPassword = "";
+
+if (Request(&packet, login, svc, RAD_AUTH_PACKET))
+ return -1;
+
+if (packet.packetType != RAD_ACCEPT_PACKET)
+ return -1;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int STG_CLIENT::PostAuthenticate(const string & login, const string & svc)
+{
+RAD_PACKET packet;
+
+userPassword = "";
+
+if (Request(&packet, login, svc, RAD_POST_AUTH_PACKET))
+ return -1;
+
+if (packet.packetType != RAD_ACCEPT_PACKET)
+ return -1;
+
+if (svc == "Framed-User")
+ framedIP = packet.ip;
+else
+ framedIP = 0;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int STG_CLIENT::Account(const std::string & type, const string & login, const string & svc, const string & sessid)
+{
+RAD_PACKET packet;
+
+userPassword = "";
+strncpy((char *)packet.sessid, sessid.c_str(), RAD_SESSID_LEN);
+
+if (type == "Start")
+ {
+ if (Request(&packet, login, svc, RAD_ACCT_START_PACKET))
+ return -1;
+ }
+else if (type == "Stop")
+ {
+ if (Request(&packet, login, svc, RAD_ACCT_STOP_PACKET))
+ return -1;
+ }
+else if (type == "Interim-Update")
+ {
+ if (Request(&packet, login, svc, RAD_ACCT_UPDATE_PACKET))
+ return -1;
+ }
+else
+ {
+ if (Request(&packet, login, svc, RAD_ACCT_OTHER_PACKET))
+ return -1;
+ }
+
+if (packet.packetType != RAD_ACCEPT_PACKET)
+ return -1;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+void STG_CLIENT::Encrypt(char * dst, const char * src, int len8)
+{
+// len8 - длина в 8-ми байтовых блоках
+if (dst != src)
+ memcpy(dst, src, len8 * 8);
+
+for (int i = 0; i < len8; i++)
+ Blowfish_Encrypt(&ctx, (uint32_t *)(dst + i*8), (uint32_t *)(dst + i*8 + 4));
+}
+//-----------------------------------------------------------------------------
+void STG_CLIENT::Decrypt(char * dst, const char * src, int len8)
+{
+// len8 - длина в 8-ми байтовых блоках
+if (dst != src)
+ memcpy(dst, src, len8 * 8);
+
+for (int i = 0; i < len8; i++)
+ Blowfish_Decrypt(&ctx, (uint32_t *)(dst + i*8), (uint32_t *)(dst + i*8 + 4));
+}
+//-----------------------------------------------------------------------------
--- /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>
+ */
+
+/*
+ * Header file for client part of data access via Stargazer for RADIUS
+ *
+ * $Revision: 1.4 $
+ * $Date: 2010/04/16 12:30:02 $
+ *
+ */
+
+#ifndef STG_CLIENT_H
+#define STG_CLIENT_H
+
+#include <string>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/socket.h> // socklen_t
+
+#include "blowfish.h"
+#include "rad_packets.h"
+
+class STG_CLIENT
+{
+public:
+ STG_CLIENT();
+ ~STG_CLIENT();
+
+ void SetServer(const std::string & host);
+ void SetPort(uint16_t port);
+ void SetLocalPort(uint16_t port);
+ void SetPassword(const std::string & password);
+
+ int Start();
+ int Stop();
+
+ std::string GetUserPassword() const;
+
+ int Authorize(const std::string & login, const std::string & svc);
+ int Authenticate(const std::string & login, const std::string & svc);
+ int PostAuthenticate(const std::string & login, const std::string & svc);
+ int Account(const std::string & type, const std::string & login, const std::string & svc, const std::string & sessid);
+
+ uint32_t GetFramedIP() const;
+
+
+ const std::string & GetError() const { return errorStr; };
+
+private:
+ std::string host;
+ uint16_t port;
+ uint16_t localPort;
+ std::string password;
+ int sock;
+ std::string errorStr;
+
+ struct sockaddr_in outerAddr;
+ socklen_t outerAddrLen;
+
+ std::string userPassword;
+
+ uint32_t framedIP;
+
+ BLOWFISH_CTX ctx;
+
+ int PrepareNet();
+ void FinalizeNet();
+
+ void InitEncrypt();
+ void Encrypt(char * dst, const char * src, int len8);
+ void Decrypt(char * dst, const char * src, int len8);
+
+ int Request(RAD_PACKET * packet, const std::string & login, const std::string & svc, uint8_t packetType);
+
+ int RecvData(RAD_PACKET * packet);
+ int Send(const RAD_PACKET & packet);
+
+};
+
+#endif
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.18 2010/02/11 12:22:01 faust Exp $
+###############################################################################
+
+include ../../Makefile.conf
+
+PROG = rscriptd
+
+SRCS = ./main.cpp \
+ ./listener.cpp \
+ ./pidfile.cpp
+
+STGLIBS = -lstg_logger \
+ -lstg_common \
+ -lstg_crypto \
+ -lscript_executer \
+ -lconffiles
+
+LIBS += $(LIB_THREAD)
+
+#ifeq ($(OS),linux)
+#LIBS += -ldl
+#else
+#LIBS += -lc
+#endif
+
+SEARCH_DIRS = -I $(DIR_INCLUDE)
+
+OBJS = $(notdir $(patsubst %.cpp, %.o, $(patsubst %.c, %.o, $(SRCS))))
+
+CXXFLAGS += -Wall
+LDFLAGS += -Wl,-E -L$(DIR_LIB) -Wl,-rpath,$(PREFIX)/usr/lib/stg -Wl,-rpath-link,$(DIR_LIB)
+
+vpath %.so $(DIR_LIB)
+
+.PHONY: all clean distclean libs install uninstall
+all: libs $(PROG) ../../Makefile.conf
+
+libs:
+ $(MAKE) -C $(DIR_LIBSRC)
+
+$(PROG): $(OBJS) $(STGLIBS)
+ $(CC) $^ $(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*
+ $(MAKE) -C $(DIR_LIBSRC) clean
+
+distclean: clean
+ rm -f ../../Makefile.conf
+
+install: install-bin install-data
+
+install-bin:
+ mkdir -m $(BIN_MODE) -p $(PREFIX)/usr/sbin
+ install -m $(BIN_MODE) -o $(OWNER) -s $(PROG) $(PREFIX)/usr/sbin/$(PROG)
+ $(MAKE) -C $(DIR_LIBSRC) install
+
+install-data:
+ # Install etc
+ mkdir -m $(DATA_MODE) -p $(PREFIX)/etc/stargazer
+ install -m $(DATA_MODE) -o $(OWNER) ./rscriptd.conf $(PREFIX)/etc/stargazer/rscriptd.conf
+
+uninstall: uninstall-bin uninstall-data
+
+uninstall-bin:
+ rm -f $(PREFIX)/usr/sbin/$(PROG)
+
+uninstall-data:
+ # Uninstall etc
+ rm -f $(PREFIX)/etc/stragazer/rscriptd.conf
+
+
+ifneq ($(MAKECMDGOALS),distclean)
+ifneq ($(MAKECMDGOALS),clean)
+ifneq ($(MAKECMDGOALS),uninstall)
+-include deps
+endif
+endif
+endif
+
+deps: $(SRCS) ../../Makefile.conf
+ $(MAKE) -C $(DIR_LIBSRC) includes
+ @>deps ;\
+ for file in $(SRCS); do\
+ echo "`$(CC) $(CXXFLAGS) $(SEARCH_DIRS) -MM $$file` Makefile" >> deps ;\
+ echo -e '\t$$(CC) -c $$< $(CXXFLAGS) $(SEARCH_DIRS) $(DEFS)' >> deps ;\
+ done
+
+
--- /dev/null
+#!/bin/sh
+
+# $Author: faust $
+# $Revision: 1.21 $
+# $Date: 2010/04/14 08:58:52 $
+######################################################
+
+OS=unknown
+sys=`uname -s`
+release=`uname -r | cut -b1`
+BUILD_DIR=`pwd`
+CONFFILE="../../Makefile.conf"
+PREFIX="/"
+BIN_MODE=0755
+DATA_MODE=0644
+OWNER=root
+
+if [ -z $1 ]
+then
+ MAKEOPTS="-j1"
+else
+ if [ "$1" = "debug" ]
+ then
+ DEFS="-DDEBUG"
+ MAKEOPTS="-j1"
+ CXXFLAGS="$CXXFLAGS -g3 -W -Wall"
+ else
+ MAKEOPTS="-j1"
+ fi
+fi
+
+CXXFLAGS="$CXXFLAGS -I/usr/local/include"
+LDFLAGS="$LDFLAGS -L/usr/local/lib"
+
+if [ "$sys" = "Linux" ]
+then
+ OS=linux
+ release=""
+ MAKE="make"
+fi
+
+if [ "$sys" = "FreeBSD" ]
+then
+ case $release in
+ 4) OS=bsd;;
+ 5) OS=bsd5;;
+ 6) OS=bsd5;;
+ 7) OS=bsd7;;
+ 8) OS=bsd7;;
+ *) OS=unknown;;
+ esac
+ MAKE="gmake"
+fi
+
+if [ "$OS" = "unknown" ]
+then
+ echo "#############################################################################"
+ echo "# Sorry, but rscriptd currently supported by Linux, FreeBSD 4.x, 5.x, 6.x #"
+ echo "#############################################################################"
+ exit 1
+fi
+
+echo "#############################################################################"
+echo " Building rscriptd for $sys $release"
+echo "#############################################################################"
+
+STG_LIBS="stg_logger.lib
+ stg_locker.lib
+ crypto.lib
+ common.lib
+ script_executer.lib
+ conffiles.lib"
+
+if [ "$OS" = "linux" ]
+then
+ DEFS="$DEFS -DLINUX"
+ LIB_THREAD=-lpthread
+ SHELL="/bin/bash"
+else
+ if [ "$OS" = "bsd" ]
+ then
+ DEFS="$DEFS -DFREE_BSD"
+ LIB_THREAD=-lc_r
+ else
+ DEFS="$DEFS -DFREE_BSD5"
+ if [ "$OS" = "bsd7" ]
+ then
+ LIB_THREAD=-lpthread
+ else
+ LIB_THREAD=-lc_r
+ fi
+ fi
+ SHELL="/usr/local/bin/bash"
+fi
+
+echo -n "Checking endianess... "
+echo "int main() { int probe = 0x00000001; return *(char *)&probe; }" > build_check.c
+gcc $CXXFLAGS $LDFLAGS build_check.c -o fake > /dev/null 2> /dev/null
+if [ $? != 0 ]
+then
+ echo "FAIL!"
+ echo "Endianess checking failed"
+ exit;
+else
+ ./fake
+ if [ $? = 1 ]
+ then
+ ARCH=le
+ CXXFLAGS="$CXXFLAGS -DARCH_LE"
+ echo "Little Endian"
+ else
+ ARCH=be
+ CXXFLAGS="$CXXFLAGS -DARCH_BE"
+ echo "Big Endian"
+ fi
+fi
+rm -f fake
+rm -f build_check.c
+
+echo "OS=$OS" > $CONFFILE
+echo "STG_TIME=yes" >> $CONFFILE
+echo "DIR_BUILD=$BUILD_DIR" >> $CONFFILE
+echo "DIR_LIB=\$(DIR_BUILD)/../../lib" >> $CONFFILE
+echo "DIR_LIBSRC=\$(DIR_BUILD)/../../stglibs" >> $CONFFILE
+echo "DIR_INCLUDE=\$(DIR_BUILD)/../../include" >> $CONFFILE
+echo "ARCH=$ARCH" >> $CONFFILE
+echo "DEFS=$DEFS" >> $CONFFILE
+echo -n "STG_LIBS=" >> $CONFFILE
+for lib in $STG_LIBS
+do
+ echo -n "$lib " >> $CONFFILE
+done
+echo "" >> $CONFFILE
+echo "LIB_THREAD=$LIB_THREAD" >> $CONFFILE
+echo "SHELL=$SHELL" >> $CONFFILE
+echo "CXXFLAGS=$CXXFLAGS" >> $CONFFILE
+echo "LDFLAGS=$LDFLAGS" >> $CONFFILE
+echo "PREFIX=$PREFIX" >> $CONFFILE
+echo "BIN_MODE=$BIN_MODE" >> $CONFFILE
+echo "DATA_MODE=$DATA_MODE" >> $CONFFILE
+echo "OWNER=$OWNER" >> $CONFFILE
+
+$MAKE $MAKEOPTS
+
--- /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 : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#include <arpa/inet.h>
+#include <sys/uio.h> // readv
+#include <sys/types.h> // for historical versions of BSD
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <unistd.h>
+
+#include <csignal>
+#include <ctime>
+#include <cstring>
+#include <sstream>
+#include <algorithm>
+
+#include "listener.h"
+#include "script_executer.h"
+#include "stg_locker.h"
+#include "common.h"
+
+//-----------------------------------------------------------------------------
+LISTENER::LISTENER()
+ : WriteServLog(GetStgLogger()),
+ port(0),
+ running(false),
+ receiverStopped(true),
+ processorStopped(true),
+ userTimeout(0),
+ listenSocket(0)
+{
+version = "rscriptd listener v.1.2";
+
+pthread_mutex_init(&mutex, NULL);
+}
+//-----------------------------------------------------------------------------
+void LISTENER::SetPassword(const string & p)
+{
+password = p;
+printfd(__FILE__, "Encryption initiated with password \'%s\'\n", password.c_str());
+InitEncrypt(&ctxS, password);
+}
+//-----------------------------------------------------------------------------
+bool LISTENER::Start()
+{
+printfd(__FILE__, "LISTENER::Start()\n");
+running = true;
+
+if (PrepareNet())
+ {
+ return true;
+ }
+
+if (receiverStopped)
+ {
+ if (pthread_create(&receiverThread, NULL, Run, this))
+ {
+ errorStr = "Cannot create thread.";
+ return true;
+ }
+ }
+
+if (processorStopped)
+ {
+ if (pthread_create(&processorThread, NULL, RunProcessor, this))
+ {
+ errorStr = "Cannot create thread.";
+ return true;
+ }
+ }
+
+errorStr = "";
+
+return false;
+}
+//-----------------------------------------------------------------------------
+bool LISTENER::Stop()
+{
+running = false;
+
+printfd(__FILE__, "LISTENER::Stop()\n");
+
+usleep(500000);
+
+if (!processorStopped)
+ {
+ //5 seconds to thread stops itself
+ for (int i = 0; i < 25 && !processorStopped; i++)
+ {
+ usleep(200000);
+ }
+
+ //after 5 seconds waiting thread still running. now killing it
+ if (!processorStopped)
+ {
+ //TODO pthread_cancel()
+ if (pthread_kill(processorThread, SIGINT))
+ {
+ errorStr = "Cannot kill thread.";
+ return true;
+ }
+ printfd(__FILE__, "LISTENER killed Timeouter\n");
+ }
+ }
+
+if (!receiverStopped)
+ {
+ //5 seconds to thread stops itself
+ for (int i = 0; i < 25 && !receiverStopped; i++)
+ {
+ usleep(200000);
+ }
+
+ //after 5 seconds waiting thread still running. now killing it
+ if (!receiverStopped)
+ {
+ //TODO pthread_cancel()
+ if (pthread_kill(receiverThread, SIGINT))
+ {
+ errorStr = "Cannot kill thread.";
+ return true;
+ }
+ printfd(__FILE__, "LISTENER killed Run\n");
+ }
+ }
+
+pthread_join(receiverThread, NULL);
+pthread_join(processorThread, NULL);
+
+pthread_mutex_destroy(&mutex);
+
+FinalizeNet();
+
+std::for_each(users.begin(), users.end(), DisconnectUser(*this));
+
+printfd(__FILE__, "LISTENER::Stoped successfully.\n");
+
+return false;
+}
+//-----------------------------------------------------------------------------
+void * LISTENER::Run(void * d)
+{
+LISTENER * ia = static_cast<LISTENER *>(d);
+
+ia->Runner();
+
+return NULL;
+}
+//-----------------------------------------------------------------------------
+void LISTENER::Runner()
+{
+receiverStopped = false;
+
+while (running)
+ {
+ RecvPacket();
+ }
+
+receiverStopped = true;
+}
+//-----------------------------------------------------------------------------
+void * LISTENER::RunProcessor(void * d)
+{
+LISTENER * ia = static_cast<LISTENER *>(d);
+
+ia->ProcessorRunner();
+
+return NULL;
+}
+//-----------------------------------------------------------------------------
+void LISTENER::ProcessorRunner()
+{
+processorStopped = false;
+
+while (running)
+ {
+ usleep(500000);
+ if (!pending.empty())
+ ProcessPending();
+ ProcessTimeouts();
+ }
+
+processorStopped = true;
+}
+//-----------------------------------------------------------------------------
+bool LISTENER::PrepareNet()
+{
+listenSocket = socket(AF_INET, SOCK_DGRAM, 0);
+
+if (listenSocket < 0)
+ {
+ errorStr = "Cannot create socket.";
+ return true;
+ }
+
+printfd(__FILE__, "Port: %d\n", port);
+
+struct sockaddr_in listenAddr;
+listenAddr.sin_family = AF_INET;
+listenAddr.sin_port = htons(port);
+listenAddr.sin_addr.s_addr = inet_addr("0.0.0.0");
+
+if (bind(listenSocket, (struct sockaddr*)&listenAddr, sizeof(listenAddr)) < 0)
+ {
+ errorStr = "LISTENER: Bind failed.";
+ return true;
+ }
+
+printfd(__FILE__, "LISTENER::PrepareNet() >>>> Start successfull.\n");
+
+return false;
+}
+//-----------------------------------------------------------------------------
+bool LISTENER::FinalizeNet()
+{
+close(listenSocket);
+
+return false;
+}
+//-----------------------------------------------------------------------------
+bool LISTENER::RecvPacket()
+{
+struct iovec iov[2];
+
+char buffer[RS_MAX_PACKET_LEN];
+RS_PACKET_HEADER packetHead;
+
+iov[0].iov_base = reinterpret_cast<char *>(&packetHead);
+iov[0].iov_len = sizeof(packetHead);
+iov[1].iov_base = buffer;
+iov[1].iov_len = sizeof(buffer);
+
+size_t dataLen = 0;
+while (dataLen < sizeof(buffer))
+ {
+ if (!WaitPackets(listenSocket))
+ {
+ if (!running)
+ return false;
+ continue;
+ }
+ int portion = readv(listenSocket, iov, 2);
+ if (portion < 0)
+ {
+ return true;
+ }
+ dataLen += portion;
+ }
+
+if (CheckHeader(packetHead))
+ {
+ printfd(__FILE__, "Invalid packet or incorrect protocol version!\n");
+ return true;
+ }
+
+std::string userLogin((char *)packetHead.login);
+PendingData data;
+data.login = userLogin;
+data.ip = ntohl(packetHead.ip);
+data.id = ntohl(packetHead.id);
+
+if (packetHead.packetType == RS_ALIVE_PACKET)
+ {
+ data.type = PendingData::ALIVE;
+ }
+else if (packetHead.packetType == RS_CONNECT_PACKET)
+ {
+ data.type = PendingData::CONNECT;
+ if (GetParams(buffer, data))
+ {
+ return true;
+ }
+ }
+else if (packetHead.packetType == RS_DISCONNECT_PACKET)
+ {
+ data.type = PendingData::DISCONNECT;
+ if (GetParams(buffer, data))
+ {
+ return true;
+ }
+ }
+
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+pending.push_back(data);
+
+return false;
+}
+//-----------------------------------------------------------------------------
+bool LISTENER::GetParams(char * buffer, UserData & data)
+{
+RS_PACKET_TAIL packetTail;
+
+Decrypt(&ctxS, (char *)&packetTail, buffer, sizeof(packetTail) / 8);
+
+if (strncmp((char *)packetTail.magic, RS_ID, RS_MAGIC_LEN))
+ {
+ printfd(__FILE__, "Invalid crypto magic\n");
+ return true;
+ }
+
+std::stringstream params;
+params << data.login << " "
+ << inet_ntostring(data.ip) << " "
+ << ntohl(data.id) << " "
+ << (char *)packetTail.params;
+
+data.params = params.str();
+
+return false;
+}
+//-----------------------------------------------------------------------------
+void LISTENER::ProcessPending()
+{
+printfd(__FILE__, "Pending data size: %d\n", pending.size());
+std::list<PendingData>::iterator it(pending.begin());
+while (it != pending.end())
+ {
+ std::vector<AliveData>::iterator uit(
+ std::lower_bound(
+ users.begin(),
+ users.end(),
+ it->login)
+ );
+ if (it->type == PendingData::CONNECT)
+ {
+ if (uit == users.end() || uit->login != it->login)
+ {
+ // Add new user
+ Connect(*it);
+ users.insert(uit, AliveData(static_cast<UserData>(*it)));
+ }
+ else if (uit->login == it->login)
+ {
+ // Update already existing user
+ time(&uit->lastAlive);
+ uit->params = it->params;
+ }
+ }
+ else if (it->type == PendingData::ALIVE)
+ {
+ if (uit != users.end() && uit->login == it->login)
+ {
+ // Update existing user
+ time(&uit->lastAlive);
+ }
+ }
+ else if (it->type == PendingData::DISCONNECT)
+ {
+ if (uit != users.end() && uit->login == it->login.c_str())
+ {
+ // Disconnect existing user
+ Disconnect(*uit);
+ users.erase(uit);
+ }
+ }
+
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ pending.erase(it++);
+ }
+}
+//-----------------------------------------------------------------------------
+void LISTENER::ProcessTimeouts()
+{
+const std::vector<AliveData>::iterator it(
+ std::stable_partition(
+ users.begin(),
+ users.end(),
+ IsNotTimedOut(userTimeout)
+ )
+ );
+
+if (it != users.end())
+ {
+ printfd(__FILE__, "Total users: %d, users to disconnect: %d\n", users.size(), std::distance(it, users.end()));
+
+ std::for_each(
+ it,
+ users.end(),
+ DisconnectUser(*this)
+ );
+
+ users.erase(it, users.end());
+ }
+}
+//-----------------------------------------------------------------------------
+bool LISTENER::Connect(const UserData & data) const
+{
+printfd(__FILE__, "Connect %s\n", data.login.c_str());
+if (access(scriptOnConnect.c_str(), X_OK) == 0)
+ {
+ if (ScriptExec(scriptOnConnect + " " + data.params))
+ {
+ WriteServLog("Script %s cannot be executed for an unknown reason.", scriptOnConnect.c_str());
+ return true;
+ }
+ }
+else
+ {
+ WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
+ return true;
+ }
+return false;
+}
+//-----------------------------------------------------------------------------
+bool LISTENER::Disconnect(const UserData & data) const
+{
+printfd(__FILE__, "Disconnect %s\n", data.login.c_str());
+if (access(scriptOnDisconnect.c_str(), X_OK) == 0)
+ {
+ if (ScriptExec(scriptOnDisconnect + " " + data.params))
+ {
+ WriteServLog("Script %s cannot be executed for an unknown reson.", scriptOnDisconnect.c_str());
+ return true;
+ }
+ }
+else
+ {
+ WriteServLog("Script %s cannot be executed. File not found.", scriptOnDisconnect.c_str());
+ return true;
+ }
+return false;
+}
+//-----------------------------------------------------------------------------
+void LISTENER::InitEncrypt(BLOWFISH_CTX * ctx, const string & password)
+{
+unsigned char keyL[PASSWD_LEN];
+memset(keyL, 0, PASSWD_LEN);
+strncpy((char *)keyL, password.c_str(), PASSWD_LEN);
+Blowfish_Init(ctx, keyL, PASSWD_LEN);
+}
+//-----------------------------------------------------------------------------
+void LISTENER::Decrypt(BLOWFISH_CTX * ctx, char * dst, const char * src, int len8)
+{
+if (dst != src)
+ memcpy(dst, src, len8 * 8);
+
+for (int i = 0; i < len8; i++)
+ Blowfish_Decrypt(ctx, (uint32_t *)(dst + i * 8), (uint32_t *)(dst + i * 8 + 4));
+}
+//-----------------------------------------------------------------------------
+bool LISTENER::CheckHeader(const RS_PACKET_HEADER & header) const
+{
+if (strncmp((char *)header.magic, RS_ID, RS_MAGIC_LEN))
+ {
+ return true;
+ }
+if (strncmp((char *)header.protoVer, "02", RS_PROTO_VER_LEN))
+ {
+ return true;
+ }
+return false;
+}
+//-----------------------------------------------------------------------------
+bool LISTENER::WaitPackets(int sd) const
+{
+fd_set rfds;
+FD_ZERO(&rfds);
+FD_SET(sd, &rfds);
+
+struct timeval tv;
+tv.tv_sec = 0;
+tv.tv_usec = 500000;
+
+int res = select(sd + 1, &rfds, NULL, NULL, &tv);
+if (res == -1) // Error
+ {
+ if (errno != EINTR)
+ {
+ printfd(__FILE__, "Error on select: '%s'\n", strerror(errno));
+ }
+ return false;
+ }
+
+if (res == 0) // Timeout
+ {
+ return false;
+ }
+
+return true;
+}
+//-----------------------------------------------------------------------------
--- /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 : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#include <pthread.h>
+
+#include <string>
+#include <vector>
+#include <list>
+#include <functional>
+
+#include "os_int.h"
+#include "blowfish.h"
+#include "rs_packets.h"
+#include "stg_logger.h"
+
+struct UserData
+{
+ std::string params;
+ std::string login;
+ uint32_t ip;
+ uint32_t id;
+};
+
+struct PendingData : public UserData
+{
+ enum {CONNECT, ALIVE, DISCONNECT} type;
+};
+
+struct AliveData : public UserData
+{
+ explicit AliveData(const UserData & data)
+ : UserData(data),
+ lastAlive(time(NULL))
+ {};
+ bool operator<(const std::string & rvalue) const { return login < rvalue; };
+ time_t lastAlive;
+};
+
+class IsNotTimedOut : public std::unary_function<const AliveData &, bool> {
+ public:
+ IsNotTimedOut(double to) : timeout(to), now(time(NULL)) {}
+ bool operator()(const AliveData & data) const
+ {
+ return difftime(now, data.lastAlive) < timeout;
+ }
+ private:
+ double timeout;
+ time_t now;
+};
+
+class LISTENER
+{
+public:
+ LISTENER();
+ ~LISTENER(){};
+
+ void SetPort(uint16_t p) { port = p; };
+ void SetPassword(const std::string & p);
+ void SetUserTimeout(int t) { userTimeout = t; };
+ void SetScriptOnConnect(const std::string & script) { scriptOnConnect = script; };
+ void SetScriptOnDisconnect(const std::string & script) { scriptOnDisconnect = script; };
+
+ bool Start();
+ bool Stop();
+ bool IsRunning() const { return !receiverStopped && !processorStopped; };
+
+ const std::string & GetStrError() const { return errorStr; };
+ const std::string & GetVersion() const { return version; };
+
+private:
+ // Threading stuff
+ static void * Run(void * self);
+ static void * RunProcessor(void * self);
+ void Runner();
+ void ProcessorRunner();
+ // Networking stuff
+ bool PrepareNet();
+ bool FinalizeNet();
+ bool WaitPackets(int sd) const;
+ bool RecvPacket();
+ // Parsing stuff
+ bool CheckHeader(const RS_PACKET_HEADER & header) const;
+ bool GetParams(char * buffer, UserData & data);
+ // Processing stuff
+ void ProcessPending();
+ void ProcessTimeouts();
+ bool Disconnect(const UserData & data) const;
+ bool Connect(const UserData & data) const;
+ // Decryption stuff
+ void InitEncrypt(BLOWFISH_CTX * ctx, const std::string & password);
+ void Decrypt(BLOWFISH_CTX * ctx, char * dst, const char * src, int len8);
+
+ BLOWFISH_CTX ctxS;
+ STG_LOGGER & WriteServLog;
+
+ mutable std::string errorStr;
+ std::string scriptOnConnect;
+ std::string scriptOnDisconnect;
+ std::string password;
+ uint16_t port;
+
+ bool running;
+ bool receiverStopped;
+ bool processorStopped;
+ std::vector<AliveData> users;
+ std::list<PendingData> pending;
+ int userTimeout;
+
+ pthread_t receiverThread;
+ pthread_t processorThread;
+ pthread_mutex_t mutex;
+
+ int listenSocket;
+
+ std::string version;
+
+ friend class DisconnectUser;
+};
+
+class DisconnectUser : public std::unary_function<const UserData &, void> {
+ public:
+ DisconnectUser(LISTENER & l) : listener(l) {};
+ void operator()(const UserData & data)
+ {
+ listener.Disconnect(data);
+ };
+ private:
+ LISTENER & listener;
+};
+//-----------------------------------------------------------------------------
--- /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 : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+ /*
+ $Revision: 1.19 $
+ $Author: faust $
+ $Date: 2010/09/10 06:37:45 $
+ */
+
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <fcntl.h> // creat
+#include <unistd.h>
+
+#include <cstdlib>
+#include <csignal>
+#include <set>
+
+#include "common.h"
+#include "stg_logger.h"
+#include "script_executer.h"
+#include "conffiles.h"
+#include "listener.h"
+#include "pidfile.h"
+#include "version.h"
+
+using namespace std;
+
+#ifdef DEBUG
+# define MAIN_DEBUG 1
+# define NO_DAEMON 1
+#endif
+
+#define START_FILE "/._ST_ART_ED_"
+
+static bool childExited = false;
+set<pid_t> executersPid;
+static pid_t stgChildPid;
+volatile time_t stgTime = time(NULL);
+
+class STG_STOPPER
+{
+public:
+ STG_STOPPER() { nonstop = true; }
+ bool GetStatus() const { return nonstop; };
+ void Stop(const char * __file__, int __line__)
+ {
+ #ifdef NO_DAEMON
+ printfd(__FILE__, "rscriptd stopped at %s:%d\n", __file__, __line__);
+ #endif
+ nonstop = false;
+ }
+private:
+ bool nonstop;
+};
+//-----------------------------------------------------------------------------
+STG_STOPPER nonstop;
+//-----------------------------------------------------------------------------
+void CatchPROF(int)
+{
+}
+//-----------------------------------------------------------------------------
+void CatchUSR1(int)
+{
+}
+//-----------------------------------------------------------------------------
+void CatchTERM(int sig)
+{
+/*
+ *Function Name:CatchINT
+ *Parameters: sig_num - signal number
+ *Description: INT signal handler
+ *Returns: Nothing
+ */
+STG_LOGGER & WriteServLog = GetStgLogger();
+WriteServLog("Shutting down... %d", sig);
+
+nonstop.Stop(__FILE__, __LINE__);
+
+struct sigaction newsa, oldsa;
+sigset_t sigmask;
+
+sigemptyset(&sigmask);
+sigaddset(&sigmask, SIGTERM);
+newsa.sa_handler = SIG_IGN;
+newsa.sa_mask = sigmask;
+newsa.sa_flags = 0;
+sigaction(SIGTERM, &newsa, &oldsa);
+
+sigemptyset(&sigmask);
+sigaddset(&sigmask, SIGINT);
+newsa.sa_handler = SIG_IGN;
+newsa.sa_mask = sigmask;
+newsa.sa_flags = 0;
+sigaction(SIGINT, &newsa, &oldsa);
+}
+//-----------------------------------------------------------------------------
+void CatchPIPE(int)
+{
+STG_LOGGER & WriteServLog = GetStgLogger();
+WriteServLog("Broken pipe!");
+}
+//-----------------------------------------------------------------------------
+void CatchHUP(int)
+{
+}
+//-----------------------------------------------------------------------------
+void CatchCHLD(int)
+{
+int status;
+pid_t childPid;
+childPid = waitpid(-1, &status, WNOHANG);
+
+set<pid_t>::iterator pid;
+pid = executersPid.find(childPid);
+if (pid != executersPid.end())
+ {
+ executersPid.erase(pid);
+ }
+if (childPid == stgChildPid)
+ {
+ childExited = true;
+ }
+}
+//-----------------------------------------------------------------------------
+void SetSignalHandlers()
+{
+struct sigaction newsa, oldsa;
+sigset_t sigmask;
+
+sigemptyset(&sigmask);
+sigaddset(&sigmask, SIGTERM);
+newsa.sa_handler = CatchTERM;
+newsa.sa_mask = sigmask;
+newsa.sa_flags = 0;
+sigaction(SIGTERM, &newsa, &oldsa);
+
+sigemptyset(&sigmask);
+sigaddset(&sigmask, SIGUSR1);
+newsa.sa_handler = CatchUSR1;
+newsa.sa_mask = sigmask;
+newsa.sa_flags = 0;
+sigaction(SIGUSR1, &newsa, &oldsa);
+
+sigemptyset(&sigmask);
+sigaddset(&sigmask, SIGINT);
+newsa.sa_handler = CatchTERM;
+newsa.sa_mask = sigmask;
+newsa.sa_flags = 0;
+sigaction(SIGINT, &newsa, &oldsa);
+
+sigemptyset(&sigmask);
+sigaddset(&sigmask, SIGPIPE);
+newsa.sa_handler = CatchPIPE;
+newsa.sa_mask = sigmask;
+newsa.sa_flags = 0;
+sigaction(SIGPIPE, &newsa, &oldsa);
+
+sigemptyset(&sigmask);
+sigaddset(&sigmask, SIGHUP);
+newsa.sa_handler = CatchHUP;
+newsa.sa_mask = sigmask;
+newsa.sa_flags = 0;
+sigaction(SIGHUP, &newsa, &oldsa);
+
+sigemptyset(&sigmask);
+sigaddset(&sigmask, SIGCHLD);
+newsa.sa_handler = CatchCHLD;
+newsa.sa_mask = sigmask;
+newsa.sa_flags = 0;
+sigaction(SIGCHLD, &newsa, &oldsa);
+}
+//-----------------------------------------------------------------------------
+int StartScriptExecuter(char * procName, int msgKey, int * msgID)
+{
+STG_LOGGER & WriteServLog = GetStgLogger();
+
+if (*msgID == -11) // If msgID == -11 - first call. Create queue
+ {
+ for (int i = 0; i < 2; i++)
+ {
+ *msgID = msgget(msgKey, IPC_CREAT | IPC_EXCL | 0600);
+
+ if (*msgID == -1)
+ {
+ *msgID = msgget(msgKey, 0);
+ if (*msgID == -1)
+ {
+ WriteServLog("Message queue not created.");
+ return -1;
+ }
+ else
+ {
+ msgctl(*msgID, IPC_RMID, NULL);
+ }
+ }
+ else
+ {
+ WriteServLog("Message queue created successfully. msgKey=%d msgID=%d", msgKey, *msgID);
+ break;
+ }
+ }
+ }
+
+pid_t executerPid = fork();
+
+switch (executerPid)
+ {
+ case -1: // Failure
+ WriteServLog("Fork error!");
+ return -1;
+
+ case 0: // Child
+ //close(0);
+ //close(1);
+ //close(2);
+ //setsid();
+ Executer(msgKey, *msgID, executerPid, procName);
+ return 1;
+
+ default: // Parent
+ if (executersPid.empty())
+ Executer(msgKey, *msgID, executerPid, NULL);
+ executersPid.insert(executerPid);
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+#ifdef NO_DAEMON
+int ForkAndWait(const string &)
+#else
+int ForkAndWait(const string & confDir)
+#endif
+{
+#ifndef NO_DAEMON
+stgChildPid = fork();
+string startFile = confDir + START_FILE;
+unlink(startFile.c_str());
+
+switch (stgChildPid)
+ {
+ case -1: // Failure
+ return -1;
+ break;
+
+ case 0: // Child
+ //close(0);
+ close(1);
+ close(2);
+ setsid();
+ break;
+
+ default: // Parent
+ for (int i = 0; i < 120 * 5; i++)
+ {
+ if (access(startFile.c_str(), F_OK) == 0)
+ {
+ //printf("Fork successfull. Exit.\n");
+ unlink(startFile.c_str());
+ exit(0);
+ }
+
+ if (childExited)
+ {
+ unlink(startFile.c_str());
+ exit(1);
+ }
+ usleep(200000);
+ }
+ unlink(startFile.c_str());
+ exit(1);
+ break;
+ }
+#endif
+return 0;
+}
+//-----------------------------------------------------------------------------
+void KillExecuters()
+{
+set<pid_t>::iterator pid;
+pid = executersPid.begin();
+while (pid != executersPid.end())
+ {
+ printfd(__FILE__, "KillExecuters pid=%d\n", *pid);
+ kill(*pid, SIGUSR1);
+ ++pid;
+ }
+}
+//-----------------------------------------------------------------------------
+int main(int argc, char * argv[])
+{
+
+/*
+ Initialization order:
+ - Logger
+ - Config
+ - Set signal nandlers
+ - Fork and exit
+ */
+
+CONFIGFILE * cfg = NULL;
+LISTENER * listener = NULL;
+int msgID = -11;
+int execNum = 0;
+int execMsgKey = 0;
+
+string logFileName;
+string confDir;
+string password;
+string onConnect;
+string onDisconnect;
+int port;
+int userTimeout;
+
+if (getuid())
+ {
+ printf("You must be root. Exit.\n");
+ exit(1);
+ }
+
+if (argc == 2)
+ cfg = new CONFIGFILE(argv[1]);
+else
+ cfg = new CONFIGFILE("/etc/rscriptd/rscriptd.conf");
+
+if (cfg->Error())
+ {
+ STG_LOGGER & WriteServLog = GetStgLogger();
+ WriteServLog.SetLogFileName("/var/log/rscriptd.log");
+ WriteServLog("Error reading config file!");
+ delete cfg;
+ return EXIT_FAILURE;
+ }
+
+cfg->ReadString("LogFileName", &logFileName, "/var/log/rscriptd.log");
+cfg->ReadInt("ExecutersNum", &execNum, 1);
+cfg->ReadInt("ExecMsgKey", &execMsgKey, 5555);
+cfg->ReadString("ConfigDir", &confDir, "/etc/rscriptd");
+cfg->ReadString("Password", &password, "");
+cfg->ReadInt("Port", &port, 5555);
+cfg->ReadInt("UserTimeout", &userTimeout, 60);
+cfg->ReadString("ScriptOnConnect", &onConnect, "/etc/rscriptd/OnConnect");
+cfg->ReadString("ScriptOnDisconnect", &onDisconnect, "/etc/rscriptd/OnDisconnect");
+
+SetSignalHandlers();
+if (ForkAndWait(confDir) < 0)
+ {
+ STG_LOGGER & WriteServLog = GetStgLogger();
+ WriteServLog("Fork error!");
+ delete cfg;
+ return EXIT_FAILURE;
+ }
+
+STG_LOGGER & WriteServLog = GetStgLogger();
+PIDFile pidFile("/var/run/rscriptd.pid");
+WriteServLog.SetLogFileName(logFileName);
+WriteServLog("rscriptd v. %s", SERVER_VERSION);
+
+for (int i = 0; i < execNum; i++)
+ {
+ int ret = StartScriptExecuter(argv[0], execMsgKey, &msgID);
+ if (ret < 0)
+ {
+ STG_LOGGER & WriteServLog = GetStgLogger();
+ WriteServLog("Start Script Executer error!");
+ delete cfg;
+ return EXIT_FAILURE;
+ }
+ if (ret == 1)
+ {
+ delete cfg;
+ return EXIT_SUCCESS;
+ }
+ }
+
+listener = new LISTENER();
+listener->SetPort(port);
+listener->SetPassword(password);
+listener->SetUserTimeout(userTimeout);
+listener->SetScriptOnConnect(onConnect);
+listener->SetScriptOnDisconnect(onDisconnect);
+
+listener->Start();
+
+WriteServLog("rscriptd started successfully.");
+WriteServLog("+++++++++++++++++++++++++++++++++++++++++++++");
+
+#ifndef NO_DAEMON
+string startFile(confDir + START_FILE);
+creat(startFile.c_str(), S_IRUSR);
+#endif
+
+while (nonstop.GetStatus())
+ {
+ usleep(100000);
+ }
+
+listener->Stop();
+
+WriteServLog("+++++++++++++++++++++++++++++++++++++++++++++");
+
+int res = msgctl(msgID, IPC_RMID, NULL);
+if (res)
+ WriteServLog("Queue was not removed. id=%d", msgID);
+else
+ WriteServLog("Queue removed successfully.");
+
+KillExecuters();
+
+WriteServLog("rscriptd stopped successfully.");
+WriteServLog("---------------------------------------------");
+
+delete listener;
+delete cfg;
+return EXIT_SUCCESS;
+}
+//-----------------------------------------------------------------------------
+
--- /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>
+ */
+
+/*
+ $Revision: 1.1 $
+ $Date: 2010/02/11 12:32:25 $
+ $Author: faust $
+ */
+
+/*
+ * An implementation of RAII pid-file writer
+ */
+
+#include <fstream>
+#include <unistd.h>
+
+#include "pidfile.h"
+
+PIDFile::PIDFile(const std::string & fn)
+ : fileName(fn)
+{
+if (fileName != "")
+ {
+ std::ofstream pf(fileName.c_str());
+ pf << getpid() << std::endl;
+ pf.close();
+ }
+}
+
+PIDFile::~PIDFile()
+{
+if (fileName != "")
+ {
+ unlink(fileName.c_str());
+ }
+}
--- /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>
+ */
+
+/*
+ * Header file for RAII pid-file writer
+ */
+
+/*
+ $Revision: 1.1 $
+ $Date: 2010/02/11 12:32:25 $
+ $Author: faust $
+ */
+
+#ifndef __PID_FILE_H__
+#define __PID_FILE_H__
+
+#include <string>
+
+class PIDFile {
+public:
+ PIDFile(const std::string & fn);
+ ~PIDFile();
+private:
+ std::string fileName;
+};
+
+#endif
--- /dev/null
+LogFileName=/var/log/rscriptd.log
+ExecutersNum=1
+ConfigDir=/etc/rscriptd
+Password=123456
+Port=9999
+UserTimeout=60
+ScriptOnConnect=/etc/rscriptd/OnConnect
+ScriptOnDisconnect=/etc/rscriptd/OnDisconnect
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.18 2009/08/06 12:50:55 faust Exp $
+###############################################################################
+
+include ../../Makefile.conf
+
+PROG = sgauth
+
+SRCS = ./main.cpp \
+ ./web.cpp
+
+STGLIBS = -lconffiles \
+ -lstg_crypto \
+ -lstg_common \
+ -lia_auth_c \
+ -lcommon_settings
+
+LIBS += $(LIB_THREAD) \
+ -lexpat
+
+ifeq ($(OS),linux)
+LIBS += -ldl
+else
+LIBS += -lintl \
+ -lc
+endif
+
+SEARCH_DIRS = -I $(DIR_INCLUDE)
+
+OBJS = $(notdir $(patsubst %.cpp, %.o, $(patsubst %.c, %.o, $(SRCS))))
+
+CXXFLAGS += -Wall
+LDFLAGS += -Wl,-E -L$(DIR_LIB) -Wl,-rpath,$(PREFIX)/usr/lib/stg -Wl,-rpath-link,$(DIR_LIB)
+
+vpath %.so $(DIR_LIB)
+
+.PHONY: all clean distclean libs install uninstall install-bin install-data uninstall-bin uninstall-data
+all: libs $(PROG) ../../Makefile.conf
+
+libs:
+ $(MAKE) -C $(DIR_LIBSRC)
+
+$(PROG): $(OBJS) $(STGLIBS)
+ $(CC) $^ $(LDFLAGS) -o $(PROG) $(LIBS)
+
+clean:
+ rm -f deps $(PROG) *.o tags *.*~ .OS
+ rm -f .OS
+ rm -f .store
+ rm -f .db.sql
+ rm -f core*
+ rm -f css.h
+ $(MAKE) -C $(DIR_LIBSRC) clean
+
+distclean: clean
+ rm -f ../../Makefile.conf
+
+install: install-bin install-data
+
+install-bin:
+ mkdir -m $(BIN_MODE) -p $(PREFIX)/usr/sbin
+ install -m $(BIN_MODE) -o $(OWNER) -s $(PROG) $(PREFIX)/usr/sbin/$(PROG)
+ $(MAKE) -C $(DIR_LIBSRC) install
+
+install-data:
+ # Install etc
+ mkdir -m $(DATA_MODE) -p $(PREFIX)/etc
+ install -m $(DATA_MODE) -o $(OWNER) ./sgauth.conf $(PREFIX)/etc/sgauth.conf
+
+uninstall: uninstall-bin uninstall-data
+
+uninstall-bin:
+ rm -f $(PREFIX)/usr/sbin/$(PROG)
+
+uninstall-data:
+ # Uninstall etc
+ rm -f $(PREFIX)/etc/stargazer/sgauth.conf
+
+
+ifneq ($(MAKECMDGOALS),distclean)
+ifneq ($(MAKECMDGOALS),clean)
+ifneq ($(MAKECMDGOALS),uninstall)
+-include deps
+endif
+endif
+endif
+
+deps: $(SRCS) ../../Makefile.conf sgauth.css
+ $(MAKE) -C $(DIR_LIBSRC) includes
+ @>deps ;\
+ ./make_css.sh
+ for file in $(SRCS); do\
+ echo "`$(CC) $(CXXFLAGS) $(SEARCH_DIRS) -MM $$file` Makefile" >> deps ;\
+ echo -e '\t$$(CC) -c $$< $(CXXFLAGS) $(SEARCH_DIRS) $(DEFS)' >> deps ;\
+ done
+
+
--- /dev/null
+#!/bin/sh
+
+# $Author: faust $
+# $Revision: 1.24 $
+# $Date: 2010/04/14 08:59:02 $
+######################################################
+
+OS=unknown
+sys=`uname -s`
+release=`uname -r | cut -b1`
+BUILD_DIR=`pwd`
+CONFFILE="../../Makefile.conf"
+PREFIX="/"
+BIN_MODE=0755
+DATA_MODE=0644
+OWNER=root
+
+if [ -z $1 ]
+then
+ MAKEOPTS="-j1"
+else
+ if [ "$1" = "debug" ]
+ then
+ DEFS="-DDEBUG"
+ MAKEOPTS="-j1"
+ CXXFLAGS="$CXXFLAGS -g3 -W -Wall"
+ else
+ MAKEOPTS="-j1"
+ fi
+fi
+
+CXXFLAGS="$CXXFLAGS -I/usr/local/include"
+LDFLAGS="$CXXFLAGS -L/usr/local/lib"
+
+if [ "$sys" = "Linux" ]
+then
+ OS=linux
+ release=""
+ MAKE="make"
+fi
+
+if [ "$sys" = "FreeBSD" ]
+then
+ case $release in
+ 4) OS=bsd;;
+ 5) OS=bsd5;;
+ 6) OS=bsd5;;
+ 7) OS=bsd7;;
+ 8) OS=bsd7;;
+ *) OS=unknown;;
+ esac
+ MAKE="gmake"
+fi
+
+if [ "$OS" = "unknown" ]
+then
+ echo "#############################################################################"
+ echo "# Sorry, but sgauth currently supported by Linux, FreeBSD 4.x, 5.x, 6.x #"
+ echo "#############################################################################"
+ exit 1
+fi
+
+echo "#############################################################################"
+echo " Building sgauth for $sys $release"
+echo "#############################################################################"
+
+STG_LIBS="crypto.lib
+ common.lib
+ common_settings.lib
+ conffiles.lib
+ ia_auth_c.lib"
+
+if [ "$OS" = "linux" ]
+then
+ DEFS="$DEFS -DLINUX"
+ LIB_THREAD=-lpthread
+ SHELL="/bin/bash"
+else
+ if [ "$OS" = "bsd" ]
+ then
+ DEFS="$DEFS -DFREE_BSD"
+ LIB_THREAD=-lc_r
+ else
+ DEFS="$DEFS -DFREE_BSD5"
+ if [ "$OS" = "bsd7" ]
+ then
+ LIB_THREAD=-lpthread
+ else
+ LIB_THREAD=-lc_r
+ fi
+ fi
+ SHELL="/usr/local/bin/bash"
+fi
+
+echo -n "Checking endianess... "
+echo "int main() { int probe = 0x00000001; return *(char *)&probe; }" > build_check.c
+gcc $CXXFLAGS $LDFLAGS build_check.c -o fake > /dev/null 2> /dev/null
+if [ $? != 0 ]
+then
+ echo "FAIL!"
+ echo "Endianess checking failed"
+ exit;
+else
+ ./fake
+ if [ $? = 1 ]
+ then
+ ARCH=le
+ CXXFLAGS="$CXXFLAGS -DARCH_LE"
+ echo "Little Endian"
+ else
+ ARCH=be
+ CXXFLAGS="$CXXFLAGS -DARCH_BE"
+ echo "Big Endian"
+ fi
+fi
+rm -f fake
+rm -f build_check.c
+
+echo "OS=$OS" > $CONFFILE
+echo "STG_TIME=yes" >> $CONFFILE
+echo "DIR_BUILD=$BUILD_DIR" >> $CONFFILE
+echo "DIR_LIB=\$(DIR_BUILD)/../../lib" >> $CONFFILE
+echo "DIR_LIBSRC=\$(DIR_BUILD)/../../stglibs" >> $CONFFILE
+echo "DIR_INCLUDE=\$(DIR_BUILD)/../../include" >> $CONFFILE
+echo "ARCH=$ARCH" >> $CONFFILE
+echo "DEFS=$DEFS" >> $CONFFILE
+echo -n "STG_LIBS=" >> $CONFFILE
+for lib in $STG_LIBS
+do
+ echo -n "$lib " >> $CONFFILE
+done
+echo "" >> $CONFFILE
+echo "LIB_THREAD=$LIB_THREAD" >> $CONFFILE
+echo "SHELL=$SHELL" >> $CONFFILE
+echo "CXXFLAGS=$CXXFLAGS" >> $CONFFILE
+echo "LDFLAGS=$LDFLAGS" >> $CONFFILE
+echo "PREFIX=$PREFIX" >> $CONFFILE
+echo "BIN_MODE=$BIN_MODE" >> $CONFFILE
+echo "DATA_MODE=$DATA_MODE" >> $CONFFILE
+echo "OWNER=$OWNER" >> $CONFFILE
+$MAKE $MAKEOPTS
+
--- /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>
+ */
+
+ /*
+ $Revision: 1.13 $
+ $Date: 2010/04/14 09:01:29 $
+ $Author: faust $
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef WIN32
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <signal.h>
+#include "conffiles.h"
+#endif
+
+#include <string.h>
+#include <vector>
+#include <iostream>
+
+#include "ia_auth_c.h"
+#include "common.h"
+#include "common_settings.h"
+#include "web.h"
+
+int mes;
+char infoText[256];
+char messageText[256];
+
+const int winKOI = 0;
+
+IA_CLIENT_PROT * clnp;
+WEB * web = NULL;
+
+using namespace std;
+
+time_t stgTime;
+
+//-----------------------------------------------------------------------------
+class SETTINGS: public COMMON_SETTINGS
+{
+public:
+ SETTINGS();
+ virtual ~SETTINGS(){};
+ virtual int Reload(){ return 0; };
+ void SetConfFile(string confFile);
+ virtual int ReadSettings();
+
+ virtual string GetStrError() const;
+
+ string GetServerName() const;
+ uint16_t GetServerPort() const;
+ uint16_t GetLocalPort() const;
+
+ string GetLogin() const;
+ string GetPassword() const;
+
+ bool GetDaemon() const;
+ bool GetShowPid() const;
+ bool GetNoWeb() const;
+ bool GetReconnect() const;
+ int GetRefreshPeriod() const;
+ uint32_t GetListenWebIP() const;
+
+ void Print() const;
+
+private:
+ string login;
+ string password;
+ string serverName;
+ int port;
+ int localPort;
+ uint32_t listenWebIP;
+ int refreshPeriod;
+
+ bool daemon;
+ bool noWeb;
+ bool reconnect;
+ bool showPid;
+
+ string confFile;
+};
+//-----------------------------------------------------------------------------
+SETTINGS::SETTINGS()
+{
+confFile = "/etc/sgauth.conf";
+}
+//-----------------------------------------------------------------------------
+void SETTINGS::SetConfFile(string confFile)
+{
+SETTINGS::confFile = confFile;
+}
+//-----------------------------------------------------------------------------
+int SETTINGS::ReadSettings()
+{
+CONFIGFILE * cf;
+
+cf = new CONFIGFILE(confFile);
+string tmp;
+int e = cf->Error();
+
+if (e)
+ {
+ printf("Cannot read file.\n");
+ delete cf;
+ return -1;
+ }
+
+cf->ReadString("Login", &login, "/?--?--?*");
+if (login == "/?--?--?*")
+ {
+ strError = "Parameter \'Login\' not found.";
+ delete cf;
+ return -1;
+ }
+
+cf->ReadString("Password", &password, "/?--?--?*");
+if (login == "/?--?--?*")
+ {
+ strError = "Parameter \'Password\' not found.";
+ delete cf;
+ return -1;
+ }
+
+cf->ReadString("ServerName", &serverName, "?*?*?");
+if (serverName == "?*?*?")
+ {
+ strError = "Parameter \'ServerName\' not found.";
+ delete cf;
+ return -1;
+ }
+
+cf->ReadString("ListenWebIP", &tmp, "127.0.0.1");
+listenWebIP = inet_addr(tmp.c_str());
+if (listenWebIP == INADDR_NONE)
+ {
+ strError = "Parameter \'ListenWebIP\' is not valid.";
+ delete cf;
+ return -1;
+ }
+
+cf->ReadString("ServerPort", &tmp, "5555");
+if (ParseIntInRange(tmp, 1, 65535, &port))
+ {
+ strError = "Parameter \'ServerPort\' is not valid.";
+ delete cf;
+ return -1;
+ }
+
+cf->ReadString("LocalPort", &tmp, "0");
+if (ParseIntInRange(tmp, 0, 65535, &localPort))
+ {
+ strError = "Parameter \'LocalPort\' is not valid.";
+ delete cf;
+ return -1;
+ }
+
+printf("LocalPort=%d\n", localPort);
+
+cf->ReadString("RefreshPeriod", &tmp, "5");
+if (ParseIntInRange(tmp, 1, 24*3600, &refreshPeriod))
+ {
+ strError = "Parameter \'RefreshPeriod\' is not valid.";
+ delete cf;
+ return -1;
+ }
+
+cf->ReadString("Reconnect", &tmp, "yes");
+if (ParseYesNo(tmp, &reconnect))
+ {
+ strError = "Parameter \'Reconnect\' is not valid.";
+ delete cf;
+ return -1;
+ }
+
+cf->ReadString("Daemon", &tmp, "yes");
+if (ParseYesNo(tmp, &daemon))
+ {
+ strError = "Parameter \'Daemon\' is not valid.";
+ delete cf;
+ return -1;
+ }
+
+cf->ReadString("ShowPid", &tmp, "no");
+if (ParseYesNo(tmp, &showPid))
+ {
+ strError = "Parameter \'ShowPid\' is not valid.";
+ delete cf;
+ return -1;
+ }
+
+cf->ReadString("DisableWeb", &tmp, "no");
+if (ParseYesNo(tmp, &noWeb))
+ {
+ strError = "Parameter \'DisableWeb\' is not valid.";
+ delete cf;
+ return -1;
+ }
+
+delete cf;
+return 0;
+}
+//-----------------------------------------------------------------------------
+string SETTINGS::GetStrError() const
+{
+return strError;
+}
+//-----------------------------------------------------------------------------
+string SETTINGS::GetLogin() const
+{
+return login;
+}
+//-----------------------------------------------------------------------------
+string SETTINGS::GetPassword() const
+{
+return password;
+}
+//-----------------------------------------------------------------------------
+string SETTINGS::GetServerName() const
+{
+return serverName;
+}
+//-----------------------------------------------------------------------------
+uint16_t SETTINGS::GetServerPort() const
+{
+return port;
+}
+//-----------------------------------------------------------------------------
+uint16_t SETTINGS::GetLocalPort() const
+{
+return localPort;
+}
+//-----------------------------------------------------------------------------
+int SETTINGS::GetRefreshPeriod() const
+{
+return refreshPeriod;
+}
+//-----------------------------------------------------------------------------
+bool SETTINGS::GetDaemon() const
+{
+return daemon;
+}
+//-----------------------------------------------------------------------------
+bool SETTINGS::GetNoWeb() const
+{
+return noWeb;
+}
+//-----------------------------------------------------------------------------
+bool SETTINGS::GetShowPid() const
+{
+return showPid;
+}
+//-----------------------------------------------------------------------------
+bool SETTINGS::GetReconnect() const
+{
+return reconnect;
+}
+//-----------------------------------------------------------------------------
+uint32_t SETTINGS::GetListenWebIP() const
+{
+return listenWebIP;
+}
+//-----------------------------------------------------------------------------
+void SETTINGS::Print() const
+{
+cout << "login = " << login << endl;
+cout << "password = " << password << endl;
+cout << "ip = " << serverName << endl;
+cout << "port = " << port << endl;
+cout << "localPort = " << localPort << endl;
+cout << "listenWebIP = " << inet_ntostring(listenWebIP) << endl;
+cout << "DisableWeb = " << noWeb << endl;
+cout << "refreshPeriod = " << refreshPeriod << endl;
+cout << "daemon = " << daemon << endl;
+cout << "reconnect = " << reconnect << endl;
+}
+//-----------------------------------------------------------------------------
+void Usage()
+{
+printf("sgauth <server> <port> <login> <password>\n"); //TODO change to correct
+}
+//-----------------------------------------------------------------------------
+void EventsFn(int)
+{
+LOADSTAT ls;
+clnp->GetStat(&ls);
+}
+//-----------------------------------------------------------------------------
+void SetDirName(const vector<string> & dn, void *)
+{
+for (int j = 0; j < DIR_NUM; j++)
+ {
+ if (winKOI)
+ {
+ string dir;
+ KOIToWin(dn[j], &dir);
+ if (web)
+ web->SetDirName(dir, j);
+ }
+ else
+ {
+ if (web)
+ web->SetDirName(dn[j], j);
+ }
+ }
+}
+//-----------------------------------------------------------------------------
+void StatUpdate(const LOADSTAT & ls, void *)
+{
+if (web)
+ web->UpdateStat(ls);
+}
+//-----------------------------------------------------------------------------
+void StatusChanged(int, void *)
+{
+
+}
+//-----------------------------------------------------------------------------
+void ShowMessage(const string & message, int i, int, int, void *)
+{
+if (web)
+ web->AddMessage(message, i);
+}
+//-----------------------------------------------------------------------------
+void ShowError(const string & message, int, void *)
+{
+if (web)
+ web->AddMessage(message, 0);
+}
+//-----------------------------------------------------------------------------
+#ifndef WIN32
+void CatchUSR1(int)
+{
+if (clnp->GetAuthorized())
+ {
+ cout << "Connect" << endl;
+ clnp->Connect();
+ }
+}
+//-----------------------------------------------------------------------------
+void CatchUSR2(int)
+{
+cout << "Disconnect" << endl;
+clnp->Disconnect();
+}
+//-----------------------------------------------------------------------------
+void CatchTERM(int)
+{
+cout << "Terminated" << endl;
+clnp->Disconnect();
+sleep(2);
+exit(0);
+}
+//-----------------------------------------------------------------------------
+static void SetSignalHandlers()
+{
+struct sigaction newsa, oldsa;
+sigset_t sigmask;
+
+sigemptyset(&sigmask);
+sigaddset(&sigmask, SIGTERM);
+newsa.sa_handler = CatchTERM;
+newsa.sa_mask = sigmask;
+newsa.sa_flags = 0;
+sigaction(SIGTERM, &newsa, &oldsa);
+
+sigemptyset(&sigmask);
+sigaddset(&sigmask, SIGINT);
+newsa.sa_handler = CatchTERM;
+newsa.sa_mask = sigmask;
+newsa.sa_flags = 0;
+sigaction(SIGINT, &newsa, &oldsa);
+
+sigemptyset(&sigmask);
+sigaddset(&sigmask, SIGUSR1);
+newsa.sa_handler = CatchUSR1;
+newsa.sa_mask = sigmask;
+newsa.sa_flags = 0;
+sigaction(SIGUSR1, &newsa, &oldsa);
+
+sigemptyset(&sigmask);
+sigaddset(&sigmask, SIGUSR2);
+newsa.sa_handler = CatchUSR2;
+newsa.sa_mask = sigmask;
+newsa.sa_flags = 0;
+sigaction(SIGUSR2, &newsa, &oldsa);
+
+return;
+}
+#endif
+//-----------------------------------------------------------------------------
+int main(int argc, char *argv[])
+{
+//int port;
+//char *endptr;
+
+SETTINGS settings;
+
+#ifndef WIN32
+if (argc == 2)
+#else
+if(0)
+#endif
+ {
+ settings.SetConfFile(argv[1]);
+ if (settings.ReadSettings())
+ {
+ printf("ReadSettingsError\n");
+ printf("%s\n", settings.GetStrError().c_str());
+ exit(-1);
+ }
+ settings.Print();
+ }
+else
+ {
+ /*if (argc != 5)
+ {
+ Usage();
+ exit(1);
+ }
+ else
+ {
+ string serverName(argv[1]);
+ port = strtol(argv[2], &endptr, 10);
+ if (*endptr != 0)
+ {
+ printf("Invalid port!\n");
+ exit(1);
+ }
+ login = argv[3];
+ passwd = argv[4];
+ }*/
+ }
+
+//settings.Print();
+
+#ifndef WIN32
+if (settings.GetDaemon())
+ {
+ /*close(0);
+ close(1);
+ close(2);*/
+
+ switch (fork())
+ {
+ case -1: // ìÁÖÁ
+ exit(1);
+ break;
+
+ case 0: // ðÏÔÏÍÏË
+ setsid();
+ break;
+
+ default: // ïÓÎÏ×ÎÏÊ ÐÒÏÃÅÓÓ
+ exit(0);
+ break;
+ }
+ }
+
+
+
+#endif
+
+clnp = new IA_CLIENT_PROT(settings.GetServerName(), settings.GetServerPort(), settings.GetLocalPort());
+
+if (!settings.GetNoWeb())
+ {
+ web = new WEB();
+ web->SetRefreshPagePeriod(settings.GetRefreshPeriod());
+ web->SetListenAddr(settings.GetListenWebIP());
+ web->Start();
+ }
+
+clnp->SetLogin(settings.GetLogin());
+clnp->SetPassword(settings.GetPassword());
+
+clnp->SetStatusChangedCb(StatusChanged, NULL);
+clnp->SetInfoCb(ShowMessage, NULL);
+clnp->SetErrorCb(ShowError, NULL);
+clnp->SetDirNameCb(SetDirName, NULL);
+clnp->SetStatChangedCb(StatUpdate, NULL);
+clnp->SetReconnect(settings.GetReconnect());
+
+
+clnp->Start();
+
+SetSignalHandlers();
+
+#ifdef LINUX
+for (int i = 1; i < argc; i++)
+ memset(argv[i], 0, strlen(argv[i]));
+
+if(argc > 1)
+ strcpy(argv[1], "Connecting...");
+#endif
+
+#ifdef FREEBSD
+setproctitle("Connecting...");
+#endif
+clnp->Connect();
+
+while (1)
+ {
+ #ifdef WIN32
+ Sleep(200);
+ #else
+ usleep(200000);
+ #endif
+
+ char state[20];
+
+ if (clnp->GetAuthorized())
+ {
+ if (settings.GetShowPid())
+ sprintf(state, "On %d", getpid());
+ else
+ strcpy(state, "Online");
+ }
+ else
+ {
+ if (settings.GetShowPid())
+ sprintf(state, "Off %d", getpid());
+ else
+ strcpy(state, "Offline");
+ }
+
+ #ifdef LINUX
+ for (int i = 1; i < argc; i++)
+ memset(argv[i], 0, strlen(argv[i]));
+ if(argc > 1)
+ strcpy(argv[1], state);
+ #endif
+
+ #ifdef FREEBSD
+ setproctitle(state);
+ #endif
+
+ #ifdef FREEBSD_5
+ setproctitle(state);
+ #endif
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
+
--- /dev/null
+#!/bin/sh
+
+OUT_FILE=css.h
+
+
+echo "const char * css =" > $OUT_FILE
+echo "\"/*------*/\\\\n\"" >> $OUT_FILE
+sed -e 's/$/\\n"/g' -e 's/^/"/g' sgauth.css >> $OUT_FILE
+echo ";" >> $OUT_FILE
+
--- /dev/null
+äÌÑ ËÏÍÉÐÉÌÑÃÉÉ ÐÒÏÇÒÁÍÍÙ ÚÁÐÕÓÔÉÔÅ ÓËÒÉÐÔ ./build
+
+ðÒÏÇÒÁÍÍÁ ÚÁÐÕÓËÁÅÔÓÑ ÓÏ ÓÌÅÄÕÀÝÉÍÉ ÐÁÒÁÍÅÔÒÁÍÉ:
+ > sgauth <server> <port> <login> <password>
+ÉÌÉ
+ > sgauth <config_file_name>
+ÉÌÉ
+ > sgauth
+
+÷ ÐÏÓÌÅÄÎÅÍ ÓÌÕÞÁÅ ÉÓÐÏÌØÚÕÅÔÓÑ ËÏÎÆÉÇÕÒÁÃÉÏÎÎÙÊ ÆÁÊÌ /etc/sgauth.conf
+
+ðÒÉ ÐÏÄËÌÀÞÅÎÉÉ ÂÒÁÕÚÅÒÏÍ ÐÏ ÁÄÒÅÓÕ http://localhost:5580
+ÍÏÖÎÏ ÐÏÓÍÏÔÒÅÔØ ÓÔÁÔÉÓÔÉËÕ.
--- /dev/null
+#Stargazer server ip
+ServerName=192.168.1.2
+
+#Stargazer server port
+#Default value 5555
+ServerPort=5555
+
+#User's login
+Login=test
+
+#
+#
+LocalPort=12345
+
+#User's password
+Password=1234567
+
+#
+#Default value yes
+#Reconnect=no
+
+#
+#Default value yes
+#Daemon=yes
+
+#Refresh web page period
+#Default value 10
+#RefreshPeriod=10
+
+#
+#Default value 127.0.0.1
+ListenWebIP=0.0.0.0
+
+#Default value no
+DisableWeb=no
+
+#ShowPid=no
--- /dev/null
+H3
+{
+color: black;
+}
+
+body
+{
+background-color: silver;
+}
+
+#TraffTable
+{
+background-color: white;
+}
+
+#TraffTableCaptionRow
+{
+background-color: silver;
+}
+
+#TraffTableCaptionCellC,
+#TraffTableUMCellC,
+#TraffTableDMCellC,
+#TraffTableUSCellC,
+#TraffTableDSCellC
+{
+background-color: silver;
+}
+
+#TraffTableDMRow,
+#TraffTableDSRow
+{
+background-color: #f2f0cc;
+}
+
+#TraffTableUMRow,
+#TraffTableUSRow
+{
+background-color: white;
+}
+
+#ConnectionStateOnline
+{
+color: green;
+font-size: 20px
+}
+
+#ConnectionStateOffline
+{
+color: red;
+font-size: 20px
+}
+
+p
+{
+padding: 2px;
+margin: 0px;
+}
+
+#MessagesTable
+{
+background-color: white;
+}
+
+#MessagesTableRowC
+{
+background-color: silver;
+}
+
+
+#MessagesTableRow0,
+#MessagesTableRow2,
+#MessagesTableRow4,
+#MessagesTableRow6,
+#MessagesTableRow8
+{
+background-color: #f2f0cc;
+}
--- /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>
+ */
+
+ /*
+ $Revision: 1.7 $
+ $Date: 2010/03/15 12:58:17 $
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <libintl.h>
+
+#include "web.h"
+#include "common.h"
+#include "ia_auth_c.h"
+
+extern WEB * web;
+extern IA_CLIENT_PROT * clnp;
+
+#define LISTEN_PORT (5580)
+
+#include "css.h"
+
+//---------------------------------------------------------------------------
+#ifndef WIN32
+void * RunWeb(void *)
+#else
+unsigned long WINAPI RunWeb(void *)
+#endif
+{
+while (1)
+ web->Run();
+return NULL;
+}
+//---------------------------------------------------------------------------
+WEB::WEB()
+ : res(0),
+ listenSocket(0),
+ outerSocket(0),
+ refreshPeriod(0),
+ listenWebAddr(0),
+ outerAddrLen(0)
+{
+#ifdef WIN32
+res = WSAStartup(MAKEWORD(2,0), &wsaData);
+#endif
+
+for (int i = 0; i < DIR_NUM; i++)
+ dirName[i] = "-";
+
+refreshPeriod = 5;
+}
+//---------------------------------------------------------------------------
+void WEB::Start()
+{
+#ifdef WIN32
+unsigned long pt;
+CreateThread(
+ NULL, // pointer to thread security attributes
+ 16384, // initial thread stack size, in bytes
+ RunWeb, // pointer to thread function
+ NULL, // argument for new thread
+ 0, // CREATE_SUSPENDED, // creation flags
+ &pt // pointer to returned thread identifier
+ );
+#else
+pthread_create(&thread, NULL, RunWeb, NULL);
+#endif
+}
+//---------------------------------------------------------------------------
+void WEB::PrepareNet()
+{
+listenSocket = socket(PF_INET, SOCK_STREAM, 0);
+listenAddr.sin_family = AF_INET;
+listenAddr.sin_port = htons(LISTEN_PORT);
+listenAddr.sin_addr.s_addr = listenWebAddr;
+
+int lng = 1;
+
+#ifndef WIN32
+if (0 != setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, &lng, 4))
+ {
+ printf("Setsockopt Fail\n");
+ printf(">>> Error %s\n", strerror(errno));
+ }
+#else
+//??? TODO
+#endif
+
+
+res = bind(listenSocket, (struct sockaddr*)&listenAddr, sizeof(listenAddr));
+
+if (res == -1)
+ {
+ printf("Bind failed.\n");
+ exit(0);
+ }
+
+res = listen(listenSocket, 0);
+if (res == -1)
+ {
+ printf("Listen failed.\n");
+ exit(0);
+ }
+
+outerAddrLen = sizeof(outerAddr);
+}
+//---------------------------------------------------------------------------
+void WEB::SetRefreshPagePeriod(int p)
+{
+refreshPeriod = p;
+if (refreshPeriod <= 0 || refreshPeriod > 24*3600)
+ refreshPeriod = 5;
+}
+//---------------------------------------------------------------------------
+void WEB::SetListenAddr(uint32_t ip)
+{
+listenWebAddr = ip;
+}
+//---------------------------------------------------------------------------
+void WEB::Run()
+{
+PrepareNet();
+char recvBuffer[4096];
+while (1)
+ {
+ outerSocket = accept(listenSocket, (struct sockaddr*)&outerAddr, &outerAddrLen);
+ if (outerSocket == -1)
+ {
+ printf(">>> Error %s\n", strerror(errno));
+ continue;
+ }
+ recv(outerSocket, recvBuffer, sizeof(recvBuffer), 0);
+
+ if (strncmp(recvBuffer, "GET /sgauth.css", strlen("GET /sgauth.css")) == 0)
+ {
+ SendCSS();
+ //printf("(1) recvBuffer=%s\n", recvBuffer);
+ }
+ else if (strncmp(recvBuffer, "GET /disconnect", strlen("GET /disconnect")) == 0)
+ {
+ clnp->Disconnect();
+ Redirect("/");
+ //printf("(2) recvBuffer=%s\n", recvBuffer);
+ }
+ else if (strncmp(recvBuffer, "GET /connect", strlen("GET /connect")) == 0)
+ {
+ clnp->Connect();
+ Redirect("/");
+ //printf("(3) recvBuffer=%s\n", recvBuffer);
+ }
+ else if (strncmp(recvBuffer, "GET /exit", strlen("GET /exit")) == 0)
+ {
+ Redirect("/");
+ clnp->Disconnect();
+ #ifdef WIN32
+ Sleep(1000);
+ #else
+ usleep(1000000);
+ #endif
+ exit(0);
+ }
+ else
+ {
+ SendReply();
+ //printf("(4) recvBuffer=%s\n", recvBuffer);
+ }
+
+ #ifdef WIN32
+ closesocket(outerSocket);
+ #else
+ close(outerSocket);
+ #endif
+ }
+}
+//---------------------------------------------------------------------------
+int WEB::Redirect(const char * url)
+{
+const char * redirect =
+ "HTTP/1.0 200 OK\n"
+ "Content-Type: text/html\n"
+ "Connection: close"
+ "\n\n"
+ "<html>\n"
+ "<head>\n"
+ "<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0;%s\">\n"
+ "</head>\n"
+ "<body>\n"
+ "</body></html>\n\n";
+
+char buff[2000];
+sprintf(buff, redirect, url);
+send(outerSocket, buff, strlen(buff), 0);
+
+return 0;
+}
+//---------------------------------------------------------------------------
+int WEB::SendReply()
+{
+int j, rowNum;
+
+const char * replyHeader =
+ "HTTP/1.0 200 OK\n"
+ "Content-Type: text/html\n"
+ "Connection: close"
+ "\n\n"
+ "<html>\n"
+ "<head>\n"
+ "<META HTTP-EQUIV=\"Refresh\" CONTENT=\"%d\">\n"
+ "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=windows-1251\">\n"
+ "<title>sgauth</title>\n"
+ "<link rel=\"Stylesheet\" href=\"sgauth.css\">"
+ "</head>\n"
+ "<body>\n"
+ "<H3>Stargazer</H3><p>\n";
+
+const char * replyFooter = "</body></html>\n\n";
+
+char replyHeaderBuffer[2000];
+sprintf(replyHeaderBuffer, replyHeader, refreshPeriod);
+
+send(outerSocket, replyHeaderBuffer, strlen(replyHeaderBuffer), 0);
+
+char str[512];
+
+int st = clnp->GetAuthorized();
+
+sprintf(str, "<a href=\"connect\">%s</a><p>\n", gettext("Connect"));
+res = send(outerSocket, str, strlen(str), 0);
+
+sprintf(str, "<a href=\"disconnect\">%s</a><p>\n", gettext("Disconnect"));
+res = send(outerSocket, str, strlen(str), 0);
+
+sprintf(str, "<a href=\"/\">%s</a><p>\n", gettext("Refresh"));
+res = send(outerSocket, str, strlen(str), 0);
+
+sprintf(str, "<a href=\"exit\">%s</a><p>\n", gettext("Exit"));
+res = send(outerSocket, str, strlen(str), 0);
+
+sprintf(str, "<div id=\"%s\">%s</div><p>\n" , st ? "ConnectionStateOnline":"ConnectionStateOffline", st ? "Online":"Offline");
+res = send(outerSocket, str, strlen(str), 0);
+
+sprintf(str, "<div id=\"Cash\">%s: %.3f</div><p>\n" , gettext("Cash"), ls.cash / 1000.0);
+res = send(outerSocket, str, strlen(str), 0);
+
+sprintf(str, "<div id=\"Prepaid Traffic\">%s: %s</div><p>\n" ,
+ gettext("PrepaidTraffic"),
+ ls.freeMb[0] == 'C' ? ls.freeMb + 1 : ls.freeMb);
+res = send(outerSocket, str, strlen(str), 0);
+
+sprintf(str, "<TABLE id=\"TraffTable\">\n");
+res = send(outerSocket, str, strlen(str), 0);
+sprintf(str, " <TR id=\"TraffTableCaptionRow\">\n");
+res = send(outerSocket, str, strlen(str), 0);
+sprintf(str, " <TD id=\"TraffTableCaptionCellC\"> </TD>\n");
+res = send(outerSocket, str, strlen(str), 0);
+
+rowNum = 0;
+for (j = 0; j < DIR_NUM; j++)
+ {
+ if (dirName[j][0] == 0)
+ continue;
+ string s;
+ KOIToWin(dirName[j], &s);// +++++++++ sigsegv ========== TODO too long dir name crashes sgauth
+ sprintf(str, " <TD id=\"TraffTableCaptionCell%d\">%s</TD>\n", rowNum++, s.c_str());
+ send(outerSocket, str, strlen(str), 0);
+ }
+
+sprintf(str," </TR>\n");
+send(outerSocket, str, strlen(str), 0);
+
+sprintf(str," <TR id=\"TraffTableUMRow\">\n");
+send(outerSocket, str, strlen(str), 0);
+
+sprintf(str," <TD id=\"TraffTableUMCellC\">%s</TD>\n", gettext("Month Upload"));
+send(outerSocket, str, strlen(str), 0);
+
+rowNum = 0;
+for (j = 0; j < DIR_NUM; j++)
+ {
+ if (dirName[j][0] == 0)
+ continue;
+ sprintf(str," <TD id=\"TraffTableUMCell%d\">%s</TD>\n", rowNum++, IntToKMG(ls.mu[j], ST_F));
+ res = send(outerSocket, str, strlen(str), 0);
+ }
+
+sprintf(str," </TR>\n");
+res = send(outerSocket, str, strlen(str), 0);
+sprintf(str," <TR id=\"TraffTableDMRow\">\n");
+res = send(outerSocket, str, strlen(str), 0);
+sprintf(str," <TD id=\"TraffTableDMCellC\">%s</TD>\n", gettext("Month Download"));
+res = send(outerSocket, str, strlen(str), 0);
+
+rowNum = 0;
+for (j = 0; j < DIR_NUM; j++)
+ {
+ if (dirName[j][0] == 0)
+ continue;
+ sprintf(str," <TD id=\"TraffTableDMCell%d\">%s</TD>\n", rowNum++, IntToKMG(ls.md[j], ST_F));
+ res = send(outerSocket, str, strlen(str), 0);
+ }
+sprintf(str," </TR>\n");
+res = send(outerSocket, str, strlen(str), 0);
+
+
+sprintf(str," <TR id=\"TraffTableUSRow\">\n");
+res = send(outerSocket, str, strlen(str), 0);
+sprintf(str," <TD id=\"TraffTableUSCellC\">%s</TD>\n", gettext("Session Upload"));
+res = send(outerSocket, str, strlen(str), 0);
+
+rowNum = 0;
+for (j = 0; j < DIR_NUM; j++)
+ {
+ if (dirName[j][0] == 0)
+ continue;
+ sprintf(str," <TD id=\"TraffTableUSCell%d\">%s</TD>\n", rowNum++, IntToKMG(ls.su[j], ST_F));
+ res = send(outerSocket, str, strlen(str), 0);
+ }
+
+sprintf(str," </TR>\n");
+res = send(outerSocket, str, strlen(str), 0);
+sprintf(str," <TR id=\"TraffTableDSRow\">\n");
+res = send(outerSocket, str, strlen(str), 0);
+sprintf(str," <TD id=\"TraffTableDSCellC\">%s</TD>\n", gettext("Session Download"));
+res = send(outerSocket, str, strlen(str), 0);
+
+rowNum = 0;
+for (j = 0; j < DIR_NUM; j++)
+ {
+ if (dirName[j][0] == 0)
+ continue;
+ sprintf(str," <TD id=\"TraffTableDSCell%d\">%s</TD>\n", j, IntToKMG(ls.sd[j], ST_F));
+ res = send(outerSocket, str, strlen(str), 0);
+ }
+
+sprintf(str," </TR>\n");
+res = send(outerSocket, str, strlen(str), 0);
+
+sprintf(str,"</TABLE>\n");
+res = send(outerSocket, str, strlen(str), 0);
+
+rowNum = 0;
+if (!messages.empty())
+ {
+ sprintf(str," <TABLE id=\"MessagesTable\">\n");
+ res = send(outerSocket, str, strlen(str), 0);
+
+ sprintf(str," <TR id=\"MessagesTableRowC\">\n");
+ send(outerSocket, str, strlen(str), 0);
+ sprintf(str," <TD>Date</TD>\n");
+ send(outerSocket, str, strlen(str), 0);
+ sprintf(str," <TD>Text</TD>\n");
+ send(outerSocket, str, strlen(str), 0);
+ sprintf(str," </TR>\n");
+ send(outerSocket, str, strlen(str), 0);
+
+ list<STG_MESSAGE>::reverse_iterator it;
+ it = messages.rbegin();
+ while (it != messages.rend())
+ {
+ sprintf(str," <TR id=\"MessagesTableRow%d\">\n", rowNum);
+ send(outerSocket, str, strlen(str), 0);
+ sprintf(str," <TD>%s</TD>\n", it->recvTime.c_str());
+ send(outerSocket, str, strlen(str), 0);
+ sprintf(str," <TD>%s</TD>\n", it->msg.c_str());
+ send(outerSocket, str, strlen(str), 0);
+ sprintf(str," </TR>\n");
+ send(outerSocket, str, strlen(str), 0);
+ ++it;
+ ++rowNum;
+ }
+
+ sprintf(str," </TABLE>\n");
+ res = send(outerSocket, str, strlen(str), 0);
+ }
+
+time_t t = time(NULL);
+sprintf(str,"Îáíîâëåíî: %s</b>" , ctime(&t));
+res = send(outerSocket, str, strlen(str), 0);
+
+send(outerSocket, replyFooter, strlen(replyFooter), 0);
+
+return 0;
+}
+//---------------------------------------------------------------------------
+int WEB::SendCSS()
+{
+const char * replyHeader =
+ "HTTP/1.0 200 OK\n"
+ "Content-Type: text/css\n"
+ "Connection: close\n\n";
+
+const char * replyFooter= "\n\n";
+
+send(outerSocket, replyHeader, strlen(replyHeader), 0);
+send(outerSocket, css, strlen(css), 0);
+send(outerSocket, replyFooter, strlen(replyFooter), 0);
+
+return 0;
+}
+//---------------------------------------------------------------------------
+void WEB::SetDirName(const string & dn, int n)
+{
+web->dirName[n] = dn;
+}
+//---------------------------------------------------------------------------
+void WEB::AddMessage(const string & message, int type)
+{
+time_t t = time(NULL);
+STG_MESSAGE m;
+
+m.msg = message;
+m.type = type;
+m.recvTime = ctime(&t);
+
+messages.push_back(m);
+
+if (messages.size() > MAX_MESSAGES)
+ messages.pop_front();
+
+}
+//---------------------------------------------------------------------------
+void WEB::UpdateStat(const LOADSTAT & ls)
+{
+memcpy((void*)&(WEB::ls), &ls, sizeof(LOADSTAT));
+}
+//---------------------------------------------------------------------------
+
--- /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>
+ */
+
+ /*
+ $Revision: 1.3 $
+ $Date: 2007/12/17 08:39:08 $
+ */
+
+#ifndef WIN32
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#else
+#include <winsock2.h>
+#endif
+
+#include <string>
+#include <list>
+
+#include "stg_const.h"
+#include "ia_packets.h"
+
+using namespace std;
+
+#define MAX_MESSAGES (10)
+//-----------------------------------------------------------------------------
+struct STG_MESSAGE
+{
+string msg;
+string recvTime;
+int type;
+};
+//-----------------------------------------------------------------------------
+class WEB
+{
+public:
+ WEB();
+ void Run();
+ void SetDirName(const string & dn, int n);
+ void SetRefreshPagePeriod(int p);
+ void SetListenAddr(uint32_t ip);
+ void AddMessage(const string & message, int type);
+ void UpdateStat(const LOADSTAT & ls);
+ void Start();
+private:
+
+ void PrepareNet();
+
+ #ifdef WIN32
+ WSADATA wsaData;
+ #else
+ pthread_t thread;
+ #endif
+
+ int SendReply();
+ int SendCSS();
+ int Redirect(const char * url);
+
+ string dirName[DIR_NUM];
+ int res;
+ int listenSocket;
+ int outerSocket;
+ struct sockaddr_in listenAddr;
+ struct sockaddr_in outerAddr;
+ int refreshPeriod;
+
+ uint32_t listenWebAddr;
+ LOADSTAT ls;
+
+ list<STG_MESSAGE> messages;
+
+ #ifndef WIN32
+ socklen_t outerAddrLen;
+ #else
+ int outerAddrLen;
+ #endif
+};
+//-----------------------------------------------------------------------------
+
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.21 2010/02/11 12:34:14 faust Exp $
+###############################################################################
+
+include ../../Makefile.conf
+
+PROG = sgconf
+
+SRCS = ./main.cpp \
+ ./common_sg.cpp
+
+STGLIBS = -lconffiles \
+ -lstg_common \
+ -lstg_crypto \
+ -lsrvconf
+
+LIBS += -lexpat \
+ $(LIB_THREAD)
+
+ifeq ($(OS),linux)
+LIBS += -ldl
+else
+LIBS += -lc \
+ -liconv
+endif
+
+SEARCH_DIRS = -I $(DIR_INCLUDE)
+
+ifeq ($(OS),bsd)
+SEARCH_DIRS += -I/usr/local/include
+CXXFLAGS += -DHAVE_DECL_GETOPT=1
+endif
+
+ifeq ($(OS),bsd5)
+SEARCH_DIRS += -I/usr/local/include
+CXXFLAGS += -DHAVE_DECL_GETOPT=1
+endif
+
+OBJS = $(notdir $(patsubst %.cpp, %.o, $(patsubst %.c, %.o, $(SRCS))))
+
+CXXFLAGS += -Wall
+LDFLAGS += -Wl,-E -L$(DIR_LIB) -Wl,-rpath,$(PREFIX)/usr/lib/stg -Wl,-rpath-link,$(DIR_LIB)
+
+vpath %.so $(DIR_LIB)
+
+.PHONY: all clean distclean libs install uninstall install-bin install-data uninstall-bin uninstall-data
+all: libs $(PROG) ../../Makefile.conf
+
+libs:
+ $(MAKE) -C $(DIR_LIBSRC)
+
+$(PROG): $(OBJS) $(STGLIBS)
+ $(CC) $^ $(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*
+ $(MAKE) -C $(DIR_LIBSRC) clean
+
+distclean: clean
+ rm -f ../../Makefile.conf
+
+install: install-bin install-data
+
+install-bin:
+ mkdir -m $(BIN_MODE) -p $(PREFIX)/usr/sbin
+ install -m $(BIN_MODE) -o $(OWNER) -s $(PROG) $(PREFIX)/usr/sbin/$(PROG)
+ $(MAKE) -C $(DIR_LIBSRC) install
+
+install-data:
+
+uninstall: uninstall-bin uninstall-data
+
+uninstall-bin:
+ rm -f $(PREFIX)/usr/sbin/$(PROG)
+
+uninstall-data:
+
+
+ifneq ($(MAKECMDGOALS),distclean)
+ifneq ($(MAKECMDGOALS),clean)
+ifneq ($(MAKECMDGOALS),uninstall)
+-include deps
+endif
+endif
+endif
+
+deps: $(SRCS) ../../Makefile.conf
+ $(MAKE) -C $(DIR_LIBSRC) includes
+ @>deps ;\
+ for file in $(SRCS); do\
+ echo "`$(CC) $(CXXFLAGS) $(SEARCH_DIRS) -MM $$file` Makefile" >> deps ;\
+ echo -e '\t$$(CC) -c $$< $(CXXFLAGS) $(SEARCH_DIRS) $(DEFS)' >> deps ;\
+ done
+
+
--- /dev/null
+Compiling:
+> ./build
+
--- /dev/null
+#!/bin/sh
+
+# $Author: faust $
+# $Revision: 1.21 $
+# $Date: 2010/04/14 08:59:11 $
+######################################################
+
+OS=unknown
+sys=`uname -s`
+release=`uname -r | cut -b1`
+BUILD_DIR=`pwd`
+CONFFILE="../../Makefile.conf"
+PREFIX="/"
+BIN_MODE=0755
+DATA_MODE=0644
+OWNER=root
+
+if [ -z $1 ]
+then
+ MAKEOPTS="-j1"
+else
+ if [ "$1" = "debug" ]
+ then
+ DEFS="-DDEBUG"
+ MAKEOPTS="-j1"
+ CXXFLAGS="$CXXFLAGS -g3 -W -Wall"
+ else
+ MAKEOPTS="-j1"
+ fi
+fi
+
+CXXFLAGS="$CXXFLAGS -I/usr/local/include"
+LDFLAGS="$LDFLAGS -L/usr/local/lib"
+
+if [ "$sys" = "Linux" ]
+then
+ OS=linux
+ release=""
+ MAKE="make"
+fi
+
+if [ "$sys" = "FreeBSD" ]
+then
+ case $release in
+ 4) OS=bsd;;
+ 5) OS=bsd5;;
+ 6) OS=bsd5;;
+ 7) OS=bsd7;;
+ 8) OS=bsd7;;
+ *) OS=unknown;;
+ esac
+ MAKE="gmake"
+fi
+
+if [ "$OS" = "unknown" ]
+then
+ echo "#############################################################################"
+ echo "# Sorry, but sgconf currently supported by Linux, FreeBSD 4.x, 5.x, 6.x #"
+ echo "#############################################################################"
+ exit 1
+fi
+
+echo "#############################################################################"
+echo " Building sgconf for $sys $release"
+echo "#############################################################################"
+
+STG_LIBS="conffiles.lib
+ crypto.lib
+ common.lib
+ srvconf.lib"
+
+if [ "$OS" = "linux" ]
+then
+ DEFS="$DEFS -DLINUX"
+ LIB_THREAD=-lpthread
+ SHELL="/bin/bash"
+else
+ if [ "$OS" = "bsd" ]
+ then
+ DEFS="$DEFS -DFREE_BSD"
+ else
+ DEFS="$DEFS -DFREE_BSD5"
+ if [ "$OS" = "bsd7" ]
+ then
+ LIB_THREAD=-lpthread
+ else
+ LIB_THREAD=-lc_r
+ fi
+ fi
+ SHELL="/usr/local/bin/bash"
+fi
+
+echo -n "Checking endianess... "
+echo "int main() { int probe = 0x00000001; return *(char *)&probe; }" > build_check.c
+gcc $CXXFLAGS $LDFLAGS build_check.c -o fake > /dev/null 2> /dev/null
+if [ $? != 0 ]
+then
+ echo "FAIL!"
+ echo "Endianess checking failed"
+ exit;
+else
+ ./fake
+ if [ $? = 1 ]
+ then
+ ARCH=le
+ CXXFLAGS="$CXXFLAGS -DARCH_LE"
+ echo "Little Endian"
+ else
+ ARCH=be
+ CXXFLAGS="$CXXFLAGS -DARCH_BE"
+ echo "Big Endian"
+ fi
+fi
+rm -f fake
+
+echo -n "Checking for -lexpat... "
+echo "int main() { return 0; }" > build_check.c
+gcc $CXXFLAGS $LDFLAGS build_check.c -lexpat -o fake > /dev/null 2> /dev/null
+if [ $? != 0 ]
+then
+ CHECK_EXPAT=no
+ echo "no"
+else
+ CHECK_EXPAT=yes
+ echo "yes"
+fi
+rm -f fake
+rm -f build_check.c
+
+if [ "$CHECK_EXPAT" != "yes" ]
+then
+ echo "-lexpat not found!"
+ exit 1
+fi
+
+echo "OS=$OS" > $CONFFILE
+echo "STG_TIME=yes" >> $CONFFILE
+echo "DIR_BUILD=$BUILD_DIR" >> $CONFFILE
+echo "DIR_LIB=\$(DIR_BUILD)/../../lib" >> $CONFFILE
+echo "DIR_LIBSRC=\$(DIR_BUILD)/../../stglibs" >> $CONFFILE
+echo "DIR_INCLUDE=\$(DIR_BUILD)/../../include" >> $CONFFILE
+echo "ARCH=$ARCH" >> $CONFFILE
+echo "CHECK_EXPAT=$CHECK_EXPAT" >> $CONFFILE
+echo "DEFS=$DEFS" >> $CONFFILE
+echo -n "STG_LIBS=" >> $CONFFILE
+for lib in $STG_LIBS
+do
+ echo -n "$lib " >> $CONFFILE
+done
+echo "" >> $CONFFILE
+echo "LIB_THREAD=$LIB_THREAD" >> $CONFFILE
+echo "SHELL=$SHELL" >> $CONFFILE
+echo "CXXFLAGS=$CXXFLAGS" >> $CONFFILE
+echo "LDFLAGS=$LDFLAGS" >> $CONFFILE
+echo "PREFIX=$PREFIX" >> $CONFFILE
+echo "BIN_MODE=$BIN_MODE" >> $CONFFILE
+echo "DATA_MODE=$DATA_MODE" >> $CONFFILE
+echo "OWNER=$OWNER" >> $CONFFILE
+
+$MAKE $MAKEOPTS
+
--- /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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <locale.h>
+#include <langinfo.h>
+#include <iostream>
+#include <iconv.h>
+
+#include "common_sg.h"
+#include "version_sg.h"
+#include "common.h"
+#include "sg_error_codes.h"
+
+using namespace std;
+
+const int usageConf = 0;
+const int usageInfo = 1;
+
+const int TO_KOI8 = 0;
+const int FROM_KOI8 = 1;
+//-----------------------------------------------------------------------------
+struct GetUserCbData
+{
+ void * data;
+ bool * result;
+};
+//---------------------------------------------------------------------------
+struct HelpParams
+{
+ string setActionName;
+ string getActionName;
+ string valueName;
+ 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 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 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] == '-'))
+ {
+ return 1;
+ }
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+short int ParseServerPort(const char * p)
+{
+int port;
+if (str2x(p, port) != 0)
+ {
+ printf("Incorresct server port %s\n", p);
+ exit(NETWORK_ERR_CODE);
+ }
+return (short)port;
+}
+//-----------------------------------------------------------------------------
+char * ParseAdminLogin(char * adm)
+{
+if (CheckLogin(adm))
+ {
+ printf("Incorresct 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("Incorresct user login %s\n", usr);
+ exit(PARAMETER_PARSING_ERR_CODE);
+ }
+return usr;
+}
+//-----------------------------------------------------------------------------
+void ConvertKOI8(const string & src, 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-r");
+ }
+else
+ {
+ strcpy(charsetT, nl_langinfo(CODESET));
+ strcpy(charsetF, "koi8-r");
+ }
+
+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 string & src, string * dst)
+{
+ConvertKOI8(src, dst, FROM_KOI8);
+}
+//-----------------------------------------------------------------------------
+void ConvertToKOI8(const string & src, string * dst)
+{
+ConvertKOI8(src, dst, TO_KOI8);
+}
+//-----------------------------------------------------------------------------
+int RecvSetUserAnswer(const char * ans, void * d)
+{
+GetUserCbData * gucbd;
+gucbd = (GetUserCbData *)d;
+
+bool * result = gucbd->result;
+
+//REQUEST * req = (REQUEST *)gucbd->data;
+
+//printf("ans=%s\n", ans);
+if (strcasecmp("Ok", ans) == 0)
+ *result = true;
+else
+ *result = false;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+struct StringReqParams
+{
+ string name;
+ RESETABLE<string> reqParam;
+ string * value;
+};
+//-----------------------------------------------------------------------------
+void RecvUserData(USERDATA * ud, void * d)
+{
+GetUserCbData * gucbd;
+gucbd = (GetUserCbData *)d;
+
+bool * result = gucbd->result;
+
+REQUEST * req = (REQUEST *)gucbd->data;
+
+if (ud->login == "")
+ {
+ *result = false;
+ return;
+ }
+
+if (!req->cash.res_empty())
+ cout << "cash=" << ud->cash << endl;
+
+if (!req->credit.res_empty())
+ cout << "credit=" << ud->credit << endl;
+
+if (!req->down.res_empty())
+ cout << "down=" << ud->down << endl;
+
+if (!req->passive.res_empty())
+ cout << "passive=" << ud->passive << endl;
+
+if (!req->disableDetailStat.res_empty())
+ cout << "disableDetailStat=" << ud->disableDetailStat << endl;
+
+if (!req->alwaysOnline.res_empty())
+ cout << "alwaysOnline=" << ud->alwaysOnline << endl;
+
+if (!req->prepaidTraff.res_empty())
+ cout << "prepaidTraff=" << ud->prepaidTraff << endl;
+
+for (int i = 0; i < DIR_NUM; i++)
+ {
+ if (!req->u[i].res_empty())
+ cout << "u" << i << "=" << ud->stat.mu[i] << endl;
+ if (!req->d[i].res_empty())
+ cout << "d" << i << "=" << ud->stat.md[i] << endl;
+ }
+
+for (int i = 0; i < USERDATA_NUM; i++)
+ {
+ if (!req->ud[i].res_empty())
+ {
+ string str;
+ ConvertFromKOI8(ud->userData[i], &str);
+ cout << "userdata" << i << "=" << str << endl;
+ }
+ }
+
+StringReqParams strReqParams[] =
+{
+ {"note", req->note, &ud->note},
+ {"name", req->name, &ud->name},
+ {"address", req->address, &ud->address},
+ {"email", req->email, &ud->email},
+ {"phone", req->phone, &ud->phone},
+ {"group", req->group, &ud->group},
+ {"tariff", req->tariff, &ud->tariff},
+ {"password", req->usrPasswd, &ud->password},
+ {"ip", req->ips, &ud->ips} // IP-address of user
+};
+for (unsigned i = 0; i < sizeof(strReqParams) / sizeof(StringReqParams); i++)
+ {
+ if (!strReqParams[i].reqParam.res_empty())
+ {
+ string str;
+ ConvertFromKOI8(*strReqParams[i].value, &str);
+ cout << strReqParams[i].name << "=" << str << endl;
+ }
+ }
+*result = true;
+}
+//-----------------------------------------------------------------------------
+int ProcessSetUser(const std::string &server,
+ int port,
+ const std::string &admLogin,
+ const std::string &admPasswd,
+ const std::string &str,
+ void * data,
+ bool isMessage)
+{
+SERVCONF sc;
+
+bool result = false;
+
+
+sc.SetServer(server.c_str()); // õÓÔÁÎÁ×ÌÉ×ÁÅÍ ÉÍÑ ÓÅÒ×ÅÒÁ Ó ËÏÔÏÒÇÏ ÚÁÂÉÒÁÔØ ÉÎÆÕ
+sc.SetPort(port); // ÁÄÍÉÎÓËÉÊ ÐÏÒÔ ÓÅÒ×ÅÒÁÐÏÒÔ
+sc.SetAdmLogin(admLogin.c_str()); // ÷ÙÓÔÁ×ÌÑÅÍ ÌÏÇÉÎ É ÐÁÒÏÌØ ÁÄÍÉÎÁ
+sc.SetAdmPassword(admPasswd.c_str());
+
+// TODO Good variable name :)
+GetUserCbData gucbd;
+
+gucbd.data = data;
+gucbd.result = &result;
+
+if (isMessage)
+ {
+ sc.SetSendMessageCb(RecvSetUserAnswer, &gucbd);
+ sc.MsgUser(str.c_str());
+ }
+else
+ {
+ sc.SetChgUserCb(RecvSetUserAnswer, &gucbd);
+ sc.ChgUser(str.c_str());
+ }
+
+if (result)
+ {
+ printf("Ok\n");
+ return 0;
+ }
+else
+ {
+ printf("Error\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int ProcessGetUser(const std::string &server,
+ int port,
+ const std::string &admLogin,
+ const std::string &admPasswd,
+ const std::string &login,
+ void * data)
+{
+SERVCONF sc;
+
+bool result = false;
+
+sc.SetServer(server.c_str()); // õÓÔÁÎÁ×ÌÉ×ÁÅÍ ÉÍÑ ÓÅÒ×ÅÒÁ Ó ËÏÔÏÒÇÏ ÚÁÂÉÒÁÔØ ÉÎÆÕ
+sc.SetPort(port); // ÁÄÍÉÎÓËÉÊ ÐÏÒÔ ÓÅÒ×ÅÒÁÐÏÒÔ
+sc.SetAdmLogin(admLogin.c_str()); // ÷ÙÓÔÁ×ÌÑÅÍ ÌÏÇÉÎ É ÐÁÒÏÌØ ÁÄÍÉÎÁ
+sc.SetAdmPassword(admPasswd.c_str());
+
+// TODO Good variable name :)
+GetUserCbData gucbd;
+
+gucbd.data = data;
+gucbd.result = &result;
+
+sc.SetGetUserDataRecvCb(RecvUserData, &gucbd);
+sc.GetUser(login.c_str());
+
+if (result)
+ {
+ printf("Ok\n");
+ return 0;
+ }
+else
+ {
+ printf("Error\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
+
--- /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 <string>
+
+#include "servconf.h"
+#include "request.h"
+
+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);
+
+int ProcessGetUser(const std::string &server,
+ int port,
+ const std::string &admLogin,
+ const std::string &admPasswd,
+ const std::string &login,
+ void * data);
+
+int ProcessSetUser(const std::string &server,
+ int port,
+ const std::string &admLogin,
+ const std::string &admPasswd,
+ const std::string &str,
+ void * data,
+ bool isMessage = false);
+
+#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.25 $
+ $Date: 2010/03/25 14:37:43 $
+ */
+
+#include <unistd.h>
+#include <getopt.h>
+#include <iconv.h>
+#include <langinfo.h>
+
+#include <cerrno>
+#include <clocale>
+#include <cstdio>
+#include <cstring>
+#include <string>
+#include <list>
+#include <sstream>
+
+#include "request.h"
+#include "common.h"
+#include "netunit.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
+{"disable-stat",0, 0, 'S'}, //disable detail stat
+{"always-online",0, 0, 'O'}, //always online
+{"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
+{"ip", 0, 0, 'I'}, //IP-address of user
+
+{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
+{"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
+{"ip", 0, 0, 'I'}, //IP-address of user
+
+{0, 0, 0, 0}};
+
+//-----------------------------------------------------------------------------
+double ParseCash(const char * c, string * message)
+{
+//-c 123.45:log message
+double cash;
+char * msg;
+char * str;
+str = new char[strlen(c)];
+
+strcpy(str, c);
+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, 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.res_empty())
+ {
+ string msg;
+ Encode12str(msg, req->usrMsg);
+ 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.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())
+ {
+ 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.res_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.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);
+ }
+
+if (!req->disableDetailStat.res_empty())
+ {
+ sprintf(str, "<disableDetailStat value=\"%d\" />\n", req->disableDetailStat.const_data());
+ strcat(r, str);
+ }
+
+if (!req->alwaysOnline.res_empty())
+ {
+ sprintf(str, "<aonline value=\"%d\" />\n", req->alwaysOnline.const_data());
+ strcat(r, str);
+ }
+
+// IP-address of user
+if (!req->ips.res_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->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())
+ {
+ string note;
+ Encode12str(note, req->note);
+ sprintf(str, "<note value=\"%s\"/>", note.c_str());
+ strcat(r, str);
+ }
+
+if (!req->name.res_empty())
+ {
+ string name;
+ Encode12str(name, req->name);
+ sprintf(str, "<name value=\"%s\"/>", name.c_str());
+ strcat(r, str);
+ }
+
+if (!req->address.res_empty())
+ {
+ string address;
+ Encode12str(address, req->address);
+ sprintf(str, "<address value=\"%s\"/>", address.c_str());
+ strcat(r, str);
+ }
+
+if (!req->email.res_empty())
+ {
+ string email;
+ Encode12str(email, req->email);
+ sprintf(str, "<email value=\"%s\"/>", email.c_str());
+ strcat(r, str);
+ }
+
+if (!req->phone.res_empty())
+ {
+ string phone;
+ Encode12str(phone, req->phone);
+ sprintf(str, "<phone value=\"%s\"/>", phone.c_str());
+ strcat(r, str);
+ }
+
+if (!req->group.res_empty())
+ {
+ string group;
+ Encode12str(group, req->group);
+ sprintf(str, "<group value=\"%s\"/>", group.c_str());
+ strcat(r, str);
+ }
+
+for (int i = 0; i < USERDATA_NUM; i++)
+ {
+ if (!req->ud[i].res_empty())
+ {
+ string ud;
+ Encode12str(ud, req->ud[i]);
+ sprintf(str, "<userdata%d value=\"%s\"/>", i, ud.c_str());
+ strcat(r, str);
+ }
+ }
+
+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()
+ || !req->ips.res_empty() // IP-address of user
+
+ || !req->createUser
+ || !req->deleteUser;
+
+
+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;
+int missedOptionArg = false;
+
+const char * short_options_get = "s:p:a:w:u:crtmodieNADLPGISO";
+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 '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
+ 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 '?':
+ case ':':
+ //printf ("Unknown option \n");
+ 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);
+ }
+
+return ProcessGetUser(req.server, req.port, req.admLogin, req.admPasswd, req.login, &req);
+}
+//-----------------------------------------------------------------------------
+int 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:";
+
+int missedOptionArg = false;
+
+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
+ ParseAnyString(optarg, &str);
+ req.usrMsg = str;
+ isMessage = true;
+ 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, "koi8-r");
+ req.name = str;
+ break;
+
+ case 'D': //aDdress
+ ParseAnyString(optarg, &str);
+ req.address = str;
+ break;
+
+ case 'L': //emaiL
+ ParseAnyString(optarg, &str);
+ req.email = str;
+ //printf("EMAIL=%s\n", optarg);
+ break;
+
+ case 'P': //phone
+ ParseAnyString(optarg, &str);
+ req.phone = str;
+ break;
+
+ case 'G': //Group
+ ParseAnyString(optarg, &str);
+ req.group = str;
+ break;
+
+ case 'I': //IP-address of user
+ ParseAnyString(optarg, &str);
+ req.ips = str;
+ break;
+
+ case 'S':
+ req.disableDetailStat = ParseDownPassive(optarg);
+ break;
+
+ case 'O':
+ req.alwaysOnline = ParseDownPassive(optarg);
+ 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("Missing option argument\n");
+ missedOptionArg = true;
+ break;
+
+ case ':':
+ //printf("Missing option argument\n");
+ 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);
+
+CreateRequestSet(&req, rstr);
+return ProcessSetUser(req.server, req.port, req.admLogin, req.admPasswd, rstr, NULL, isMessage);
+}
+//-----------------------------------------------------------------------------
+int main(int argc, char **argv)
+{
+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");
+ return mainSet(argc - 1, argv + 1);
+ }
+else
+ {
+ UsageConf();
+ exit(PARAMETER_PARSING_ERR_CODE);
+ }
+return UNKNOWN_ERR_CODE;
+}
+//-----------------------------------------------------------------------------
+
--- /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.4 $
+ $Date: 2008/05/11 08:15:07 $
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <expat.h>
+#include <string.h>
+
+#include <string>
+#include <list>
+
+#include "common.h"
+#include "netunit.h"
+#include "request.h"
+
+using namespace std;
+
+int parse_depth = 0;
+XML_Parser parser;
+//---------------------------------------------------------------------------
+int ParseAns(void * data, const char *el, const char **attr)
+{
+if (strcasecmp(attr[1], "ok") == 0)
+ {
+ return 0;
+ }
+if (strcasecmp(attr[1], "error") == 0)
+ {
+ return 1;
+ }
+if (strcasecmp(attr[1], "err") == 0)
+ {
+ return 1;
+ }
+return -1;
+}
+//---------------------------------------------------------------------------
+void StartElement(void *data, const char *el, const char **attr)
+{
+parse_depth++;
+if (parse_depth == 1)
+ {
+ if (ParseAns(data, el, attr) < 0)
+ {
+ printf("Unexpected token\n");
+ exit(UNKNOWN_ERR_CODE);
+ }
+ if (ParseAns(data, el, attr) == 1)
+ {
+ printf("User not found\n");
+ exit(USER_NOT_FOUND_ERR_CODE);
+ }
+ return;
+ }
+}
+//-----------------------------------------------------------------------------
+void EndElement(void *data, const char *el)
+{
+parse_depth--;
+}
+//---------------------------------------------------------------------------
+int ParseReply(void * data, list<string> * ans)
+{
+int done = 0;
+int len;
+
+parse_depth = 0;
+parser = XML_ParserCreate(NULL);
+
+if (!parser)
+ {
+ printf("Couldn't allocate memory for parser\n");
+ exit(UNKNOWN_ERR_CODE);
+ }
+
+XML_ParserReset(parser, NULL);
+XML_SetElementHandler(parser, StartElement, EndElement);
+
+list<string>::iterator n = ans->begin();
+while (n != ans->end())
+ {
+ len = strlen(n->c_str());
+
+ if (++n == ans->end())
+ done = 1;
+ n--;
+
+ if (XML_Parse(parser, n->c_str(), len, done) == XML_STATUS_ERROR)
+ {
+ char s[128];
+ printf(s, "Parse error at line %d:\n%s\n",
+ XML_GetCurrentLineNumber(parser),
+ XML_ErrorString(XML_GetErrorCode(parser)));
+ exit(UNKNOWN_ERR_CODE);
+ }
+
+ ++n;
+ }
+
+XML_ParserFree(parser);
+return 0;
+}
+//-----------------------------------------------------------------------------
+
--- /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 "resetable.h"
+#include "stg_const.h"
+#include "os_int.h"
+
+#define TARIFF_NOW (0)
+#define TARIFF_DEL (1)
+#define TARIFF_REC (2)
+
+using namespace std;
+//-----------------------------------------------------------------------------
+struct REQUEST
+{
+
+REQUEST()
+{
+ for (int i = 0; i < DIR_NUM; i++)
+ {
+ u[i].reset();
+ d[i].reset();
+ }
+
+ for (int i = 0; i < USERDATA_NUM; i++)
+ ud[i].reset();
+
+ createUser = false;
+ deleteUser = false;
+}
+
+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;
+
+RESETABLE<string> usrMsg;
+RESETABLE<double> credit;
+RESETABLE<string> usrPasswd;
+RESETABLE<bool> down;
+RESETABLE<bool> passive;
+RESETABLE<bool> disableDetailStat;
+RESETABLE<bool> alwaysOnline;
+RESETABLE<double> prepaidTraff;
+
+RESETABLE<int64_t> u[DIR_NUM];
+RESETABLE<int64_t> d[DIR_NUM];
+
+RESETABLE<string> ud[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
+/*
+ * 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 "request.h"
+#include "common.h"
+#include "netunit.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)];
+
+strcpy(str, c);
+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-r";
+
+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
+/*
+ * 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
+
+
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.45 2009/03/20 15:47:10 faust Exp $
+###############################################################################
+
+include ../../Makefile.conf
+
+PROG = stargazer
+
+SRCS = ./admin.cpp \
+ ./admins.cpp \
+ ./main.cpp \
+ ./curr_ip.cpp \
+ ./settings.cpp \
+ ./stg_timer.cpp \
+ ./tariff.cpp \
+ ./tariffs.cpp \
+ ./traffcounter.cpp \
+ ./user.cpp \
+ ./user_property.cpp \
+ ./users.cpp \
+ ./plugin_runner.cpp \
+ ./store_loader.cpp \
+ ./pidfile.cpp
+
+STGLIBS = -lstg_logger \
+ -lstg_locker \
+ -lstg_common \
+ -lscript_executer \
+ -ldotconfpp
+
+LIBS += -lexpat
+
+ifeq ($(OS),linux)
+LIBS += $(LIB_THREAD) \
+ -ldl
+else
+LIBS += $(LIB_THREAD) \
+ -lc
+endif
+
+SEARCH_DIRS = -I $(DIR_INCLUDE)
+
+OBJS = $(notdir $(patsubst %.cpp, %.o, $(patsubst %.c, %.o, $(SRCS))))
+
+CXXFLAGS += -Wall -W
+LDFLAGS += -Wl,-E -L$(DIR_LIB) -Wl,-rpath,$(PREFIX)/usr/lib/stg -Wl,-rpath-link,$(DIR_LIB)
+vpath %.so $(DIR_LIB)
+
+.PHONY: all clean distclean libs plugins install uninstall install-bin install-data
+all: libs plugins $(PROG)
+
+libs:
+ $(MAKE) -C $(DIR_LIBSRC)
+
+plugins: libs
+ $(MAKE) -C $(DIR_PLUGINS)
+
+$(PROG): $(OBJS) $(STGLIBS)
+ $(CC) $^ $(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*
+ $(MAKE) -C $(DIR_LIBSRC) clean
+ $(MAKE) -C $(DIR_PLUGINS) clean
+
+distclean: clean
+ rm -f $(DIR_MOD)/*
+ rm -f ../../Makefile.conf
+
+install: install-bin install-data
+
+install-bin:
+ mkdir -m $(BIN_MODE) -p $(PREFIX)/usr/sbin
+ install -m $(BIN_MODE) -o $(OWNER) -s $(PROG) $(PREFIX)/usr/sbin/$(PROG)
+ $(MAKE) -C $(DIR_LIBSRC) install
+ $(MAKE) -C $(DIR_PLUGINS) install
+
+install-data:
+ # Install etc
+ mkdir -m $(DATA_MODE) -p $(PREFIX)/etc/stargazer
+ install -m $(DATA_MODE) -o $(OWNER) $(ETC_DIR)/stargazer.conf $(PREFIX)/etc/stargazer/stargazer.conf
+ install -m $(DATA_MODE) -o $(OWNER) $(ETC_DIR)/rules $(PREFIX)/etc/stargazer/rules
+ install -m $(BIN_MODE) -o $(OWNER) $(ETC_DIR)/On* $(PREFIX)/etc/stargazer/
+
+ # Install file db
+ mkdir -m $(DATA_MODE) -p $(PREFIX)/var/stargazer/admins
+ mkdir -m $(DATA_MODE) -p $(PREFIX)/var/stargazer/tariffs
+ mkdir -m $(DATA_MODE) -p $(PREFIX)/var/stargazer/users/test
+ install -m $(DATA_MODE) -o $(OWNER) $(VAR_DIR)/admins/admin.adm $(PREFIX)/var/stargazer/admins/admin.adm
+ install -m $(DATA_MODE) -o $(OWNER) $(VAR_DIR)/tariffs/tariff.tf $(PREFIX)/var/stargazer/tariffs/tariff.tf
+ install -m $(DATA_MODE) -o $(OWNER) $(VAR_DIR)/users/test/conf $(PREFIX)/var/stargazer/users/test/conf
+ install -m $(DATA_MODE) -o $(OWNER) $(VAR_DIR)/users/test/stat $(PREFIX)/var/stargazer/users/test/stat
+
+ifeq ($(CHECK_FBCLIENT),yes)
+ # Install firebird db
+ mkdir -p $(PREFIX)/var/stargazer
+ chown $(OWNER):$(FIREBIRD_GROUP) $(PREFIX)/var/stargazer
+ chmod g+rw $(PREFIX)/var/stargazer
+ echo "connect '$(DB_ADDRESS)' user '$(DB_USER)' password '$(DB_PASSWORD)';" > .db.sql
+ echo "drop database;" >> .db.sql
+ echo "create database '$(DB_ADDRESS)' user '$(DB_USER)' password '$(DB_PASSWORD)' default character set win1251;" >> .db.sql
+ cat $(VAR_DIR)/../00-base-00.sql >> .db.sql
+ $(FIREBIRD_ISQL) -i .db.sql
+ rm -f .db.sql
+endif
+
+uninstall: uninstall-bin uninstall-data
+
+uninstall-bin:
+ rm -f $(PREFIX)/usr/sbin/$(PROG)
+ $(MAKE) -C $(DIR_LIBSRC) uninstall
+ $(MAKE) -C $(DIR_PLUGINS) uninstall
+ rm -rf $(PREFIX)/usr/lib/stg
+
+uninstall-data:
+ # Uninstall etc
+ rm -rf $(PREFIX)/etc/stargazer
+ rm -rf $(PREFIX)/var/stargazer
+
+
+ifneq ($(MAKECMDGOALS),distclean)
+ifneq ($(MAKECMDGOALS),clean)
+ifneq ($(MAKECMDGOALS),uninstall)
+-include deps
+endif
+endif
+endif
+
+deps: $(SRCS) ../../Makefile.conf
+ $(MAKE) -C $(DIR_LIBSRC) includes
+ @>deps ;\
+ for file in $(SRCS); do\
+ echo "`$(CC) $(CXXFLAGS) $(SEARCH_DIRS) -MM $$file` Makefile ../../Makefile.conf" >> deps ;\
+ echo -e '\t$$(CC) -c $$< $(CXXFLAGS) $(SEARCH_DIRS) $(DEFS)' >> deps ;\
+ done
+
+
--- /dev/null
+1. éÓÐÒÁ×ÌÅÎÁ ÏÛÉÂËÁ × ÐÌÁÇÉÎÅ ËÏÎÆÉÇÕÒÁÔÏÒÁ ÐÒÉ×ÏÄÉ×ÛÁÑ Ë ÐÁÄÅÎÉÀ ÓÅÒ×ÅÒÁ
+2. ðÅÒÅÒÁÂÏÔÁÎ ËÏÄ ÐÌÁÇÉÎÁ Á×ÔÏÒÉÚÁÃÉÉ inetaccess. õ×ÅÌÉÞÅÎÁ ÓËÏÒÏÓÔØ ÅÇÏ
+ ÒÁÂÏÔÙ
+3. éÓÐÒÁ×ÌÅÎÁ ÏÛÉÂËÁ, ÐÒÉ×ÏÄÉ×ÛÁÑ Ë ÓÌÉÛËÏÍ ÞÁÓÔÏÊ ÚÁÐÉÓÉ ÆÁÊÌÏ× stat É conf,
+ É ÓÏÏÔ×ÅÔÓÔ×ÅÎÎÏ Ë ×ÙÓÏËÏÊ ÚÁÇÒÕÚËÅ ÐÒÏÃÅÓÓÏÒÁ
+4. éÓÐÒÁ×ÌÅÎÁ ÏÛÉÂËÁ × ÏÂÒÁÂÏÔËÅ ÐÏÒÏÇÁ ÔÁÒÉÆÁ. ðÒÉ ÔÒÁÆÉËÅ ÂÏÌÅÅ 2 ç ÐÏÒÏÇ
+ ÐÅÒÅÓÔÁ×ÁÌ ÒÁÂÏÔÁÔØ
+5. äÏÂÁ×ÌÅÎÁ ×ÏÚÍÏÖÎÏÓÔØ ×ÙÐÏÌÎÑÔØ ÓËÒÉÐÔÙ OnConnect É OnDisconnect ÕÄÁÌÅÎÎÏ
+ (ôÏÌØËÏ ÄÌÑ ÔÅÓÔÏ×)
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.50 2010/10/07 18:27:27 faust Exp $
+###############################################################################
+
+include ../../Makefile.conf
+
+PROG = stargazer
+
+SRCS = ./admin.cpp \
+ ./admins.cpp \
+ ./main.cpp \
+ ./settings.cpp \
+ ./stg_timer.cpp \
+ ./tariff.cpp \
+ ./tariffs.cpp \
+ ./traffcounter.cpp \
+ ./user.cpp \
+ ./user_property.cpp \
+ ./users.cpp \
+ ./plugin_runner.cpp \
+ ./store_loader.cpp \
+ ./pidfile.cpp \
+ ./eventloop.cpp
+
+STGLIBS = -lstg_logger \
+ -lstg_locker \
+ -lstg_common \
+ -lscript_executer \
+ -ldotconfpp
+
+LIBS += -lexpat
+
+ifeq ($(OS),linux)
+LIBS += $(LIB_THREAD) \
+ -ldl
+else
+LIBS += $(LIB_THREAD) \
+ -lc
+endif
+
+SEARCH_DIRS = -I $(DIR_INCLUDE)
+
+OBJS = $(notdir $(patsubst %.cpp, %.o, $(patsubst %.c, %.o, $(SRCS))))
+
+LDFLAGS += -Wl,-E -L$(DIR_LIB) -Wl,-rpath,$(PREFIX)/usr/lib/stg -Wl,-rpath-link,$(DIR_LIB)
+vpath %.so $(DIR_LIB)
+
+.PHONY: all clean distclean libs plugins install uninstall install-bin install-data
+all: libs plugins $(PROG)
+
+libs:
+ $(MAKE) -C $(DIR_LIBSRC)
+
+plugins: libs
+ $(MAKE) -C $(DIR_PLUGINS)
+
+$(PROG): $(OBJS) libs
+ $(CC) $(OBJS) $(LDFLAGS) $(LIBS) $(STGLIBS) -o $(PROG)
+
+clean:
+ rm -f deps $(PROG) *.o tags *.*~ .OS
+ rm -f .OS
+ rm -f .store
+ rm -f .db.sql
+ rm -f core*
+ $(MAKE) -C $(DIR_LIBSRC) clean
+ $(MAKE) -C $(DIR_PLUGINS) clean
+
+distclean: clean
+ rm -f $(DIR_MOD)/*
+ rm -f ../../Makefile.conf
+
+install: install-bin install-data
+
+install-bin:
+ mkdir -m $(BIN_MODE) -p $(PREFIX)/usr/sbin
+ install -m $(BIN_MODE) -o $(OWNER) -s $(PROG) $(PREFIX)/usr/sbin/$(PROG)
+ $(MAKE) -C $(DIR_LIBSRC) install
+ $(MAKE) -C $(DIR_PLUGINS) install
+
+install-data:
+ # Install etc
+ mkdir -m $(DATA_MODE) -p $(PREFIX)/etc/stargazer
+ install -m $(DATA_MODE) -o $(OWNER) $(ETC_DIR)/stargazer.conf $(PREFIX)/etc/stargazer/stargazer.conf
+ install -m $(DATA_MODE) -o $(OWNER) $(ETC_DIR)/rules $(PREFIX)/etc/stargazer/rules
+ install -m $(BIN_MODE) -o $(OWNER) $(ETC_DIR)/On* $(PREFIX)/etc/stargazer/
+
+ # Install file db
+ mkdir -m $(DATA_MODE) -p $(PREFIX)/var/stargazer/admins
+ mkdir -m $(DATA_MODE) -p $(PREFIX)/var/stargazer/tariffs
+ mkdir -m $(DATA_MODE) -p $(PREFIX)/var/stargazer/users/test
+ install -m $(DATA_MODE) -o $(OWNER) $(VAR_DIR)/admins/admin.adm $(PREFIX)/var/stargazer/admins/admin.adm
+ install -m $(DATA_MODE) -o $(OWNER) $(VAR_DIR)/tariffs/tariff.tf $(PREFIX)/var/stargazer/tariffs/tariff.tf
+ install -m $(DATA_MODE) -o $(OWNER) $(VAR_DIR)/users/test/conf $(PREFIX)/var/stargazer/users/test/conf
+ install -m $(DATA_MODE) -o $(OWNER) $(VAR_DIR)/users/test/stat $(PREFIX)/var/stargazer/users/test/stat
+
+ifeq ($(CHECK_FBCLIENT),yes)
+ # Install firebird db
+ mkdir -p $(PREFIX)/var/stargazer
+ chown $(OWNER):$(FIREBIRD_GROUP) $(PREFIX)/var/stargazer
+ chmod g+rw $(PREFIX)/var/stargazer
+ echo "connect '$(DB_ADDRESS)' user '$(DB_USER)' password '$(DB_PASSWORD)';" > .db.sql
+ echo "drop database;" >> .db.sql
+ echo "create database '$(DB_ADDRESS)' user '$(DB_USER)' password '$(DB_PASSWORD)' default character set win1251;" >> .db.sql
+ cat $(VAR_DIR)/../00-base-00.sql >> .db.sql
+ $(FIREBIRD_ISQL) -i .db.sql
+ rm -f .db.sql
+endif
+
+uninstall: uninstall-bin uninstall-data
+
+uninstall-bin:
+ rm -f $(PREFIX)/usr/sbin/$(PROG)
+ $(MAKE) -C $(DIR_LIBSRC) uninstall
+ $(MAKE) -C $(DIR_PLUGINS) uninstall
+ rm -rf $(PREFIX)/usr/lib/stg
+
+uninstall-data:
+ # Uninstall etc
+ rm -rf $(PREFIX)/etc/stargazer
+ rm -rf $(PREFIX)/var/stargazer
+
+
+ifneq ($(MAKECMDGOALS),distclean)
+ifneq ($(MAKECMDGOALS),clean)
+ifneq ($(MAKECMDGOALS),uninstall)
+-include deps
+endif
+endif
+endif
+
+deps: $(SRCS) ../../Makefile.conf
+ $(MAKE) -C $(DIR_LIBSRC) includes
+ @>deps ;\
+ for file in $(SRCS); do\
+ echo "`$(CC) $(CXXFLAGS) $(SEARCH_DIRS) -MM $$file` Makefile ../../Makefile.conf" >> deps ;\
+ echo -e '\t$$(CC) -c $$< $(CXXFLAGS) $(SEARCH_DIRS) $(DEFS)' >> deps ;\
+ done
+
+
--- /dev/null
+éÎÓÔÁÌÑÃÉÑ É ÚÁÐÕÓË.
+1. > ./build
+2. > make install
+3. ðÒÁ×ËÁ ËÏÎÆÉÇÕÒÁÃÉÏÎÎÙÈ ÆÁÊÌÏ×
+4. > stargazer
+
--- /dev/null
+1. äÏÂÁ×ÉÔØ ÐÁÒÁÍÅÔÒÙ × Á×ÔÏÒÉÚÁÔÏÒ É ËÏÎÆÉÇÕÒÁÔÏÒ HostAllow, ...
+2. äÏÂÁ×ÉÔØ ÐÁÒÁÍÅÔÒÙ × Á×ÔÏÒÉÚÁÔÏÒ FloodControl
+3. äÏÐÉÓÁÎÉÅ ÍÏÄÕÌÅÊ
+ - VPN
+4. óÅÒ×ÉÓÙ
+5. ëÏÒÐÏÒÁÃÉÉ
+6. óÔÁÒÔÏ×ÙÅ ÓËÒÉÐÔÙ ÄÌÑ ÒÁÚÎÙÈ ïó
--- /dev/null
+#ifndef __ACTIONS_H__
+#define __ACTIONS_H__
+
+// Usage:
+//
+// ACTIONS_LIST actionsList;
+// CLASS myClass;
+// DATA1 myData1;
+// DATA2 myData2;
+//
+// actionsList.Enqueue(myClass, &CLASS::myMethod1, myData1);
+// actionsList.Enqueue(myClass, &CLASS::myMethod2, myData2);
+//
+// actionsList.InvokeAll();
+
+#include <pthread.h>
+#include <list>
+#include <functional>
+
+// Generalized actor type - a method of some class with one argument
+template <class ACTIVE_CLASS, typename DATA_TYPE>
+struct ACTOR
+{
+typedef void (ACTIVE_CLASS::*TYPE)(DATA_TYPE);
+};
+
+// Abstract base action class for polymorphic action invocation
+class BASE_ACTION
+{
+public:
+ virtual ~BASE_ACTION() {};
+ virtual void Invoke() = 0;
+};
+
+// Concrete generalized action type - an actor with it's data and owner
+template <class ACTIVE_CLASS, typename DATA_TYPE>
+class ACTION : public BASE_ACTION,
+ public std::unary_function<ACTIVE_CLASS &, void>
+{
+public:
+ ACTION(ACTIVE_CLASS & ac,
+ typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE a,
+ DATA_TYPE d)
+ : activeClass(ac), actor(a), data(d) {};
+ void Invoke();
+private:
+ ACTIVE_CLASS & activeClass;
+ typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE actor;
+ DATA_TYPE data;
+};
+
+// A list of an actions
+// All methods are thread-safe
+class ACTIONS_LIST : private std::list<BASE_ACTION *>
+{
+public:
+ // Just a typedef for parent class
+ typedef std::list<BASE_ACTION *> parent;
+
+ // Initialize mutex
+ ACTIONS_LIST();
+ // Delete actions and destroy mutex
+ ~ACTIONS_LIST();
+
+ parent::iterator begin();
+ parent::iterator end();
+ parent::const_iterator begin() const;
+ parent::const_iterator end() const;
+
+ bool empty() const;
+ size_t size() const;
+ void swap(ACTIONS_LIST & list);
+
+ // Add an action to list
+ template <class ACTIVE_CLASS, typename DATA_TYPE>
+ void Enqueue(ACTIVE_CLASS & ac,
+ typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE a,
+ DATA_TYPE d);
+ // Invoke all actions in the list
+ void InvokeAll();
+private:
+ mutable pthread_mutex_t mutex;
+};
+
+#include "actions.inl.h"
+
+#endif
--- /dev/null
+#ifndef __ACTIONS_INL_H__
+#define __ACTIONS_INL_H__
+
+#include <algorithm>
+
+#include "stg_locker.h"
+
+// Polymorphick action invocation
+template <class ACTIVE_CLASS, typename DATA_TYPE>
+inline
+void ACTION<ACTIVE_CLASS, DATA_TYPE>::Invoke()
+{
+(activeClass.*actor)(data);
+}
+
+inline
+ACTIONS_LIST::ACTIONS_LIST()
+ : mutex()
+{
+pthread_mutex_init(&mutex, NULL);
+};
+
+// Delete all actions before deleting list
+inline
+ACTIONS_LIST::~ACTIONS_LIST()
+{
+
+ {
+ STG_LOCKER(&mutex, __FILE__, __LINE__);
+
+ parent::iterator it(parent::begin());
+ while (it != parent::end())
+ {
+ delete *it++;
+ }
+ }
+
+pthread_mutex_destroy(&mutex);
+};
+
+inline
+ACTIONS_LIST::parent::iterator ACTIONS_LIST::begin()
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+return parent::begin();
+};
+
+inline
+ACTIONS_LIST::parent::iterator ACTIONS_LIST::end()
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+return parent::end();
+};
+
+inline
+ACTIONS_LIST::parent::const_iterator ACTIONS_LIST::begin() const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+return parent::begin();
+};
+
+inline
+ACTIONS_LIST::parent::const_iterator ACTIONS_LIST::end() const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+return parent::end();
+};
+
+inline
+bool ACTIONS_LIST::empty() const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+return parent::empty();
+};
+
+inline
+size_t ACTIONS_LIST::size() const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+return parent::size();
+};
+
+inline
+void ACTIONS_LIST::swap(ACTIONS_LIST & list)
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+parent::swap(list);
+};
+
+template <class ACTIVE_CLASS, typename DATA_TYPE>
+inline
+void ACTIONS_LIST::Enqueue(ACTIVE_CLASS & ac,
+ typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE a,
+ DATA_TYPE d)
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+push_back(new ACTION<ACTIVE_CLASS, DATA_TYPE>(ac, a, d));
+}
+
+inline
+void ACTIONS_LIST::InvokeAll()
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+std::for_each(
+ parent::begin(),
+ parent::end(),
+ std::mem_fun(&BASE_ACTION::Invoke)
+);
+};
+
+#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
+ */
+
+/*
+ * Date: 27.10.2002
+ */
+
+/*
+ * Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+ /*
+ $Revision: 1.13 $
+ $Date: 2010/10/04 20:16:09 $
+ $Author: faust $
+ */
+
+#include "admin.h"
+#include "common.h"
+
+//-----------------------------------------------------------------------------
+ADMIN::ADMIN()
+ : conf(),
+ ip(0),
+ WriteServLog(GetStgLogger())
+{
+}
+//-----------------------------------------------------------------------------
+ADMIN::ADMIN(const ADMIN_CONF & ac)
+ : conf(ac),
+ ip(0),
+ WriteServLog(GetStgLogger())
+{
+}
+//-----------------------------------------------------------------------------
+ADMIN::ADMIN(const PRIV & priv, const std::string & login, const std::string & password)
+ : conf(priv, login, password),
+ ip(0),
+ WriteServLog(GetStgLogger())
+{
+}
+//-----------------------------------------------------------------------------
+ADMIN & ADMIN::operator=(const ADMIN & adm)
+{
+if (&adm == this)
+ return *this;
+
+conf = adm.conf;
+ip = adm.ip;
+return *this;
+}
+//-----------------------------------------------------------------------------
+ADMIN & ADMIN::operator=(const ADMIN_CONF & ac)
+{
+conf = ac;
+return *this;
+}
+//-----------------------------------------------------------------------------
+bool ADMIN::operator==(const ADMIN & rhs) const
+{
+return conf.login == rhs.GetLogin();
+}
+//-----------------------------------------------------------------------------
+bool ADMIN::operator!=(const ADMIN & rhs) const
+{
+return conf.login != rhs.GetLogin();
+}
+//-----------------------------------------------------------------------------
+bool ADMIN::operator<(const ADMIN & rhs) const
+{
+return conf.login < rhs.GetLogin();
+}
+//-----------------------------------------------------------------------------
+bool ADMIN::operator<=(const ADMIN & rhs) const
+{
+return conf.login <= rhs.GetLogin();
+}
+//-----------------------------------------------------------------------------
+string ADMIN::GetAdminIPStr() const
+{
+return inet_ntostring(ip);
+}
+//-----------------------------------------------------------------------------
+void ADMIN::PrintAdmin() const
+{
+printfd(__FILE__, "=======================================\n");
+printfd(__FILE__, "login %s\n", conf.login.c_str());
+printfd(__FILE__, "password %s\n", conf.password.c_str());
+printfd(__FILE__, "ChgConf %d\n", conf.priv.userConf);
+printfd(__FILE__, "ChgStat %d\n", conf.priv.userStat);
+printfd(__FILE__, "ChgCash %d\n", conf.priv.userCash);
+printfd(__FILE__, "UsrAddDel %d\n", conf.priv.userAddDel);
+printfd(__FILE__, "ChgAdmin %d\n", conf.priv.adminChg);
+printfd(__FILE__, "ChgTariff %d\n", conf.priv.tariffChg);
+printfd(__FILE__, "=======================================\n");
+}
+//-----------------------------------------------------------------------------
+const string ADMIN::GetLogStr() const
+{
+return "Admin \'" + conf.login + "\', " + GetAdminIPStr() + ":";
+}
+//-----------------------------------------------------------------------------
--- /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>
+ */
+
+ /*
+ $Revision: 1.14 $
+ $Date: 2010/10/04 20:15:43 $
+ $Author: faust $
+ */
+
+#ifndef ADMIN_H
+#define ADMIN_H
+
+#include <string>
+
+#include "os_int.h"
+#include "admin_conf.h"
+#include "stg_logger.h"
+
+using namespace std;
+
+//-----------------------------------------------------------------------------
+class ADMIN
+{
+public:
+ ADMIN();
+ ADMIN(const ADMIN_CONF & ac);
+ ADMIN(const PRIV & priv,
+ const std::string & login,
+ const std::string & password);
+ ~ADMIN() {};
+
+ ADMIN & operator=(const ADMIN &);
+ ADMIN & operator=(const ADMIN_CONF &);
+ bool operator==(const ADMIN & rhs) const;
+ bool operator!=(const ADMIN & rhs) const;
+ bool operator<(const ADMIN & rhs) const;
+ bool operator<=(const ADMIN & rhs) const;
+
+ const string & GetPassword() const { return conf.password; };
+ const string & GetLogin() const { return conf.login; };
+ PRIV const * GetPriv() const { return &conf.priv; };
+ uint16_t GetPrivAsInt() const { return conf.priv.ToInt(); };
+ const ADMIN_CONF & GetConf() const { return conf; };
+ void PrintAdmin() const;
+ uint32_t GetAdminIP() const { return ip; };
+ string GetAdminIPStr() const;
+ void SetAdminIP(uint32_t ip) { ADMIN::ip = ip; };
+ const string GetLogStr() const;
+
+private:
+ ADMIN_CONF conf;
+ uint32_t ip;
+ STG_LOGGER & WriteServLog;
+};
+//-----------------------------------------------------------------------------
+
+#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
+ */
+
+/*
+ * Date: 27.10.2002
+ */
+
+/*
+ * Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+ /*
+ $Revision: 1.15 $
+ $Date: 2010/10/04 20:17:12 $
+ $Author: faust $
+ */
+
+#include <cerrno>
+#include <cassert>
+#include <algorithm>
+
+#include "admins.h"
+#include "admin.h"
+#include "common.h"
+
+using namespace std;
+
+//-----------------------------------------------------------------------------
+ADMINS::ADMINS(BASE_STORE * st)
+ : stg(0xFFFF, "@stargazer", ""),
+ noAdmin(0xFFFF, "NO-ADMIN", ""),
+ data(),
+ store(st),
+ WriteServLog(GetStgLogger()),
+ searchDescriptors(),
+ handle(0)
+{
+pthread_mutex_init(&mutex, NULL);
+ReadAdmins();
+}
+//-----------------------------------------------------------------------------
+int ADMINS::Add(const string & login, const ADMIN & admin)
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+const PRIV * priv = admin.GetPriv();
+
+if (!priv->adminChg)
+ {
+ string s = admin.GetLogStr() + " Add administrator \'" + login + "\'. Access denied.";
+ strError = "Access denied.";
+ WriteServLog(s.c_str());
+ return -1;
+ }
+
+ADMIN adm(0, login, "");
+admin_iter ai(find(data.begin(), data.end(), adm));
+
+if (ai != data.end())
+ {
+ strError = "Administrator \'" + login + "\' cannot not be added. Administrator alredy exist.";
+ WriteServLog("%s %s", admin.GetLogStr().c_str(), strError.c_str());
+
+ return -1;
+ }
+
+data.push_back(adm);
+/*ADMIN_CONF ac;
+ac.login = login;*/
+if (store->AddAdmin(login) == 0 /*&& store->SaveAdmin(ac) == 0*/)
+ {
+ WriteServLog("%s Administrator \'%s\' added.",
+ admin.GetLogStr().c_str(), login.c_str());
+ return 0;
+ }
+
+strError = "Administrator \'" + login + "\' was not added. Error: " + store->GetStrError();
+WriteServLog("%s %s", admin.GetLogStr().c_str(), strError.c_str());
+
+return -1;
+}
+//-----------------------------------------------------------------------------
+int ADMINS::Del(const string & login, const ADMIN & admin)
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ADMIN adm(0, login, "");
+const PRIV * priv = admin.GetPriv();
+
+if (!priv->adminChg)
+ {
+ string s = admin.GetLogStr() + " Delete administrator \'" + login + "\'. Access denied.";
+ strError = "Access denied.";
+ WriteServLog(s.c_str());
+ return -1;
+ }
+
+admin_iter ai(find(data.begin(), data.end(), adm));
+
+if (ai == data.end())
+ {
+ strError = "Administrator \'" + login + "\' cannot be deleted. Administrator does not exist.";
+ WriteServLog("%s %s", admin.GetLogStr().c_str(), strError.c_str());
+ return -1;
+ }
+
+map<int, const_admin_iter>::iterator si;
+si = searchDescriptors.begin();
+while (si != searchDescriptors.end())
+ {
+ if (si->second == ai)
+ (si->second)++;
+ si++;
+ }
+
+data.remove(*ai);
+if (store->DelAdmin(login) < 0)
+ {
+ strError = "Administrator \'" + login + "\' was not deleted. Error: " + store->GetStrError();
+ WriteServLog("%s %s", admin.GetLogStr().c_str(), strError.c_str());
+
+ return -1;
+ }
+
+WriteServLog("%s Administrator \'%s\' deleted.", admin.GetLogStr().c_str(), login.c_str());
+return 0;
+}
+//-----------------------------------------------------------------------------
+int ADMINS::Change(const ADMIN_CONF & ac, const ADMIN & admin)
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+const PRIV * priv = admin.GetPriv();
+
+if (!priv->adminChg)
+ {
+ string s = admin.GetLogStr() + " Change administrator \'" + ac.login + "\'. Access denied.";
+ strError = "Access denied.";
+ WriteServLog(s.c_str());
+ return -1;
+ }
+
+ADMIN adm(0, ac.login, "");
+admin_iter ai(find(data.begin(), data.end(), adm));
+
+if (ai == data.end())
+ {
+ strError = "Administrator \'" + ac.login + "\' cannot be changed " + ". Administrator does not exist.";
+ WriteServLog("%s %s", admin.GetLogStr().c_str(), strError.c_str());
+ return -1;
+ }
+
+*ai = ac;
+if (store->SaveAdmin(ac))
+ {
+ WriteServLog("Cannot write admin %s.", ac.login.c_str());
+ WriteServLog("%s", store->GetStrError().c_str());
+ return -1;
+ }
+
+WriteServLog("%s Administrator \'%s\' changed.",
+ admin.GetLogStr().c_str(), ac.login.c_str());
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int ADMINS::ReadAdmins()
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+vector<string> adminsList;
+if (store->GetAdminsList(&adminsList) < 0)
+ {
+ WriteServLog(store->GetStrError().c_str());
+ return -1;
+ }
+
+for (unsigned int i = 0; i < adminsList.size(); i++)
+ {
+ ADMIN_CONF ac(0, adminsList[i], "");
+
+ if (store->RestoreAdmin(&ac, adminsList[i]))
+ {
+ WriteServLog(store->GetStrError().c_str());
+ return -1;
+ }
+
+ data.push_back(ADMIN(ac));
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+void ADMINS::PrintAdmins() const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+const_admin_iter ai(data.begin());
+while (ai != data.end())
+ {
+ ai->PrintAdmin();
+ ai++;
+ }
+}
+//-----------------------------------------------------------------------------
+bool ADMINS::FindAdmin(const string & l, ADMIN * admin) const
+{
+assert(admin != NULL && "Pointer to admin is not null");
+
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+if (data.empty())
+ {
+ printfd(__FILE__, "no admin in system!\n");
+ *admin = noAdmin;
+ return false;
+ }
+
+ADMIN adm(0, l, "");
+const_admin_iter ai(find(data.begin(), data.end(), adm));
+
+if (ai != data.end())
+ {
+ *admin = *ai;
+ return false;
+ }
+
+return true;
+}
+//-----------------------------------------------------------------------------
+bool ADMINS::AdminExists(const string & login) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+if (data.empty())
+ {
+ printfd(__FILE__, "no admin in system!\n");
+ return true;
+ }
+
+ADMIN adm(0, login, "");
+const_admin_iter ai(find(data.begin(), data.end(), adm));
+
+if (ai != data.end())
+ return true;
+
+return false;
+}
+//-----------------------------------------------------------------------------
+bool ADMINS::AdminCorrect(const string & login, const std::string & password, ADMIN * admin) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+if (data.empty())
+ {
+ printfd(__FILE__, "no admin in system!\n");
+ return true;
+ }
+
+ADMIN adm(0, login, "");
+const_admin_iter ai(find(data.begin(), data.end(), adm));
+
+if (ai == data.end())
+ {
+ return false;
+ }
+
+if (ai->GetPassword() != password)
+ {
+ return false;
+ }
+
+*admin = *ai;
+
+return true;
+}
+//-----------------------------------------------------------------------------
+int ADMINS::OpenSearch() const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+handle++;
+searchDescriptors[handle] = data.begin();
+return handle;
+}
+//-----------------------------------------------------------------------------
+int ADMINS::SearchNext(int h, ADMIN_CONF * ac) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+if (searchDescriptors.find(h) == searchDescriptors.end())
+ {
+ WriteServLog("ADMINS. Incorrect search handle.");
+ return -1;
+ }
+
+if (searchDescriptors[h] == data.end())
+ return -1;
+
+ADMIN a = *searchDescriptors[h]++;
+
+*ac = a.GetConf();
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int ADMINS::CloseSearch(int h) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+if (searchDescriptors.find(h) != searchDescriptors.end())
+ {
+ searchDescriptors.erase(searchDescriptors.find(h));
+ return 0;
+ }
+
+WriteServLog("ADMINS. Incorrect search handle.");
+return -1;
+}
+//-----------------------------------------------------------------------------
--- /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>
+ */
+
+ /*
+ $Revision: 1.10 $
+ $Date: 2010/10/04 20:17:12 $
+ $Author: faust $
+ */
+
+#ifndef ADMINS_H
+#define ADMINS_H
+
+#include <pthread.h>
+#include <list>
+#include <map>
+
+#include "admin.h"
+#include "stg_locker.h"
+#include "base_store.h"
+#include "noncopyable.h"
+
+using namespace std;
+
+//-----------------------------------------------------------------------------
+class ADMINS : private NONCOPYABLE
+{
+public:
+ ADMINS(BASE_STORE * st);
+ ~ADMINS() {};
+
+ int Add(const string & login, const ADMIN & admin);
+ int Del(const string & login, const ADMIN & admin);
+ int Change(const ADMIN_CONF & ac, const ADMIN & admin);
+ void PrintAdmins() const;
+ const ADMIN GetSysAdmin() const { return stg; };
+ const ADMIN GetNoAdmin() const { return noAdmin; };
+ bool FindAdmin(const string & l, ADMIN * admin) const;
+ bool AdminExists(const std::string & login) const;
+ bool AdminCorrect(const std::string & login,
+ const std::string & password,
+ ADMIN * admin) const;
+ const string & GetStrError() { return strError; };
+
+ int OpenSearch() const;
+ int SearchNext(int, ADMIN_CONF * ac) const;
+ int CloseSearch(int) const;
+
+private:
+ typedef list<ADMIN>::iterator admin_iter;
+ typedef list<ADMIN>::const_iterator const_admin_iter;
+
+ int ReadAdmins();
+
+ ADMIN stg;
+ ADMIN noAdmin;
+ list<ADMIN> data;
+ BASE_STORE * store;
+ STG_LOGGER & WriteServLog;
+ mutable map<int, const_admin_iter> searchDescriptors;
+ mutable unsigned int handle;
+ mutable pthread_mutex_t mutex;
+ string strError;
+};
+//-----------------------------------------------------------------------------
+#endif
+
+
--- /dev/null
+ #!/bin/sh
+
+# $Revision: 1.57 $
+# $Author: faust $
+# $Date: 2010/05/09 12:39:01 $
+######################################################
+
+# Installation path prefix
+
+PREFIX=""
+
+# Binaries access bits
+
+BIN_MODE=0755
+
+# Data files access bits
+
+DATA_MODE=0644
+
+# Binaries and data files owner
+
+OWNER=root
+
+# Name of the firebird's group
+# Need for chown directory with firebird db
+
+FIREBIRD_GROUP=firebird
+
+# Database address
+# Firebird must have priviledges to read/write for specified path
+
+DB_ADDRESS="localhost:/var/stargazer/stargazer.fdb"
+
+# Database user
+# This user must have priviledges to create database
+
+DB_USER="stg"
+
+# Database password
+
+DB_PASSWORD="123456"
+
+# Full path to isql utility
+# Note: Debian users have to specify path to isql-fb utility
+
+FIREBIRD_ISQL="/opt/firebird/bin/isql"
+
+OS=unknown
+sys=`uname -s`
+release=`uname -r | cut -b1`
+BUILD_DIR=`pwd`
+CONFFILE="../../Makefile.conf"
+VAR_DIR="./inst/var/stargazer"
+MIN_XMLRPCC_VERSION="1.06.27"
+XMLRPC_FEATURES="c++2 abyss-server"
+
+
+if [ -z $1 ]
+then
+ DEFS="$DEFS -DNDEBUG"
+ MAKEOPTS="-j1"
+else
+ if [ "$1" = "debug" ]
+ then
+ DEFS="$DEFS -DDEBUG"
+ MAKEOPTS="-j1"
+ CXXFLAGS="$CXXFLAGS -g3 -W -Wall"
+ else
+ DEFS="$DEFS -DNDEBUG"
+ MAKEOPTS="-j1"
+ fi
+fi
+
+CXXFLAGS="$CXXFLAGS -I/usr/local/include"
+LDFLAGS="$LDFLAGS -L/usr/local/lib"
+
+if [ "$sys" = "Linux" ]
+then
+ OS=linux
+ release=""
+ ETC_DIR="./inst/linux/etc/stargazer"
+ MAKE="make"
+fi
+
+if [ "$sys" = "FreeBSD" ]
+then
+ case $release in
+ 4) OS=bsd;;
+ 5) OS=bsd5;;
+ 6) OS=bsd5;;
+ 7) OS=bsd7;;
+ 8) OS=bsd7;;
+ *) OS=unknown;;
+ esac
+ ETC_DIR="./inst/freebsd/etc/stargazer"
+ MAKE="gmake"
+fi
+
+if [ "$OS" = "unknown" ]
+then
+ echo "#############################################################################"
+ echo "# Sorry, but stargazer currently supported by Linux, FreeBSD 4.x, 5.x, 6.x #"
+ echo "#############################################################################"
+ exit 1
+fi
+
+echo "#############################################################################"
+echo " Building STG 2.4 for $sys $release"
+echo "#############################################################################"
+
+STG_LIBS="stg_logger.lib
+ stg_locker.lib
+ crypto.lib
+ common.lib
+ script_executer.lib
+ conffiles.lib
+ hostallow.lib
+ pinger.lib
+ dotconfpp.lib"
+
+PLUGINS="authorization/ao
+ authorization/inetaccess
+ configuration/sgconfig
+ other/ping
+ other/rscript
+ other/radius
+ store/files
+ capture/cap_nf"
+
+if [ "$OS" = "linux" ]
+then
+ DEFS="$DEFS -DLINUX"
+ PLUGINS="$PLUGINS
+ capture/ether_linux
+ capture/ipq_linux"
+ SHELL="/bin/bash"
+ LIB_THREAD=-lpthread
+else
+ if [ "$OS" = "bsd" ]
+ then
+ DEFS="$DEFS -DFREE_BSD"
+ LIB_THREAD=-lc_r
+ else
+ DEFS="$DEFS -DFREE_BSD5"
+ if [ "$OS" = "bsd7" ]
+ then
+ LIB_THREAD=-lpthread
+ else
+ LIB_THREAD=-lc_r
+ fi
+ fi
+ PLUGINS="$PLUGINS
+ capture/ether_freebsd
+ capture/divert_freebsd"
+ SHELL="/usr/local/bin/bash"
+fi
+
+echo -n "Checking endianess... "
+echo "int main() { int probe = 0x00000001; return *(char *)&probe; }" > build_check.c
+gcc $CXXFLAGS $LDFLAGS build_check.c -o fake > /dev/null 2> /dev/null
+if [ $? != 0 ]
+then
+ echo "FAIL!"
+ echo "Endianess checking failed"
+ exit;
+else
+ ./fake
+ if [ $? = 1 ]
+ then
+ ARCH=le
+ CXXFLAGS="$CXXFLAGS -DARCH_LE"
+ echo "Little Endian"
+ else
+ ARCH=be
+ CXXFLAGS="$CXXFLAGS -DARCH_BE"
+ echo "Big Endian"
+ fi
+fi
+rm -f fake
+
+echo -n "Checking for -lexpat... "
+echo "int main() { return 0; }" > build_check.c
+gcc $CXXFLAGS $LDFLAGS build_check.c -lexpat -o fake > /dev/null 2> /dev/null
+if [ $? != 0 ]
+then
+ CHECK_EXPAT=no
+ echo "no"
+else
+ CHECK_EXPAT=yes
+ echo "yes"
+fi
+rm -f fake
+
+echo -n "Checking for -lfbclient... "
+gcc $CXXFLAGS $LDFLAGS build_check.c -lfbclient $LIB_THREAD -o fake > /dev/null 2> /dev/null
+if [ $? != 0 ]
+then
+ CHECK_FBCLIENT=no
+ echo "no"
+else
+ CHECK_FBCLIENT=yes
+ echo "yes"
+fi
+rm -f fake
+
+echo -n "Checking for mysql_config... "
+MYSQL_VERSION=`mysql_config --version 2> /dev/null`
+if [ $? != 0 ]
+then
+ echo "no";
+ echo -n "Checking for -lmysqlclient... "
+ gcc $CXXFLAGS $LDFLAGS build_check.c -lmysqlclient_r $LIB_THREAD -o fake > /dev/null 2> /dev/null
+ if [ $? != 0 ]
+ then
+ CHECK_MYSQLCLIENT=no
+ echo "no"
+ else
+ CHECK_MYSQLCLIENT=yes
+ echo "yes"
+ fi
+ rm -f fake
+else
+ echo "yes"
+ echo -n "Checking for mysql_config --cflags... "
+ MYSQL_CFLAGS=`mysql_config --cflags 2> /dev/null`
+ if [ $? != 0 ]
+ then
+ CHECK_MYSQLCLIENT=no
+ echo "no"
+ else
+ #CXXFLAGS="$CXXFLAGS $MYSQL_CFLAGS"
+ echo "[$MYSQL_CFLAGS]"
+ echo -n "Checking for mysql_config --libs_r... "
+ MYSQL_LDFLAGS=`mysql_config --libs_r 2> /dev/null`
+ if [ $? != 0 ]
+ then
+ CHECK_MYSQLCLIENT=no
+ echo "no"
+ else
+ CHECK_MYSQLCLIENT=yes
+ #LDFLAGS="$LDFLAGS $MYSQL_LDFLAGS"
+ echo "[$MYSQL_LDFLAGS]"
+ fi
+ fi
+fi
+
+echo -n "Checking for pg_config... "
+PG_VERSION=`pg_config --version 2> /dev/null`
+if [ $? != 0 ]
+then
+ echo "no";
+ echo -n "Checking for -lpq... "
+ gcc $CXXFLAGS $LDFLAGS build_check.c -lpq $LIB_THREAD -o fake > /dev/null 2> /dev/null
+ if [ $? != 0 ]
+ then
+ CHECK_PQ=no
+ echo "no"
+ else
+ CHECK_PQ=yes
+ echo "yes"
+ fi
+ rm -f fake
+else
+ echo "yes";
+ echo -n "Checking for pg_config --includedir... "
+ PG_CFLAGS=`pg_config --includedir 2> /dev/null`
+ if [ $? != 0 ]
+ then
+ CHECK_PQ=no
+ echo "no"
+ else
+ echo "[$PG_CFLAGS]"
+ echo -n "Checking for pg_config --libdir... "
+ PG_LDFLAGS=`pg_config --libdir 2> /dev/null`
+ if [ $? != 0 ]
+ then
+ CHECK_PQ=no
+ echo "no"
+ else
+ CHECK_PQ=yes
+ echo "[$PG_LDFLAGS]"
+ fi
+ fi
+fi
+
+echo -n "Checking for xmlrpc-c-config... "
+XMLRPCC_VERSION=`xmlrpc-c-config $XMLRPC_FEATURES --version 2> /dev/null`
+if [ $? != 0 ]
+then
+ echo "no";
+ echo -n "Checking for -lxmlrpc... "
+ gcc $CXXFLAGS $LDFLAGS build_check.c -lxmlrpc $LIB_THREAD -o fake > /dev/null 2> /dev/null
+ if [ $? != 0 ]
+ then
+ CHECK_XMLRPC=no
+ echo "no"
+ else
+ CHECK_XMLRPC=yes
+ echo "yes"
+ fi
+ rm -f fake
+elif [ "$XMLRPCC_VERSION" \< "$MIN_XMLRPCC_VERSION" ]
+then
+ echo "no (need at least $MIN_XMLRPCC_VERSION, actual $XMLRPCC_VERSION)";
+ CHECK_XMLRPC=no
+else
+ echo "yes (version $XMLRPCC_VERSION)";
+ echo -n "Checking for xmlrpc-c-config --cflags... "
+ XMLRPC_CFLAGS=`xmlrpc-c-config $XMLRPC_FEATURES --cflags 2> /dev/null`
+ if [ $? != 0 ]
+ then
+ CHECK_XMLRPC=no
+ echo "no"
+ else
+ echo "[$XMLRPC_CFLAGS]"
+ echo -n "Checking for xmlrpc-c-config --libs... "
+ XMLRPC_LDFLAGS=`xmlrpc-c-config $XMLRPC_FEATURES --libs 2> /dev/null`
+ if [ $? != 0 ]
+ then
+ CHECK_XMLRPC=no
+ echo "no"
+ else
+ CHECK_XMLRPC=yes
+ echo "[$XMLRPC_LDFLAGS]"
+ fi
+ fi
+fi
+
+rm -f build_check.c
+
+if [ "$CHECK_EXPAT" != "yes" ]
+then
+ echo "-lexpat not found!"
+ exit 1
+fi
+
+if [ "$CHECK_FBCLIENT" = "yes" ]
+then
+ STG_LIBS="$STG_LIBS
+ ibpp.lib"
+ PLUGINS="$PLUGINS
+ store/firebird"
+fi
+
+if [ "$CHECK_PQ" = "yes" ]
+then
+ PLUGINS="$PLUGINS
+ store/postgresql"
+fi
+
+if [ "$CHECK_MYSQLCLIENT" = "yes" ]
+then
+ PLUGINS="$PLUGINS
+ store/mysql"
+fi
+
+if [ "$CHECK_XMLRPC" = "yes" ]
+then
+ PLUGINS="$PLUGINS
+ configuration/rpcconfig"
+fi
+
+echo "OS=$OS" > $CONFFILE
+echo "STG_TIME=yes" >> $CONFFILE
+echo "DIR_BUILD=$BUILD_DIR" >> $CONFFILE
+echo "DIR_LIB=\$(DIR_BUILD)/../../lib" >> $CONFFILE
+echo "DIR_LIBSRC=\$(DIR_BUILD)/../../stglibs" >> $CONFFILE
+echo "DIR_INCLUDE=\$(DIR_BUILD)/../../include" >> $CONFFILE
+echo "DIR_MOD=\$(DIR_BUILD)/modules" >> $CONFFILE
+echo "DIR_PLUGINS=\$(DIR_BUILD)/plugins" >> $CONFFILE
+echo "ARCH=$ARCH" >> $CONFFILE
+echo "CHECK_EXPAT=$CHECK_EXPAT" >> $CONFFILE
+echo "CHECK_FBCLIENT=$CHECK_FBCLIENT" >> $CONFFILE
+echo "CHECK_MYSQLCLIENT=$CHECK_MYSQLCLIENT" >> $CONFFILE
+echo "CHECK_PQ=$CHECK_PQ" >> $CONFFILE
+echo "CHECK_XMLRPC=$CHECK_XMLRPC" >> $CONFFILE
+echo "DEFS=$DEFS" >> $CONFFILE
+echo -n "STG_LIBS=" >> $CONFFILE
+for lib in $STG_LIBS
+do
+ echo -n "$lib " >> $CONFFILE
+done
+echo "" >> $CONFFILE
+echo -n "PLUGINS=" >> $CONFFILE
+for plugin in $PLUGINS
+do
+ echo -n "$plugin " >> $CONFFILE
+done
+echo "" >> $CONFFILE
+echo "SHELL=$SHELL" >> $CONFFILE
+echo "CXXFLAGS=$CXXFLAGS" >> $CONFFILE
+echo "LDFLAGS=$LDFLAGS" >> $CONFFILE
+echo "LIB_THREAD=$LIB_THREAD" >> $CONFFILE
+echo "PREFIX=$PREFIX" >> $CONFFILE
+echo "BIN_MODE=$BIN_MODE" >> $CONFFILE
+echo "DATA_MODE=$DATA_MODE" >> $CONFFILE
+echo "OWNER=$OWNER" >> $CONFFILE
+echo "VAR_DIR=$VAR_DIR" >> $CONFFILE
+echo "ETC_DIR=$ETC_DIR" >> $CONFFILE
+echo "DB_ADDRESS=$DB_ADDRESS" >> $CONFFILE
+echo "DB_USER=$DB_USER" >> $CONFFILE
+echo "DB_PASSWORD=$DB_PASSWORD" >> $CONFFILE
+echo "FIREBIRD_ISQL=$FIREBIRD_ISQL" >> $CONFFILE
+echo "FIREBIRD_GROUP=$FIREBIRD_GROUP" >> $CONFFILE
+
+mkdir -p modules
+
+if [ "$1" != "debug" ]
+then
+ $MAKE $MAKEOPTS
+else
+ echo -e "\n\n\nDebug build. Type $MAKE explicitly"
+fi
--- /dev/null
+#!/bin/bash
+
+export CFLAGS=-DTRAFF_STAT_WITH_PORTS
+./build debug
+
--- /dev/null
+#include <cerrno>
+#include <cstring>
+
+#include "eventloop.h"
+#include "stg_locker.h"
+#include "common.h"
+
+EVENT_LOOP::EVENT_LOOP()
+ : ACTIONS_LIST()
+{
+pthread_mutex_init(&_mutex, NULL);
+pthread_cond_init(&_condition, NULL);
+}
+
+EVENT_LOOP::~EVENT_LOOP()
+{
+pthread_cond_destroy(&_condition);
+pthread_mutex_destroy(&_mutex);
+}
+
+bool EVENT_LOOP::Start()
+{
+_running = true;
+if (pthread_create(&_tid, NULL, Run, this))
+ {
+ printfd(__FILE__, "EVENT_LOOP::Start - Failed to create thread: '%s'\n", strerror(errno));
+ return true;
+ }
+return false;
+}
+
+bool EVENT_LOOP::Stop()
+{
+_running = false;
+// Wake up thread
+pthread_cond_signal(&_condition);
+// Wait until thread exit
+pthread_join(_tid, NULL);
+return false;
+}
+
+void * EVENT_LOOP::Run(void * self)
+{
+EVENT_LOOP * ev = static_cast<EVENT_LOOP *>(self);
+ev->Runner();
+return NULL;
+}
+
+void EVENT_LOOP::Runner()
+{
+_stopped = false;
+printfd(__FILE__, "EVENT_LOOP::Runner - Before start\n");
+while (_running)
+ {
+ {
+ STG_LOCKER lock(&_mutex, __FILE__, __LINE__);
+ // Check for any actions...
+ if (empty())
+ {
+ // ... and sleep until new actions added
+ printfd(__FILE__, "EVENT_LOOP::Runner - Sleeping until new actions arrived\n");
+ pthread_cond_wait(&_condition, &_mutex);
+ }
+ // Check for running after wake up
+ if (!_running)
+ {
+ // Don't process any actions if stopping
+ break;
+ }
+ }
+ // Create new empty actions list
+ ACTIONS_LIST local;
+ // Fast swap with current
+ swap(local);
+ // Invoke all current actions
+ printfd(__FILE__, "EVENT_LOOP::Runner - Invoke %d actions\n", local.size());
+ local.InvokeAll();
+ }
+printfd(__FILE__, "EVENT_LOOP::Runner - Before stop\n");
+_stopped = true;
+}
+
+namespace {
+
+pthread_mutex_t singletonMutex;
+
+}
+
+EVENT_LOOP & EVENT_LOOP_SINGLETON::GetInstance()
+{
+// Double-checking technique
+if (!_instance)
+ {
+ STG_LOCKER lock(&singletonMutex, __FILE__, __LINE__);
+ if (!_instance)
+ {
+ CreateInstance();
+ }
+ }
+return *_instance;
+}
+
+void EVENT_LOOP_SINGLETON::CreateInstance()
+{
+static EVENT_LOOP loop;
+_instance = &loop;
+}
+
+EVENT_LOOP * EVENT_LOOP_SINGLETON::_instance = NULL;
--- /dev/null
+#ifndef __EVENT_LOOP_H__
+#define __EVENT_LOOP_H__
+
+#include <pthread.h>
+
+#include "noncopyable.h"
+#include "actions.h"
+
+class EVENT_LOOP : private NONCOPYABLE,
+ private ACTIONS_LIST
+{
+ public:
+ bool Start();
+ bool Stop();
+ bool IsRunning() const { return _running; };
+
+ template <class ACTIVE_CLASS, typename DATA_TYPE>
+ void Enqueue(ACTIVE_CLASS & ac,
+ typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE a,
+ DATA_TYPE d);
+
+ private:
+ bool _running;
+ bool _stopped;
+ pthread_t _tid;
+ pthread_mutex_t _mutex;
+ pthread_cond_t _condition;
+
+ EVENT_LOOP();
+ virtual ~EVENT_LOOP();
+
+ static void * Run(void *);
+ void Runner();
+
+ friend class EVENT_LOOP_SINGLETON;
+};
+
+class EVENT_LOOP_SINGLETON : private NONCOPYABLE
+{
+ public:
+ static EVENT_LOOP & GetInstance();
+
+ private:
+ static EVENT_LOOP * _instance;
+ static void CreateInstance();
+
+ EVENT_LOOP_SINGLETON() {};
+ ~EVENT_LOOP_SINGLETON() {};
+};
+
+template <class ACTIVE_CLASS, typename DATA_TYPE>
+void EVENT_LOOP::Enqueue(ACTIVE_CLASS & ac,
+ typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE a,
+ DATA_TYPE d)
+{
+STG_LOCKER lock(&_mutex, __FILE__, __LINE__);
+// Add new action
+ACTIONS_LIST::Enqueue(ac, a, d);
+// Signal about new action
+pthread_cond_signal(&_condition);
+}
+
+#endif
--- /dev/null
+login=$1
+param=$2
+oldValue=$3
+newValue=$4
+
+#echo "User: '$login'. Parameter $param changed from '$oldValue' to '$newValue'" >> /var/stargazer/users.chg.log
\ No newline at end of file
--- /dev/null
+#üÔÏÔ ÓËÒÉÐÔ ×ÙÚÙ×ÁÅÔÓÑ × ÍÏÍÅÎÔ, ËÏÇÄÁ ÐÏÌØÚÏ×ÁÔÅÌØ
+#ÕÓÐÅÛÎÏ ÐÒÏÛÅÌ Á×ÔÏÒÉÚÁÃÉÀ ÎÁ ÓÅÒ×ÅÒÅ. úÁÄÁÞÁ ÓËÒÉÐÔÁ - ÐÅÒÅÓÔÒÏÉÔØ
+#ÆÁÊÒ×ÏÌ ÔÁË, ÞÔÏ ÂÙ ÐÏÌØÚÏ×ÁÔÅÌØ ÐÏÌÕÞÉÌ ÄÏÓÔÕÐ × ÉÎÔÅÒÎÅÔ
+
+# Login
+LOGIN=$1
+
+#user IP
+IP=$2
+
+#cash
+CASH=$3
+
+#user ID
+ID=$4
+
+#Selected dirs to connect
+DIRS=$5
+
+
+#echo "C `date +%Y.%m.%d-%H.%M.%S` $IP $CASH" >> /var/stargazer/users/$LOGIN/connect.log
+
--- /dev/null
+# üÔÏÔ ÓËÒÉÐÔ ×ÙÚÙ×ÁÅÔÓÑ × ÍÏÍÅÎÔ, ËÏÇÄÁ ÐÏÌØÚÏ×ÁÔÅÌØ
+# ÖÅÌÁÅÔ ÏÔËÌÀÞÉÔÓÑ ÏÔ ÉÎÔÅÒÎÅÔÁ ÉÌÉ ×ÙÛÅÌ ÔÁÊÍÁÕÔ Õ ÐÏÌØÚÏ×ÁÔÅÌÑ
+# É ÓÅÒ×ÅÒ ÓÁÍ ÏÔËÌÀÞÁÅÔ ÐÏÌØÚÏ×ÁÔÅÌÑ
+# úÁÄÁÞÁ ÓËÒÉÐÔÁ ÐÏÄÏÂÎÁ ÚÁÄÁÞÅ ÓËÒÉÐÔÁ OnConnect - ÐÅÒÅÓÔÒÏÉÔØ
+# ÆÁÊÒ×ÏÌ ÔÁË, ÞÔÏ ÂÙ ÐÏÌØÚÏ×ÁÔÅÌÀ ÚÁËÒÙÔØ ÄÏÓÔÕÐ × ÉÎÔÅÒÎÅÔ
+
+# Login
+LOGIN=$1
+
+#user IP
+IP=$2
+
+#cash
+CASH=$3
+
+#user ID
+ID=$4
+
+#Selected dirs to disconnect
+DIRS=$4
+
+#echo "D `date +%Y.%m.%d-%H.%M.%S` $IP $CASH" >> /var/stargazer/users/$LOGIN/connect.log
+
+
+
+
+
--- /dev/null
+# éÓÐÏÌØÚÏ×ÁÎÉÅ (ÎÅÉÓÐÏÌØÚÏ×ÁÎÉÅ) ÜÔÏÇÏ ÓËÒÉÐÔÁ ÄÅÌÏ ×ËÕÓÁ.
+# ïÎ ÎÅ ×ÙÐÏÌÎÑÅÔ ËÒÉÔÉÞÅÓËÉÈ ÆÕÎËÃÉÊ. åÇÏ ÚÁÄÁÞÁ Á×ÔÍÁÔÉÚÉÒÏ×ÁÔØ
+# ÄÅÊÓÔ×ÉÑ ÈÁÒÁËÔÅÒÎÙÅ ÐÒÉ ÄÏÂÁ×ÌÅÎÉÉ ÐÏÌØÚÏ×ÁÔÅÌÑ ÓÅÔÉ, ÎÁÐÒÉÍÅÒ ÄÏÂÁ×ÌÅËÎÉÅ
+# ÐÏÌØÚÏ×ÁÔÅÌÀ ÐÏÞÔÙ
+
+# Login
+login=$1
+
+#echo "added user $login" >> /var/stargazer/add_del.log
+
+
+
--- /dev/null
+# Login
+login=$1
+
+#echo "deleted user $login" >> /var/stargazer/add_del.log
+
--- /dev/null
+ALL 192.168.0.0/16 DIR1
+ALL 10.0.0.0/8 DIR2
+ALL 0.0.0.0/0 DIR0
\ No newline at end of file
--- /dev/null
+################################################################################
+# æÁÊÌ ÎÁÓÔÒÏÅË ÓÅÒ×ÅÒÁ stargazer #
+################################################################################
+
+
+
+# éÍÑ ÌÏÇ-ÆÁÊÌÁ ËÕÄÁ ÐÉÛÕÔÓÑ ÓÏÂÙÔÉÑ
+LogFile = /var/log/stargazer.log
+
+
+
+# éÍÑ PID-ÆÁÊÌÁ ËÕÄÁ ÐÉÛÅÔÓÑ ÉÄÅÎÔÉÆÉËÁÔÏÒ ÐÒÏÃÅÓÓÁ
+# ðÏ ÕÍÏÌÞÁÎÉÀ /var/run/pid
+# PIDFile = /var/run/stargazer.pid
+
+
+
+# éÍÑ ÆÁÊÌÁ × ËÏÔÏÒÏÍ ÏÐÒÅÄÅÌÑÀÔÓÑ ÐÒÁ×ÉÌÁ ÐÏÄÓÞÅÔÁ ÔÒÁÆÉËÁ
+Rules = /etc/stargazer/rules
+
+
+
+# ÷ÒÅÍÑ ÞÅÒÅÚ ËÏÔÏÒÏÅ ÐÉÛÅÔÓÑ d âä ÄÅÔÁÌØÎÁÑ ÓÔÁÔÉÓÔÉËÁ ÐÏÌØÚÏ×ÁÔÅÌÑ
+# úÎÁÞÅÎÉÑ: 1, 1/2, 1/4, 1/6.
+# 1 - ÒÁÚ × ÞÁc, 1/2 - ÒÁÚ × ÐÏÌ ÞÁÓÁ, 1/4 - ÒÁÚ × 15 ÍÉÎ, 1/6 - ÒÁÚ × 10 ÍÉÎ
+DetailStatWritePeriod=1/6
+
+
+
+# ðÅÒÉÏÄÉÞÎÏÓÔØ ÚÁÐÉÓÉ ÚÁÐÉÓÉ × âä ÉÎÆÏÒÍÁÃÉÉ Ï ÓÔÁÔÉÓÔÉËÅ ÐÏÌØÚÏ×ÁÔÅÌÑ (ÍÉÎÕÔÙ)
+# ðÒÉ ÂÏÌØÛÏÍ ËÏÌ-×Å ÐÏÌØÚÏ×ÁÔÅÌÅÊ ÜÔÕ ×ÅÌÉÞÉÎÕ ÓÔÏÉÔ Õ×ÅÌÉÞÉÔØ, Ô.Ë.
+# ÚÁÐÉÓØ × âä ÍÏÖÅÔ ÚÁÎÉÍÁÔØ ÄÌÉÔÅÌØÎÏÅ ×ÒÅÍÑ.
+# úÎÁÞÅÎÉÑ: 1...1440 (ÍÉÎÕÔÙ)
+StatWritePeriod = 10
+
+
+
+# äÅÎØ ÓÎÑÔÉÑ ÁÂÏÎÐÌÁÔÙ
+# úÎÁÞÅÎÉÑ: 0...31. 0 - ðÏÓÌÅÄÎÉÊ ÄÅÎØ ÍÅÓÑÃÁ
+DayFee = 1
+
+
+
+# áÂÏÎÐÌÁÔÁ ÓÎÉÍÁÅÔÓÑ × ÐÏÓÌÅÄÎÉÊ (yes) ÉÌÉ ÐÅÒ×ÙÊ (no) ÄÅÎØ ÕÞÅÔÎÏÇÏ ÐÅÒÉÏÄÁ.
+# üÔÏ ×ÌÉÑÅÔ ÎÁ ÔÏ, ËÁË ÂÕÄÅÔ ÓÎÑÔÁ ÁÂÏÎÐÌÁÔÁ (áð) ÐÒÉ ÐÅÒÅÈÏÄÅ ÎÁ ÎÏ×ÙÊ ÔÁÒÉÆ.
+# åÓÌÉ Õ ÐÏÌØÚÏ×ÁÔÅÌÑ ÂÙÌ ÔÁÒÉÆ A Ó áð=100 É ÏÎ ÈÏÞÅÔ ÐÅÒÅÊÔÉ ÎÁ ÔÁÒÉÆ B Ó áð=200,
+# ÔÏ ÐÒÉ ÐÅÒÅÈÏÄÅ ÎÁ ÎÏ×ÙÊ ÔÁÒÉÆ ÓÏ ÓÞÅÔÁ ÐÏÌØÚÏ×ÁÔÅÌÑ ÓÎÉÍÅÔÓÑ 100, ÅÓÌÉ
+# DayFeeIsLastDay = yes É 200, ÅÓÌÉ DayFeeIsLastDay = no
+DayFeeIsLastDay = yes
+
+
+
+# äÅÎØ ÓÂÒÏÓÁ ÄÁÎÎÙÈ Ï ÔÒÁÆÉËÅ ÚÁ ÍÅÓÑÃ É ÄÅÎØ ÐÅÒÅÈÏÄÁ ÐÏÌØÚÏ×ÁÔÅÌÅÊ ÎÁ ÎÏ×ÙÅ ÔÁÒÉÆÙ
+# úÎÁÞÅÎÉÑ: 0...31. 0 - ðÏÓÌÅÄÎÉÊ ÄÅÎØ ÍÅÓÑÃÁ
+DayResetTraff = 1
+
+
+
+# "òÁÚÍÁÚÁÎÎÏÅ" ÓÎÑÔÉÅ ÁÂÏÎÐÌÁÔÙ. óÎÑÔÉÅ áð ÎÅ ÒÁÚ × ÍÅÓÑÃ, Á ËÁÖÄÙÊ
+# ÄÅÎØ 1/30 ÉÌÉ 1/31 ÞÁÓÔÉ áð
+# úÎÁÞÅÎÉÑ: yes, no
+SpreadFee = no
+
+
+
+# äÁÎÎÁÑ ÏÐÃÉÑ ÏÐÒÅÄÅÌÑÅÔ ÍÏÖÅÔ ÌÉ ÐÏÌØÚÏ×ÁÔÅÌØ ÐÏÌÕÞÉÔØ ÄÏÓÔÕÐ × ÉÎÔÅÒÅÎÔ
+# ÅÓÌÉ Õ ÎÅÇÏ ÎÁ ÓÞÅÔÕ ÎÅÔ ÄÅÎÅÇ, ÎÏ ÏÓÔÁÌÓÑ ÐÒÅÄÏÐÌÁÞÅÎÎÙÊ ÔÒÁÆÉË
+# úÎÁÞÅÎÉÑ: yes, no
+FreeMbAllowInet = no
+
+
+
+# üÔÁ ÏÐÃÉÑ ÏÐÒÅÄÅÌÑÅÔ ÞÔÏ ÂÕÄÅÔ ÐÉÓÁÔØÓÑ × ÓÔÏÉÍÏÓÔØ ÔÒÁÆÉËÁ × detail_stat.
+# åÓÌÉ Õ ÐÏÌØÚÏ×ÁÔÅÌÑ ÅÝÅ ÅÓÔØ ÐÒÅÄÏÐÌÁÞÅÎÎÙÊ ÔÒÁÆÉË É WriteFreeMbTraffCost = no,
+# ÔÏ × detail_stat ÓÔÏÉÍÏÓÔØ ÂÕÄÅÔ 0. åÓÌÉ Õ ÐÏÌØÚÏ×ÁÔÅÌÑ ÕÖÅ ÎÅÔ
+# ÐÒÅÄÏÐÌÁÞÅÎÎÏÇÏ ÔÒÁÆÉËÁ É WriteFreeMbTraffCost = no, ÔÏ × detail_stat
+# ÂÕÄÅÔ ÚÁÐÉÓÁÎÁ ÓÔÏÉÏÓÔØ ÔÒÁÆÉËÁ. ðÒÉ WriteFreeMbTraffCost = yes ÓÔÏÉÍÏÓÔØ
+# ÔÒÁÆÉËÁ ÂÕÄÅÔ ÚÁÐÉÓÁÎÁ × ÌÀÂÏÍ ÓÌÕÞÁÅ.
+WriteFreeMbTraffCost = no
+
+
+
+# îÅÏÂÑÚÁÔÅÌØÎÙÊ ÐÁÒÁÍÅÔÒ. õËÁÚÙ×ÁÅÔ ÓÎÉÍÁÔØ ÐÏÌÎÕÀ ÁÂÏÎÐÌÁÔÕ Õ ÐÏÌØÚÏ×ÁÔÅÌÑ ÄÁÖÅ
+# ÅÓÌÉ ÏÎ ÂÙÚ ÚÁÍÏÒÏÖÅÎ ÔÏÌØËÏ ÞÁÓÔØ ÕÞÅÔÎÏÇÏ ÐÅÒÉÏÄÁ.
+# ðÏ ÕÍÏÌÞÁÎÉÀ ÕÓÔÁÎÏ×ÌÅÎ × no
+# FullFee=no
+
+# îÅÏÂÑÚÁÔÅÌØÎÙÊ ÐÁÒÁÍÅÔÒ ÕËÁÚÙ×ÁÀÝÉÊ ÐÏËÁÚÙ×ÁÔØ ÎÁ ÓÞÅÔÕ É ÐÏÚ×ÏÌÑÔØ
+# ÉÓÐÏÌØÚÏ×ÁÔØ ÐÏÌØÚÏ×ÁÔÅÌÀ ÁÂÏÎÐÌÁÔÕ. ðÏ ÕÍÏÌÞÁÎÉÀ ÕÓÔÁÎÏ×ÌÅÎ × yes
+# ShowFeeInCash=yes
+
+
+
+# îÁÚ×ÁÎÉÑ ÎÁÐÒÁ×ÌÅÎÉÊ. îÁÐÒÁ×ÌÅÎÉÑ ÂÅÚ ÎÁÚ×ÁÎÉÊ ÎÅ ÂÕÄÕÔ ÏÔÏÂÒÁÖÁÔØÓÑ ×
+# Á×ÔÏÒÉÚÁÔÏÒÅ É ËÏÎÆÉÇÕÒÁÔÏÒÅ. îÁÚ×ÁÎÉÑ ÓÏÓÔÏÑÝÉÅ ÉÚ ÎÅÓËÏÌØËÉÈ ÓÌÏ× ÄÏÌÖÎÙ
+# ÂÙÔØ ×ÚÑÔÙ × ËÁ×ÙÞËÉ
+<DirNames>
+ DirName0 = ìÏËÁÌØ
+ DirName1 = çÏÒÏÄ
+ DirName2 = íÉÒ
+ DirName3 =
+ DirName4 =
+ DirName5 = "ìÏËÁÌØÎÙÅ ÉÇÒÙ"
+ DirName6 =
+ DirName7 =
+ DirName8 =
+ DirName9 =
+</DirNames>
+
+
+
+# ëÏÌ-×Ï ÚÁÐÕÓËÁÅÍÙÈ ÐÒÏÃÅÓÓÏ× stg-exec.
+# üÔÉ ÐÒÏÃÅÓÓÙ ÏÔ×ÅÞÁÀÔ ÚÁ ×ÙÐÏÌÎÅÎÉÅ ÓËÒÉÐÔÏ× OnConnect, OnDisconnect, ...
+# ëÏÌ-×Ï ÐÒÏÃÅÓÓÏ× ÏÚÎÁÞÁÅÔ ÓËÏÌØËÏ ÓËÒÉÐÔÏ× ÍÏÇÕÔ ×ÙÐÏÌÎÑÔÓÑ ÏÄÎÏ×ÒÅÍÅÎÎÏ.
+# úÎÁÞÅÎÉÑ: 1...1024
+ExecutersNum = 1
+
+
+
+# Message Key ÄÌÑ stg-exec.
+# éÄÅÎÔÉÆÉËÁÔÏÒ ÏÞÅÒÅÄÉ ÓÏÏÂÝÅÎÉÊ ÄÌÑ ×ÙÐÏÌÎÑÔÅÌÑ ÓËÒÉÐÔÏ×.
+# åÇÏ ÉÚÍÅÎÅÎÉÅ ÍÏÖÅÔ ÐÏÎÁÄÏÂÉÔÓÑ ÅÓÌÉ ÅÓÔØ ÎÅÏÂÈÏÄÉÍÏÓÔØ ÚÁÐÕÓÔÉÔØ ÎÅÓËÏÌØËÏ
+# ÜËÚÅÍÐÌÑÒÏ× stg. åÓÌÉ ×Ù ÎÅ ÐÏÎÉÍÁÅÔÅ, ÞÔÏ ÜÔÏ, ÎÅ ÔÒÏÇÁÊÔÅ ÜÔÏÔ ÐÁÒÁÍÅÔÒ!
+# úÎÁÞÅÎÉÑ: 0...2^32
+# úÎÁÞÅÎÉÅ ÐÏ ÕÍÏÌÞÁÎÉÀ: 5555
+# ExecMsgKey = 5555
+
+
+
+# ðÕÔØ Ë ÄÉÒÅËÔÏÒÉÉ, × ËÏÔÏÒÏÊ ÎÁÈÏÄÑÔÓÑ ÍÏÄÕÌÉ ÓÅÒ×ÅÒÁ
+ModulesPath = /usr/lib/stg
+
+# ïÐÒÅÄÅÌÑÅÔ ÄÉÒÅËÔÏÒÉÀ, × ËÏÔÏÒÏÊ ÂÕÄÕÔ ÎÁÈÏÄÉÔÓÑ ÆÁÊÌÙ "ÍÏÎÉÔÏÒÁ"
+# ÒÁÂÏÔÙ ÓÅÒ×ÅÒÁ. ÷ ÜÔÏÊ ÄÉÒÅËÔÏÒÉÉ ÂÕÄÕÔ ÓÏÚÄÁÎÙ ÐÕÓÔÙÅ ÆÁÊÌÙ, ×ÒÅÍÑ
+# ÍÏÄÉÆÉËÁÃÉÉ ËÏÔÏÒÙÈ ÂÕÄÅÔ ÍÅÎÑÔØÓÑ ÐÒÉÍÅÒÎÏ ÒÁÚ × ÍÉÎÕÔÕ. åÓÌÉ ËÁËÏÊ-ÔÏ
+# ËÏÍÐÏÎÅÎÔ ÓÅÒ×ÅÒÁ ÚÁ×ÉÓÎÅÔ, ÆÁÊÌ(Ù) ÐÅÒÅÓÔÁÎÅÔ ÏÂÎÏ×ÌÑÔÓÑ, É ÐÏ ÜÔÏÍÕ
+# ÐÒÉÚÎÁËÕ ÍÏÖÎÏ ÏÐÒÅÄÅÌÉÔØ ÓÂÏÊ × ÒÁÂÏÔÅ ÓÅÒ×ÅÒÁ É ÐÒÉ ÎÁÄÏÂÎÏÓÔÉ
+# ÐÅÒÅÚÁÐÕÓÔÉÔØ. åÓÌÉ ÐÁÒÁÍÅÔÒ ÎÅ ÕËÁÚÁÎ ÉÌÉ ÐÕÓÔÏÊ, ÍÏÎÉÔÏÒÉÎÇ ÐÒÏÉÚ×ÏÄÉÔÓÑ
+# ÎÅ ÂÕÄÅÔ. ðÁÒÁÍÅÔÒ ÎÅ Ñ×ÌÑÅÔÓÑ ÏÂÑÚÁÔÅÌØÎÙÍ, ÐÏ ÕÍÏÌÞÁÎÉÀ ÐÕÓÔÏÊ.
+# MonitorDir=/var/stargazer/monitor
+
+################################################################################
+# Store module
+# îÁÓÔÒÏÊËÉ ÐÌÁÇÉÎÁ ÒÁÂÏÔÁÀÝÅÇÏ Ó âä ÓÅÒ×ÅÒÁ
+
+# ÷ÔÏÒÏÊ ÐÁÒÁÍÅÔÒ - ÜÔÏ ÉÍÑ ÍÏÄÕÌÑ ÂÅÚ mod_ × ÎÁÞÁÌÅ É .so × ËÏÎÃÅ
+# ô.Å. ÐÏÌÎÏÅ ÉÍÑ ÍÏÄÕÌÑ mod_store_files.so
+<StoreModule store_files>
+
+ # òÁÂÏÞÁÑ ÄÉÒÅËÔÏÒÉÑ ÓÅÒ×ÅÒÁ, ÔÕÔ ÓÏÄÅÒÖÁÔÓÑ ÄÁÎÎÙÅ Ï ÔÁÒÉÆÁÈ, ÐÏÌØÚÏ×ÁÔÅÌÑÈ,
+ # ÁÄÍÉÎÉÓÔÒÁÔÏÒÁÈ É Ô.Ä.
+ WorkDir = /var/stargazer
+
+
+ # ÷ÌÁÄÅÌÅÃ, ÇÒÕÐÐÁ É ÐÒÁ×Á ÄÏÓÔÕÐÁ ÎÁ ÆÁÊÌÙ ÓÔÁÔÉÓÔÉËÉ (stat) ÐÏÌØÚÏ×ÁÔÅÌÑ
+ ConfOwner = root
+ ConfGroup = wheel
+ ConfMode = 600
+
+
+ # ÷ÌÁÄÅÌÅÃ, ÇÒÕÐÐÁ É ÐÒÁ×Á ÄÏÓÔÕÐÁ ÎÁ ÆÁÊÌÙ ËÏÎÆÉÇÕÒÁÃÉÉ (conf) ÐÏÌØÚÏ×ÁÔÅÌÑ
+ StatOwner = root
+ StatGroup = wheel
+ StatMode = 640
+
+ # ÷ÌÁÄÅÌÅÃ, ÇÒÕÐÐÁ É ÐÒÁ×Á ÄÏÓÔÕÐÁ ÎÁ ÌÏÇ-ÆÁÊÌÙ (log) ÐÏÌØÚÏ×ÁÔÅÌÑ
+ UserLogOwner = root
+ UserLogGroup = wheel
+ UserLogMode = 640
+
+ # õÄÁÌÑÔØ ÒÅÚÅÒ×ÎÙÅ ËÏÐÉÉ ÐÏÓÌÅ ÕÓÐÅÛÎÏÊ ÚÁÐÉÓÉ conf/stat
+ # úÎÁÞÅÎÉÑ: yes, no
+ # ðÏ ÕÍÏÌÞÁÎÉÀ: yes
+ # RemoveBak = yes
+
+ # ÷ÏÓÓÔÁÎÁ×ÌÉ×ÁÔØ ÆÁÊÌÙ conf/stat ÉÚ ÒÅÚÅÒ×ÎÙÈ ËÏÐÉÊ ÐÒÉ ÏÛÉÂËÅ ÞÔÅÎÉÑ
+ # úÎÁÞÅÎÉÑ: yes, no
+ # ðÏ ÕÍÏÌÞÁÎÉÀ: no
+ # ReadBak = no
+
+</StoreModule>
+
+#<StoreModule store_firebird>
+# # áÄÒÅÓ ÓÅÒ×ÅÒÁ âä
+# server=localhost
+#
+# # ðÕÔØ Ë âä ÎÁ ÓÅÒ×ÅÒÅ ÉÌÉ ÅÅ ÁÌÉÁÓ
+# database=/var/stg/stargazer.fdb
+#
+# # éÍÑ ÐÏÌØÚÏ×ÁÔÅÌÑ âä
+# user=stg
+#
+# # ðÁÒÏÌØ ÐÏÌØÚÏ×ÁÔÅÌÑ âä
+# password=123456
+#
+# # õÒÏ×ÅÎØ ÉÚÏÌÑÃÉÉ ÔÒÁÎÚÁÃÉÊ (ÎÅ ÏÂÑÚÁÔÅÌØÎÏ, ÐÏ ÕÍÏÌÞÁÎÉÀ oncurrency):
+# # concurrency
+# # dirtyRead
+# # readCommitted
+# # consistency
+# isolationLevel=concurrency
+#
+# # äÅÊÓÔ×ÉÑ ÐÒÉ ÂÌÏËÉÒÏ×ËÁÈ (ÎÅ ÏÂÑÚÁÔÅÌØÎÏ, ÐÏ ÕÍÏÌÞÁÎÉÀ wait):
+# # wait
+# # noWait
+# lockResolution=wait
+#</StoreModule>
+
+#<StoreModule store_postgresql>
+# # áÄÒÅÓ ÓÅÒ×ÅÒÁ âä
+# server=localhost
+#
+# # éÍÑ âä
+# database=stargazer
+#
+# # éÍÑ ÐÏÌØÚÏ×ÁÔÅÌÑ âä
+# user=stg
+#
+# # ðÁÒÏÌØ ÐÏÌØÚÏ×ÁÔÅÌÑ âä
+# password=123456
+#</StoreModule>
+
+#<StoreModule store_mysql>
+# # éÍÑ ÐÏÌØÚÏ×ÁÔÅÌÑ âä
+# dbuser = stg
+#
+# # ðÁÒÏÌØ ÐÏÌØÚÏ×ÁÔÅÌÑ âä
+# rootdbpass = 123456
+#
+# # éÍÑ âä ÎÁ ÓÅÒ×ÅÒÅ
+# dbname = stg
+#
+# # áÄÒÅÓ ÓÅÒ×ÅÒÁ âä
+# dbhost = localhost
+#</StoreModule>
+
+################################################################################
+# ðÒÏÞÉÅ ÍÏÄÕÌÉ
+
+<Modules>
+
+ # îÁÓÔÒÏÊËÉ ÐÌÁÇÉÎÁ Á×ÔÏÒÉÚÁÃÉÉ Always Online "mod_auth_ao.so"
+ # ÷ÔÏÒÏÊ ÐÁÒÁÍÅÔÒ - ÜÔÏ ÉÍÑ ÍÏÄÕÌÑ ÂÅÚ mod_ × ÎÁÞÁÌÅ É .so × ËÏÎÃÅ
+ # ô.Å. ÐÏÌÎÏÅ ÉÍÑ ÍÏÄÕÌÑ mod_auth_ao.so
+ <Module auth_ao>
+ </Module>
+
+
+
+ # îÁÓÔÒÏÊËÉ ÐÌÁÇÉÎÁ Á×ÔÏÒÉÚÁÃÉÉ InetAccess "mod_auth_ia.so"
+ # ÷ÔÏÒÏÊ ÐÁÒÁÍÅÔÒ - ÜÔÏ ÉÍÑ ÍÏÄÕÌÑ ÂÅÚ mod_ × ÎÁÞÁÌÅ É .so × ËÏÎÃÅ
+ # ô.Å. ÐÏÌÎÏÅ ÉÍÑ ÍÏÄÕÌÑ mod_auth_ia.so
+ <Module auth_ia>
+
+ # ðÏÒÔ ÎÁ ËÏÔÏÒÏÍ ÐÒÉÎÉÍÁÀÔÓÑ ÏÂÒÁÝÅÎÉÑ ÏÔ Á×ÔÏÒÉÚÁÔÏÒÁ
+ # úÎÁÞÅÎÉÑ: 1...65534
+ Port = 5555
+
+
+ # ÷ÒÅÍÑ ÍÅÖÄÕ ÐÏÓÙÌËÁÍÉ ÚÁÐÒÏÓÁ ÐÏÌØÚÏ×ÁÔÅÌÀ ÖÉ× ÌÉ ÏÎ
+ # É ÏÂÎÏ×ÌÅÎÉÅÍ ÄÁÎÎÙÈ ÓÔÁÔÉÓÔÉËÉ (ÓÅËÕÎÄÙ)
+ # úÎÁÞÅÎÉÑ: 5...600
+ UserDelay = 15
+
+
+ #ôÁÊÍÁÕÔ ÄÌÑ ÐÏÌØÚÏ×ÁÔÅÌÑ. åÓÌÉ × ÔÅÞÅÎÉÅ ÜÔÏÇÏ ×ÒÅÍÅÎÉ Á×ÔÏÒÉÚÁÔÏÒ
+ #ÎÅ ÏÔ×ÅÞÁÅÔ, ÐÏÌØÚÏ×ÁÔÅÌØ ÂÕÄÅÔ ÏÔËÌÀÞÅÎ
+ # úÎÁÞÅÎÉÑ: 15...1200
+ UserTimeout = 65
+
+
+ # üÔÏÔ ÐÁÒÁÍÅÔÒ ÏÐÒÅÄÅÌÑÅÔ ÞÔÏ ÂÕÄÅÔ ÐÅÒÅÄÁ×ÁÔØÓÑ ÐÒÏÇÒÁÍÍÅ InetAccess ÏÔ ÓÅÒ×ÅÒÁ
+ # ËÁË ÏÔÓÔÁÔÏË ÐÒÅÄÏÐÌÁÞÅÎÎÏÇÏ ÔÒÁÆÉËÁ
+ # úÎÁÞÅÎÉÑ:
+ # FreeMb = 0 - ËÏÌ-×Ï ÂÅÓÐÌÁÔÎÙÈ ÍÅÇÁÂÁÊÔ × ÐÒÅÓÞÅÔÅ ÎÁ ÃÅÎÕ ÎÕÌÅ×ÏÇÏ ÎÁÐÒÁ×ÌÅÎÉÑ
+ # FreeMb = 1 - ËÏÌ-×Ï ÂÅÓÐÌÁÔÎÙÈ ÍÅÇÁÂÁÊÔ × ÐÒÅÓÞÅÔÅ ÎÁ ÃÅÎÕ ÐÅÒ×ÏÇÏ ÎÁÐÒÁ×ÌÅÎÉÑ
+ # FreeMb = 2 - ËÏÌ-×Ï ÂÅÓÐÌÁÔÎÙÈ ÍÅÇÁÂÁÊÔ × ÐÒÅÓÞÅÔÅ ÎÁ ÃÅÎÕ ×ÔÏÒÏÇÏ ÎÁÐÒÁ×ÌÅÎÉÑ
+ # FreeMb = 3 - ËÏÌ-×Ï ÂÅÓÐÌÁÔÎÙÈ ÍÅÇÁÂÁÊÔ × ÐÒÅÓÞÅÔÅ ÎÁ ÃÅÎÕ ÔÒÅÔØÅÇÏ ÎÁÐÒÁ×ÌÅÎÉÑ
+ # ........................
+ # FreeMb = 9 - ËÏÌ-×Ï ÂÅÓÐÌÁÔÎÙÈ ÍÅÇÁÂÁÊÔ × ÐÒÅÓÞÅÔÅ ÎÁ ÃÅÎÕ ÄÅ×ÑÔÏÇÏ ÎÁÐÒÁ×ÌÅÎÉÑ
+ # FreeMb = cash - ËÏÌ-×Ï ÄÅÎÅÇ ÎÁ ËÏÔÏÒÙÅ ÀÚÅÒ ÍÏÖÅÔ ÂÅÓÐÌÁÔÎÏ ËÁÞÁÔØ
+ # FreeMb = none - ÎÉÞÅÇÏ ÎÅ ÐÅÒÅÄÁ×ÁÔØ
+ FreeMb = cash
+
+ </Module>
+
+
+
+ # íÏÄÕÌÉ ÍÏÖÎÏ ÉÓÐÏÌØÚÏ×ÁÔØ ÎÅÓËÏÌØËÏ ÒÁÚ Ó ÒÁÚÎÙÍÉ ÐÁÒÁÍÅÔÒÁÍÉ
+ #<Module auth_ia>
+ # Port = 7777
+ # UserDelay = 15
+ # UserTimeout = 65
+ # FreeMb = 0
+ #</Module>
+
+
+
+ # îÁÓÔÒÏÊËÉ ÍÏÄÕÌÑ ËÏÎÆÉÇÕÒÁÃÉÉ SgConfig "mod_conf_sg.so"
+ # ÷ÔÏÒÏÊ ÐÁÒÁÍÅÔÒ - ÜÔÏ ÉÍÑ ÍÏÄÕÌÑ ÂÅÚ mod_ × ÎÁÞÁÌÅ É .so × ËÏÎÃÅ
+ <Module conf_sg>
+
+ # ðÏÒÔ ÐÏ ËÏÔÏÒÏÍÕ ÓÅÒ×ÅÒ ×ÚÁÉÍÏÄÅÊÓÔ×ÕÅÔ Ó ËÏÎÆÉÇÕÒÁÔÏÒÏÍ
+ # úÎÁÞÅÎÉÑ: 1...65535
+ Port = 5555
+
+ </Module>
+
+
+
+ # íÏÄÕÌØ ÚÁÈ×ÁÔÁ ÔÒÁÆÉËÁ "mod_cap_bpf.so"
+ # ÷ÔÏÒÏÊ ÐÁÒÁÍÅÔÒ - ÜÔÏ ÉÍÑ ÍÏÄÕÌÑ ÂÅÚ mod_ × ÎÁÞÁÌÅ É .so × ËÏÎÃÅ
+ # âÅÚ ÐÁÒÁÍÅÔÒÏ×. ôÏÌØËÏ ÉÍÑ ÍÏÄÕÌÑ.
+ <Module cap_bpf>
+ # éÎÔÅÒÆÅÊÓ(Ù) ÎÁ ËÏÔÏÒÏÍ ÎÕÖÎÏ ÐÒÏÉÚ×ÏÄÉÔØ ÐÏÄÓÞÅÔ ÔÒÁÆÉËÁ
+ iface = rl0
+ iface = rl1
+ iface = dc0
+ </Module>
+
+ # íÏÄÕÌØ ÚÁÈ×ÁÔÁ ÔÒÁÆÉËÁ "mod_cap_nf.so"
+ # ðÒÉÎÉÍÁÅÔ ÉÎÆÏÒÍÁÃÉÀ Ï ÔÒÁÆÉËÅ ÐÏ ÐÒÏÔÏËÏÌÕ NetFlow
+ # ÷ÔÏÒÏÊ ÐÁÒÁÍÅÔÅÒ - ÜÔÏ ÉÍÑ ÍÏÄÕÌÑ ÂÅÚ mod_ × ÎÁÞÁÌÅ É .so × ËÏÎÃÅ
+ <Module cap_nf>
+ # TCPPort - ÐÏÒÔ ÄÌÑ TCP-ÓÏÅÄÉÎÅÎÉÊ
+ TCPPort = 42111
+
+ # UDPPort - ÐÏÒÔ ÄÌÑ UDP-ÓÏÅÄÉÎÅÎÉÊ
+ UDPPort = 42111
+
+ # íÏÇÕÔ ÉÍÅÔØ ÓÏ×ÐÁÄÁÀÝÉÅ ÚÎÁÞÅÎÉÑ.
+ # åÓÌÉ ÐÁÒÁÍÅÔÒ ÎÅ ÕËÁÚÁÎ - ÓÏÏÔ×ÅÔÓÔ×ÕÀÝÉÊ ÐÏÒÔ ÎÅ "ÐÒÏÓÌÕÛÉ×ÁÅÔÓÑ".
+ </Module>
+
+
+
+ # îÁÓÔÒÏÊËÉ ÍÏÄÕÌÑ ÐÉÎÇÕÀÝÅÇÏ ÐÏÌØÚÏ×ÁÔÅÌÅÊ "mod_ping.so"
+ # ÷ÔÏÒÏÊ ÐÁÒÁÍÅÔÒ - ÜÔÏ ÉÍÑ ÍÏÄÕÌÑ ÂÅÚ mod_ × ÎÁÞÁÌÅ É .so × ËÏÎÃÅ
+ <Module ping>
+
+ # ÷ÒÅÍÑ, × ÓÅËÕÎÄÁÈ, ÍÅÖÄÕ ÐÉÎÇÁÍÉ ÏÄÎÏÇÏ É ÔÏÇÏ ÖÅ ÐÏÌØÚÏ×ÁÔÅÌÑ
+ # úÎÁÞÅÎÉÑ: 10...3600
+ PingDelay = 15
+
+ </Module>
+
+# # îÁÓÔÒÏÊËÉ ÍÏÄÕÌÑ ÄÌÑ ÕÄÁÌÅÎÎÏÇÏ ×ÙÐÏÌÎÅÎÉÑ ÓËÒÉÐÔÏ× OnCOnnect É
+# # OnDisconnect "mod_remote_script.so"
+# # ÷ÔÏÒÏÊ ÐÁÒÁÍÅÔÒ - ÜÔÏ ÉÍÑ ÍÏÄÕÌÑ ÂÅÚ mod_ × ÎÁÞÁÌÅ É .so × ËÏÎÃÅ
+# <Module remote_script>
+#
+# # ÷ÒÅÍÑ, × ÓÅËÕÎÄÁÈ, ÍÅÖÄÕ ÐÏÓÙÌËÁÍÉ ÐÏÄÔ×ÅÒÖÄÅÎÉÊ, ÔÏÇÏ, ÞÔÏ ÐÏÌØÚÏ×ÁÔÅÌØ
+# # ×Ó£ ÅÝÅ ÏÎÌÁÊÎ
+# # úÎÁÞÅÎÉÑ: 10...600
+# SendPeriod = 15
+#
+# # óÏÏÔ×ÅÔÓÔ×ÉÅ ÐÏÄÓÅÔÅÊ, × ËÏÔÏÒÏÊ ÎÁÈÏÄÉÔÓÑ ÐÏÌØÚÏ×ÁÔÅÌØ É
+# # ÓÏÏÔ×ÅÔÓÔ×ÕÀÝÅÇÏ ÒÏÕÔÅÒÁ. ðÅÒ×ÁÑ ÞÁÓÔØ ÓÔÒÏËÉ - ÐÏÄÓÌÅÔØ, ÚÁÄÁÎÎÁÑ
+# # ËÁË IP-ÁÄÒÅÓ É ÍÁÓËÁ, ÞÅÒÅÚ ÐÒÏÂÅÌ - IP-ÁÄÒÅÓ ÒÏÕÔÅÒÁ ÎÁ ËÏÔÏÒÏÍ
+# # ÄÏÌÖÎÙ ×ÙÐÏÌÎÑÔØÓÑ ÓËÒÉÐÔÙ
+# # îÁÐÒÉÍÅÒ ÜÔÁ ÚÁÐÉÓØ "192.168.1.0/24 192.168.1.1" ÏÚÎÁÞÁÅÔ, ÞÔÏ ÄÌÑ
+# # ×ÓÅÈ ÐÏÌØÚÏ×ÁÔÅÌÅÊ ÉÚ ÐÏÄÓÅÔÉ 192.168.1.0/24, ÓËÒÉÐÔÙ ÂÕÄÕÔ
+# # ×ÙÐÏÌÎÑÔØÓÑ ÎÁ ÒÏÕÔÅÒÅ Ó ÁÄÒÅÓÏÍ 192.168.1.1
+# # Subnet0...Subnet100
+# Subnet0 = 192.168.1.0/24 192.168.1.7
+# Subnet1 = 192.168.2.0/24 192.168.2.5
+# Subnet2 = 192.168.3.0/24 192.168.2.5
+# Subnet3 = 192.168.4.0/24 192.168.2.5
+#
+# # ðÁÒÏÌØ ÄÌÑ ÛÉÆÒÏ×ÁÎÉÑ ÐÁËÅÔÏ× ÍÅÖÄÕ stg-ÓÅÒ×ÅÒÏÍ É ÓÅÒ×ÅÒÏÍ,
+# # ×ÙÐÏÌÎÑÀÝÉÍ ÓËÒÉÐÔÙ
+# Password = 123456
+#
+# # üÔÏÔ ÐÁÒÁÍÅÔÒ ÏÐÒÅÄÅÌÑÅÔ ËÁËÉÅ ÐÁÒÁÍÅÔÒÙ ÐÏÌØÚÏ×ÁÔÅÌÑ ÐÅÒÅÄÁÀÔÓÑ
+# # ÎÁ ÕÄÁÌÅÎÎÙÊ ÓÅÒ×ÅÒ
+# # Cash, FreeMb, Passive, Disabled, AlwaysOnline, TariffName, NextTariff, Address,
+# # Note, Group, Email, RealName, Credit, EnabledDirs, Userdata0...Userdata9
+# UserParams=Cash Tariff EnabledDirs
+#
+# # ðÏÒÔ ÐÏ ËÏÔÏÒÏÍÕ ÓÅÒ×ÅÒ ÏÔÓÙÌÁÅÔ ÓÏÏÂÝÅÎÉÑ ÎÁ ÒÏÕÔÅÒ
+# # úÎÁÞÅÎÉÑ: 1...65535
+# Port = 9999
+#
+# </Module>
+
+# <Module radius>
+# Password = 123456
+# ServerIP = 127.0.0.1
+# Port = 6666
+# AuthServices = Login-User
+# AcctServices = Framed-User
+# </Module>
+
+</Modules>
+################################################################################
+
--- /dev/null
+#!/sbin/runscript
+
+opts="reload"
+
+DAEMON=/usr/sbin/stargazer
+STARGAZER_OPTS=""
+PIDFILE=/var/run/stargazer.pid
+
+depend() {
+ need net
+}
+
+start() {
+ ebegin "Starting stargazer"
+ start-stop-daemon --start --quiet --exec ${DAEMON} -- ${STARGAZER_OPTS}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping stargazer"
+ start-stop-daemon --stop --quiet --pidfile ${PIDFILE} --retry=INT/60/KILL/5
+ rm -f ${PIDFILE}
+ eend $?
+}
+
+reload() {
+ ebegin "Reloading stargazer rules"
+ start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE
+ return 0
+ eend $?
+}
--- /dev/null
+#!/bin/bash
+#
+# processname: stargazer
+# config: /etc/stargazer/stargazer.conf
+# pidfile: /var/run/stargazer.pid
+
+# Source function library.
+. /etc/init.d/functions
+
+# Source networking configuration.
+. /etc/sysconfig/network
+
+# Source stargazer configureation.
+DAEMON=yes
+QUEUE=1h
+
+# Check that networking is up.
+[ ${NETWORKING} = "no" ] && exit 0
+
+[ -f /sbin/stargazer ] || exit 0
+
+RETVAL=0
+prog="stargazer"
+
+start() {
+ # Start daemons.
+
+ echo -n $"Starting $prog: "
+ /etc/stargazer/first 2> /dev/null
+ daemon /sbin/stargazer
+ RETVAL=$?
+ /etc/stargazer/last 2> /dev/null
+ echo
+ [ $RETVAL -eq 0 ] && touch /var/lock/subsys/stargazer
+ return $RETVAL
+}
+
+stop() {
+ # Stop daemons.
+ echo -n $"Shutting down $prog: "
+ killproc stargazer
+ RETVAL=$?
+ echo
+ [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/stargazer
+ return $RETVAL
+}
+
+# See how we were called.
+case "$1" in
+ start)
+ start
+ ;;
+ stop)
+ stop
+ ;;
+ restart|reload)
+ stop
+ start
+ RETVAL=$?
+ ;;
+ status)
+ status stargazer
+ RETVAL=$?
+ ;;
+ *)
+ echo $"Usage: $0 {start|stop|restart|status}"
+ exit 1
+esac
+
+exit $RETVAL
--- /dev/null
+#! /bin/sh
+### BEGIN INIT INFO
+# Provides: stargazer
+# Required-Start: $local_fs $remote_fs
+# Required-Stop: $local_fs $remote_fs
+# Default-Start: 2 3 4 5
+# Default-Stop: S 0 1 6
+# Short-Description: Stargazer initscript
+# Description: This file should be used to start and stop stargazer daemon
+### END INIT INFO
+
+# Author: Boris Mikhailenko <stg34@stg.dp.ua>
+
+# Do NOT "set -e"
+
+# PATH should only include /usr/* if it runs after the mountnfs.sh script
+PATH=/usr/sbin:/usr/bin:/sbin:/bin
+DESC="Billing system"
+NAME=stargazer
+DAEMON=/usr/sbin/$NAME
+DAEMON_ARGS=""
+PIDFILE=/var/run/$NAME.pid
+SCRIPTNAME=/etc/init.d/$NAME
+
+# Exit if the package is not installed
+[ -x "$DAEMON" ] || exit 0
+
+# Read configuration variable file if it is present
+[ -r /etc/default/$NAME ] && . /etc/default/$NAME
+
+# Load the VERBOSE setting and other rcS variables
+[ -f /etc/default/rcS ] && . /etc/default/rcS
+
+# Define LSB log_* functions.
+# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
+. /lib/lsb/init-functions
+
+#
+# Function that starts the daemon/service
+#
+do_start()
+{
+ # Return
+ # 0 if daemon has been started
+ # 1 if daemon was already running
+ # 2 if daemon could not be started
+ start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
+ || return 1
+
+ # ps x | grep $DAEMON | grep -v grep | cut -f1 -d" " > $PIDFILE
+
+ start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
+ $DAEMON_ARGS \
+ || return 2
+
+ # ps x | grep $DAEMON | grep -v grep | cut -f1 -d" " > $PIDFILE
+ # Add code here, if necessary, that waits for the process to be ready
+ # to handle requests from services started subsequently which depend
+ # on this one. As a last resort, sleep for some time.
+}
+
+#
+# Function that stops the daemon/service
+#
+do_stop()
+{
+ # Return
+ # 0 if daemon has been stopped
+ # 1 if daemon was already stopped
+ # 2 if daemon could not be stopped
+ # other if a failure occurred
+ start-stop-daemon --stop --quiet --retry=INT/60/KILL/5 --pidfile $PIDFILE --name $NAME
+ RETVAL="$?"
+ [ "$RETVAL" = 2 ] && return 2
+ # Wait for children to finish too if this is a daemon that forks
+ # and if the daemon is only ever run from this initscript.
+ # If the above conditions are not satisfied then add some other code
+ # that waits for the process to drop all resources that could be
+ # needed by services started subsequently. A last resort is to
+ # sleep for some time.
+ start-stop-daemon --stop --quiet --oknodo --retry=0/60/KILL/5 --exec $DAEMON
+ [ "$?" = 2 ] && return 2
+ # Many daemons don't delete their pidfiles when they exit.
+ rm -f $PIDFILE
+ return "$RETVAL"
+}
+
+#
+# Function that sends a SIGHUP to the daemon/service
+#
+do_reload() {
+ # If the daemon can reload its configuration without
+ # restarting (for example, when it is sent a SIGHUP),
+ # then implement that here.
+ start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
+ return 0
+}
+
+case "$1" in
+ start)
+ [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
+ do_start
+ case "$?" in
+ 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+ 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+ esac
+ ;;
+ stop)
+ [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
+ do_stop
+ case "$?" in
+ 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+ 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+ esac
+ ;;
+ reload)
+ # If do_reload() is not implemented then leave this commented out
+ # and leave 'force-reload' as an alias for 'restart'.
+ log_daemon_msg "Reloading $DESC" "$NAME"
+ do_reload
+ log_end_msg $?
+ ;;
+ restart)
+ #
+ # If the "reload" option is implemented then remove the
+ # 'force-reload' alias
+ #
+ log_daemon_msg "Restarting $DESC" "$NAME"
+ do_stop
+ case "$?" in
+ 0|1)
+ do_start
+ case "$?" in
+ 0) log_end_msg 0 ;;
+ 1) log_end_msg 1 ;; # Old process is still running
+ *) log_end_msg 1 ;; # Failed to start
+ esac
+ ;;
+ *)
+ # Failed to stop
+ log_end_msg 1
+ ;;
+ esac
+ ;;
+ *)
+ #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
+ echo "Usage: $SCRIPTNAME {start|stop|restart|reload}" >&2
+ exit 3
+ ;;
+esac
+
+:
--- /dev/null
+login=$1
+param=$2
+oldValue=$3
+newValue=$4
+
+#echo "User: '$login'. Parameter $param changed from '$oldValue' to '$newValue'" >> /var/stargazer/users.chg.log
\ No newline at end of file
--- /dev/null
+#Этот скрипт вызывается в момент, когда пользователь
+#успешно прошел авторизацию на сервере. Задача скрипта - перестроить
+#файрвол так, что бы пользователь получил доступ в интернет
+
+# Login
+LOGIN=$1
+
+#user IP
+IP=$2
+
+#cash
+CASH=$3
+
+#user ID
+ID=$4
+
+#Selected dirs to connect
+DIRS=$5
+
+
+#echo "C `date +%Y.%m.%d-%H.%M.%S` $IP $CASH" >> /var/stargazer/users/$LOGIN/connect.log
+
--- /dev/null
+# Этот скрипт вызывается в момент, когда пользователь
+# желает отключится от интернета или вышел таймаут у пользователя
+# и сервер сам отключает пользователя
+# Задача скрипта подобна задаче скрипта OnConnect - перестроить
+# файрвол так, что бы пользователю закрыть доступ в интернет
+
+# Login
+LOGIN=$1
+
+#user IP
+IP=$2
+
+#cash
+CASH=$3
+
+#user ID
+ID=$4
+
+#Selected dirs to disconnect
+DIRS=$4
+
+#echo "D `date +%Y.%m.%d-%H.%M.%S` $IP $CASH" >> /var/stargazer/users/$LOGIN/connect.log
+
+
+
+
+
--- /dev/null
+# Использование (неиспользование) этого скрипта дело вкуса.
+# Он не выполняет критических функций. Его задача автматизировать
+# действия характерные при добавлении пользователя сети, например добавлекние
+# пользователю почты
+
+# Login
+login=$1
+
+#echo "added user $login" >> /var/stargazer/add_del.log
+
+
+
--- /dev/null
+# Login
+login=$1
+
+#echo "deleted user $login" >> /var/stargazer/add_del.log
+
--- /dev/null
+ALL 192.168.0.0/16 DIR1
+ALL 10.0.0.0/8 DIR2
+ALL 0.0.0.0/0 DIR0
\ No newline at end of file
--- /dev/null
+################################################################################
+# æÁÊÌ ÎÁÓÔÒÏÅË ÓÅÒ×ÅÒÁ stargazer #
+################################################################################
+
+
+
+# éÍÑ ÌÏÇ-ÆÁÊÌÁ ËÕÄÁ ÐÉÛÕÔÓÑ ÓÏÂÙÔÉÑ
+LogFile = /var/log/stargazer.log
+
+
+
+# éÍÑ PID-ÆÁÊÌÁ ËÕÄÁ ÐÉÛÅÔÓÑ ÉÄÅÎÔÉÆÉËÁÔÏÒ ÐÒÏÃÅÓÓÁ
+# ðÏ ÕÍÏÌÞÁÎÉÀ /var/run/pid
+# PIDFile = /var/run/stargazer.pid
+
+
+
+# éÍÑ ÆÁÊÌÁ × ËÏÔÏÒÏÍ ÏÐÒÅÄÅÌÑÀÔÓÑ ÐÒÁ×ÉÌÁ ÐÏÄÓÞÅÔÁ ÔÒÁÆÉËÁ
+Rules = /etc/stargazer/rules
+
+
+
+# ÷ÒÅÍÑ ÞÅÒÅÚ ËÏÔÏÒÏÅ ÐÉÛÅÔÓÑ d âä ÄÅÔÁÌØÎÁÑ ÓÔÁÔÉÓÔÉËÁ ÐÏÌØÚÏ×ÁÔÅÌÑ
+# úÎÁÞÅÎÉÑ: 1, 1/2, 1/4, 1/6.
+# 1 - ÒÁÚ × ÞÁc, 1/2 - ÒÁÚ × ÐÏÌ ÞÁÓÁ, 1/4 - ÒÁÚ × 15 ÍÉÎ, 1/6 - ÒÁÚ × 10 ÍÉÎ
+DetailStatWritePeriod=1/6
+
+
+
+# ðÅÒÉÏÄÉÞÎÏÓÔØ ÚÁÐÉÓÉ ÚÁÐÉÓÉ × âä ÉÎÆÏÒÍÁÃÉÉ Ï ÓÔÁÔÉÓÔÉËÅ ÐÏÌØÚÏ×ÁÔÅÌÑ (ÍÉÎÕÔÙ)
+# ðÒÉ ÂÏÌØÛÏÍ ËÏÌ-×Å ÐÏÌØÚÏ×ÁÔÅÌÅÊ ÜÔÕ ×ÅÌÉÞÉÎÕ ÓÔÏÉÔ Õ×ÅÌÉÞÉÔØ, Ô.Ë.
+# ÚÁÐÉÓØ × âä ÍÏÖÅÔ ÚÁÎÉÍÁÔØ ÄÌÉÔÅÌØÎÏÅ ×ÒÅÍÑ.
+# úÎÁÞÅÎÉÑ: 1...1440 (ÍÉÎÕÔÙ)
+StatWritePeriod = 10
+
+
+
+# äÅÎØ ÓÎÑÔÉÑ ÁÂÏÎÐÌÁÔÙ
+# úÎÁÞÅÎÉÑ: 0...31. 0 - ðÏÓÌÅÄÎÉÊ ÄÅÎØ ÍÅÓÑÃÁ
+DayFee = 1
+
+
+
+# áÂÏÎÐÌÁÔÁ ÓÎÉÍÁÅÔÓÑ × ÐÏÓÌÅÄÎÉÊ (yes) ÉÌÉ ÐÅÒ×ÙÊ (no) ÄÅÎØ ÕÞÅÔÎÏÇÏ ÐÅÒÉÏÄÁ.
+# üÔÏ ×ÌÉÑÅÔ ÎÁ ÔÏ, ËÁË ÂÕÄÅÔ ÓÎÑÔÁ ÁÂÏÎÐÌÁÔÁ (áð) ÐÒÉ ÐÅÒÅÈÏÄÅ ÎÁ ÎÏ×ÙÊ ÔÁÒÉÆ.
+# åÓÌÉ Õ ÐÏÌØÚÏ×ÁÔÅÌÑ ÂÙÌ ÔÁÒÉÆ A Ó áð=100 É ÏÎ ÈÏÞÅÔ ÐÅÒÅÊÔÉ ÎÁ ÔÁÒÉÆ B Ó áð=200,
+# ÔÏ ÐÒÉ ÐÅÒÅÈÏÄÅ ÎÁ ÎÏ×ÙÊ ÔÁÒÉÆ ÓÏ ÓÞÅÔÁ ÐÏÌØÚÏ×ÁÔÅÌÑ ÓÎÉÍÅÔÓÑ 100, ÅÓÌÉ
+# DayFeeIsLastDay = yes É 200, ÅÓÌÉ DayFeeIsLastDay = no
+DayFeeIsLastDay = yes
+
+
+
+# äÅÎØ ÓÂÒÏÓÁ ÄÁÎÎÙÈ Ï ÔÒÁÆÉËÅ ÚÁ ÍÅÓÑÃ É ÄÅÎØ ÐÅÒÅÈÏÄÁ ÐÏÌØÚÏ×ÁÔÅÌÅÊ ÎÁ ÎÏ×ÙÅ ÔÁÒÉÆÙ
+# úÎÁÞÅÎÉÑ: 0...31. 0 - ðÏÓÌÅÄÎÉÊ ÄÅÎØ ÍÅÓÑÃÁ
+DayResetTraff = 1
+
+
+
+# "òÁÚÍÁÚÁÎÎÏÅ" ÓÎÑÔÉÅ ÁÂÏÎÐÌÁÔÙ. óÎÑÔÉÅ áð ÎÅ ÒÁÚ × ÍÅÓÑÃ, Á ËÁÖÄÙÊ
+# ÄÅÎØ 1/30 ÉÌÉ 1/31 ÞÁÓÔÉ áð
+# úÎÁÞÅÎÉÑ: yes, no
+SpreadFee = no
+
+
+
+# äÁÎÎÁÑ ÏÐÃÉÑ ÏÐÒÅÄÅÌÑÅÔ ÍÏÖÅÔ ÌÉ ÐÏÌØÚÏ×ÁÔÅÌØ ÐÏÌÕÞÉÔØ ÄÏÓÔÕÐ × ÉÎÔÅÒÅÎÔ
+# ÅÓÌÉ Õ ÎÅÇÏ ÎÁ ÓÞÅÔÕ ÎÅÔ ÄÅÎÅÇ, ÎÏ ÏÓÔÁÌÓÑ ÐÒÅÄÏÐÌÁÞÅÎÎÙÊ ÔÒÁÆÉË
+# úÎÁÞÅÎÉÑ: yes, no
+FreeMbAllowInet = no
+
+
+
+# üÔÁ ÏÐÃÉÑ ÏÐÒÅÄÅÌÑÅÔ ÞÔÏ ÂÕÄÅÔ ÐÉÓÁÔØÓÑ × ÓÔÏÉÍÏÓÔØ ÔÒÁÆÉËÁ × detail_stat.
+# åÓÌÉ Õ ÐÏÌØÚÏ×ÁÔÅÌÑ ÅÝÅ ÅÓÔØ ÐÒÅÄÏÐÌÁÞÅÎÎÙÊ ÔÒÁÆÉË É WriteFreeMbTraffCost = no,
+# ÔÏ × detail_stat ÓÔÏÉÍÏÓÔØ ÂÕÄÅÔ 0. åÓÌÉ Õ ÐÏÌØÚÏ×ÁÔÅÌÑ ÕÖÅ ÎÅÔ
+# ÐÒÅÄÏÐÌÁÞÅÎÎÏÇÏ ÔÒÁÆÉËÁ É WriteFreeMbTraffCost = no, ÔÏ × detail_stat
+# ÂÕÄÅÔ ÚÁÐÉÓÁÎÁ ÓÔÏÉÏÓÔØ ÔÒÁÆÉËÁ. ðÒÉ WriteFreeMbTraffCost = yes ÓÔÏÉÍÏÓÔØ
+# ÔÒÁÆÉËÁ ÂÕÄÅÔ ÚÁÐÉÓÁÎÁ × ÌÀÂÏÍ ÓÌÕÞÁÅ.
+WriteFreeMbTraffCost = no
+
+
+
+# îÅÏÂÑÚÁÔÅÌØÎÙÊ ÐÁÒÁÍÅÔÒ. õËÁÚÙ×ÁÅÔ ÓÎÉÍÁÔØ ÐÏÌÎÕÀ ÁÂÏÎÐÌÁÔÕ Õ ÐÏÌØÚÏ×ÁÔÅÌÑ ÄÁÖÅ
+# ÅÓÌÉ ÏÎ ÂÙÚ ÚÁÍÏÒÏÖÅÎ ÔÏÌØËÏ ÞÁÓÔØ ÕÞÅÔÎÏÇÏ ÐÅÒÉÏÄÁ.
+# ðÏ ÕÍÏÌÞÁÎÉÀ ÕÓÔÁÎÏ×ÌÅÎ × no
+# FullFee=no
+
+# îÅÏÂÑÚÁÔÅÌØÎÙÊ ÐÁÒÁÍÅÔÒ ÕËÁÚÙ×ÁÀÝÉÊ ÐÏËÁÚÙ×ÁÔØ ÎÁ ÓÞÅÔÕ É ÐÏÚ×ÏÌÑÔØ
+# ÉÓÐÏÌØÚÏ×ÁÔØ ÐÏÌØÚÏ×ÁÔÅÌÀ ÁÂÏÎÐÌÁÔÕ. ðÏ ÕÍÏÌÞÁÎÉÀ ÕÓÔÁÎÏ×ÌÅÎ × yes
+# ShowFeeInCash=yes
+
+
+
+# îÁÚ×ÁÎÉÑ ÎÁÐÒÁ×ÌÅÎÉÊ. îÁÐÒÁ×ÌÅÎÉÑ ÂÅÚ ÎÁÚ×ÁÎÉÊ ÎÅ ÂÕÄÕÔ ÏÔÏÂÒÁÖÁÔØÓÑ ×
+# Á×ÔÏÒÉÚÁÔÏÒÅ É ËÏÎÆÉÇÕÒÁÔÏÒÅ. îÁÚ×ÁÎÉÑ ÓÏÓÔÏÑÝÉÅ ÉÚ ÎÅÓËÏÌØËÉÈ ÓÌÏ× ÄÏÌÖÎÙ
+# ÂÙÔØ ×ÚÑÔÙ × ËÁ×ÙÞËÉ
+<DirNames>
+ DirName0 = ìÏËÁÌØ
+ DirName1 = çÏÒÏÄ
+ DirName2 = íÉÒ
+ DirName3 =
+ DirName4 =
+ DirName5 = "ìÏËÁÌØÎÙÅ ÉÇÒÙ"
+ DirName6 =
+ DirName7 =
+ DirName8 =
+ DirName9 =
+</DirNames>
+
+
+
+# ëÏÌ-×Ï ÚÁÐÕÓËÁÅÍÙÈ ÐÒÏÃÅÓÓÏ× stg-exec.
+# üÔÉ ÐÒÏÃÅÓÓÙ ÏÔ×ÅÞÁÀÔ ÚÁ ×ÙÐÏÌÎÅÎÉÅ ÓËÒÉÐÔÏ× OnConnect, OnDisconnect, ...
+# ëÏÌ-×Ï ÐÒÏÃÅÓÓÏ× ÏÚÎÁÞÁÅÔ ÓËÏÌØËÏ ÓËÒÉÐÔÏ× ÍÏÇÕÔ ×ÙÐÏÌÎÑÔÓÑ ÏÄÎÏ×ÒÅÍÅÎÎÏ.
+# úÎÁÞÅÎÉÑ: 1...1024
+ExecutersNum = 1
+
+
+
+# Message Key ÄÌÑ stg-exec.
+# éÄÅÎÔÉÆÉËÁÔÏÒ ÏÞÅÒÅÄÉ ÓÏÏÂÝÅÎÉÊ ÄÌÑ ×ÙÐÏÌÎÑÔÅÌÑ ÓËÒÉÐÔÏ×.
+# åÇÏ ÉÚÍÅÎÅÎÉÅ ÍÏÖÅÔ ÐÏÎÁÄÏÂÉÔÓÑ ÅÓÌÉ ÅÓÔØ ÎÅÏÂÈÏÄÉÍÏÓÔØ ÚÁÐÕÓÔÉÔØ ÎÅÓËÏÌØËÏ
+# ÜËÚÅÍÐÌÑÒÏ× stg. åÓÌÉ ×Ù ÎÅ ÐÏÎÉÍÁÅÔÅ, ÞÔÏ ÜÔÏ, ÎÅ ÔÒÏÇÁÊÔÅ ÜÔÏÔ ÐÁÒÁÍÅÔÒ!
+# úÎÁÞÅÎÉÑ: 0...2^32
+# úÎÁÞÅÎÉÅ ÐÏ ÕÍÏÌÞÁÎÉÀ: 5555
+# ExecMsgKey = 5555
+
+
+
+# ðÕÔØ Ë ÄÉÒÅËÔÏÒÉÉ, × ËÏÔÏÒÏÊ ÎÁÈÏÄÑÔÓÑ ÍÏÄÕÌÉ ÓÅÒ×ÅÒÁ
+ModulesPath = /usr/lib/stg
+
+# ïÐÒÅÄÅÌÑÅÔ ÄÉÒÅËÔÏÒÉÀ, × ËÏÔÏÒÏÊ ÂÕÄÕÔ ÎÁÈÏÄÉÔÓÑ ÆÁÊÌÙ "ÍÏÎÉÔÏÒÁ"
+# ÒÁÂÏÔÙ ÓÅÒ×ÅÒÁ. ÷ ÜÔÏÊ ÄÉÒÅËÔÏÒÉÉ ÂÕÄÕÔ ÓÏÚÄÁÎÙ ÐÕÓÔÙÅ ÆÁÊÌÙ, ×ÒÅÍÑ
+# ÍÏÄÉÆÉËÁÃÉÉ ËÏÔÏÒÙÈ ÂÕÄÅÔ ÍÅÎÑÔØÓÑ ÐÒÉÍÅÒÎÏ ÒÁÚ × ÍÉÎÕÔÕ. åÓÌÉ ËÁËÏÊ-ÔÏ
+# ËÏÍÐÏÎÅÎÔ ÓÅÒ×ÅÒÁ ÚÁ×ÉÓÎÅÔ, ÆÁÊÌ(Ù) ÐÅÒÅÓÔÁÎÅÔ ÏÂÎÏ×ÌÑÔÓÑ, É ÐÏ ÜÔÏÍÕ
+# ÐÒÉÚÎÁËÕ ÍÏÖÎÏ ÏÐÒÅÄÅÌÉÔØ ÓÂÏÊ × ÒÁÂÏÔÅ ÓÅÒ×ÅÒÁ É ÐÒÉ ÎÁÄÏÂÎÏÓÔÉ
+# ÐÅÒÅÚÁÐÕÓÔÉÔØ. åÓÌÉ ÐÁÒÁÍÅÔÒ ÎÅ ÕËÁÚÁÎ ÉÌÉ ÐÕÓÔÏÊ, ÍÏÎÉÔÏÒÉÎÇ ÐÒÏÉÚ×ÏÄÉÔÓÑ
+# ÎÅ ÂÕÄÅÔ. ðÁÒÁÍÅÔÒ ÎÅ Ñ×ÌÑÅÔÓÑ ÏÂÑÚÁÔÅÌØÎÙÍ, ÐÏ ÕÍÏÌÞÁÎÉÀ ÐÕÓÔÏÊ.
+# MonitorDir=/var/stargazer/monitor
+
+
+################################################################################
+# Store module
+# îÁÓÔÒÏÊËÉ ÐÌÁÇÉÎÁ ÒÁÂÏÔÁÀÝÅÇÏ Ó âä ÓÅÒ×ÅÒÁ
+
+# ÷ÔÏÒÏÊ ÐÁÒÁÍÅÔÒ - ÜÔÏ ÉÍÑ ÍÏÄÕÌÑ ÂÅÚ mod_ × ÎÁÞÁÌÅ É .so × ËÏÎÃÅ
+# ô.Å. ÐÏÌÎÏÅ ÉÍÑ ÍÏÄÕÌÑ mod_store_files.so
+<StoreModule store_files>
+
+ # òÁÂÏÞÁÑ ÄÉÒÅËÔÏÒÉÑ ÓÅÒ×ÅÒÁ, ÔÕÔ ÓÏÄÅÒÖÁÔÓÑ ÄÁÎÎÙÅ Ï ÔÁÒÉÆÁÈ, ÐÏÌØÚÏ×ÁÔÅÌÑÈ,
+ # ÁÄÍÉÎÉÓÔÒÁÔÏÒÁÈ É Ô.Ä.
+ WorkDir = /var/stargazer
+
+
+ # ÷ÌÁÄÅÌÅÃ, ÇÒÕÐÐÁ É ÐÒÁ×Á ÄÏÓÔÕÐÁ ÎÁ ÆÁÊÌÙ ÓÔÁÔÉÓÔÉËÉ (stat) ÐÏÌØÚÏ×ÁÔÅÌÑ
+ ConfOwner = root
+ ConfGroup = root
+ ConfMode = 600
+
+
+ # ÷ÌÁÄÅÌÅÃ, ÇÒÕÐÐÁ É ÐÒÁ×Á ÄÏÓÔÕÐÁ ÎÁ ÆÁÊÌÙ ËÏÎÆÉÇÕÒÁÃÉÉ (conf) ÐÏÌØÚÏ×ÁÔÅÌÑ
+ StatOwner = root
+ StatGroup = root
+ StatMode = 640
+
+ # ÷ÌÁÄÅÌÅÃ, ÇÒÕÐÐÁ É ÐÒÁ×Á ÄÏÓÔÕÐÁ ÎÁ ÌÏÇ-ÆÁÊÌÙ (log) ÐÏÌØÚÏ×ÁÔÅÌÑ
+ UserLogOwner = root
+ UserLogGroup = root
+ UserLogMode = 640
+
+ # õÄÁÌÑÔØ ÒÅÚÅÒ×ÎÙÅ ËÏÐÉÉ ÐÏÓÌÅ ÕÓÐÅÛÎÏÊ ÚÁÐÉÓÉ conf/stat
+ # úÎÁÞÅÎÉÑ: yes, no
+ # ðÏ ÕÍÏÌÞÁÎÉÀ: yes
+ # RemoveBak = yes
+
+ # ÷ÏÓÓÔÁÎÁ×ÌÉ×ÁÔØ ÆÁÊÌÙ conf/stat ÉÚ ÒÅÚÅÒ×ÎÙÈ ËÏÐÉÊ ÐÒÉ ÏÛÉÂËÅ ÞÔÅÎÉÑ
+ # úÎÁÞÅÎÉÑ: yes, no
+ # ðÏ ÕÍÏÌÞÁÎÉÀ: no
+ # ReadBak = no
+
+</StoreModule>
+
+#<StoreModule store_firebird>
+# # áÄÒÅÓ ÓÅÒ×ÅÒÁ âä
+# server=localhost
+#
+# # ðÕÔØ Ë âä ÎÁ ÓÅÒ×ÅÒÅ ÉÌÉ ÅÅ ÁÌÉÁÓ
+# database=/var/stg/stargazer.fdb
+#
+# # éÍÑ ÐÏÌØÚÏ×ÁÔÅÌÑ âä
+# user=stg
+#
+# # ðÁÒÏÌØ ÐÏÌØÚÏ×ÁÔÅÌÑ âä
+# password=123456
+#
+# # õÒÏ×ÅÎØ ÉÚÏÌÑÃÉÉ ÔÒÁÎÚÁÃÉÊ (ÎÅ ÏÂÑÚÁÔÅÌØÎÏ, ÐÏ ÕÍÏÌÞÁÎÉÀ oncurrency):
+# # concurrency
+# # dirtyRead
+# # readCommitted
+# # consistency
+# isolationLevel=concurrency
+#
+# # äÅÊÓÔ×ÉÑ ÐÒÉ ÂÌÏËÉÒÏ×ËÁÈ (ÎÅ ÏÂÑÚÁÔÅÌØÎÏ, ÐÏ ÕÍÏÌÞÁÎÉÀ wait):
+# # wait
+# # noWait
+# lockResolution=wait
+#</StoreModule>
+
+#<StoreModule store_postgresql>
+# # áÄÒÅÓ ÓÅÒ×ÅÒÁ âä
+# server=localhost
+#
+# # éÍÑ âä
+# database=stargazer
+#
+# # éÍÑ ÐÏÌØÚÏ×ÁÔÅÌÑ âä
+# user=stg
+#
+# # ðÁÒÏÌØ ÐÏÌØÚÏ×ÁÔÅÌÑ âä
+# password=123456
+#</StoreModule>
+
+#<StoreModule store_mysql>
+# # éÍÑ ÐÏÌØÚÏ×ÁÔÅÌÑ âä
+# dbuser = stg
+#
+# # ðÁÒÏÌØ ÐÏÌØÚÏ×ÁÔÅÌÑ âä
+# rootdbpass = 123456
+#
+# # éÍÑ âä ÎÁ ÓÅÒ×ÅÒÅ
+# dbname = stg
+#
+# # áÄÒÅÓ ÓÅÒ×ÅÒÁ âä
+# dbhost = localhost
+#</StoreModule>
+
+################################################################################
+# ðÒÏÞÉÅ ÍÏÄÕÌÉ
+
+<Modules>
+
+ # îÁÓÔÒÏÊËÉ ÐÌÁÇÉÎÁ Á×ÔÏÒÉÚÁÃÉÉ Always Online "mod_auth_ao.so"
+ # ÷ÔÏÒÏÊ ÐÁÒÁÍÅÔÒ - ÜÔÏ ÉÍÑ ÍÏÄÕÌÑ ÂÅÚ mod_ × ÎÁÞÁÌÅ É .so × ËÏÎÃÅ
+ # ô.Å. ÐÏÌÎÏÅ ÉÍÑ ÍÏÄÕÌÑ mod_auth_ao.so
+ <Module auth_ao>
+ </Module>
+
+
+
+ # îÁÓÔÒÏÊËÉ ÐÌÁÇÉÎÁ Á×ÔÏÒÉÚÁÃÉÉ InetAccess "mod_auth_ia.so"
+ # ÷ÔÏÒÏÊ ÐÁÒÁÍÅÔÒ - ÜÔÏ ÉÍÑ ÍÏÄÕÌÑ ÂÅÚ mod_ × ÎÁÞÁÌÅ É .so × ËÏÎÃÅ
+ # ô.Å. ÐÏÌÎÏÅ ÉÍÑ ÍÏÄÕÌÑ mod_auth_ia.so
+ <Module auth_ia>
+
+ # ðÏÒÔ ÎÁ ËÏÔÏÒÏÍ ÐÒÉÎÉÍÁÀÔÓÑ ÏÂÒÁÝÅÎÉÑ ÏÔ Á×ÔÏÒÉÚÁÔÏÒÁ
+ # úÎÁÞÅÎÉÑ: 1...65534
+ Port = 5555
+
+
+ # ÷ÒÅÍÑ ÍÅÖÄÕ ÐÏÓÙÌËÁÍÉ ÚÁÐÒÏÓÁ ÐÏÌØÚÏ×ÁÔÅÌÀ ÖÉ× ÌÉ ÏÎ
+ # É ÏÂÎÏ×ÌÅÎÉÅÍ ÄÁÎÎÙÈ ÓÔÁÔÉÓÔÉËÉ (ÓÅËÕÎÄÙ)
+ # úÎÁÞÅÎÉÑ: 5...600
+ UserDelay = 15
+
+
+ #ôÁÊÍÁÕÔ ÄÌÑ ÐÏÌØÚÏ×ÁÔÅÌÑ. åÓÌÉ × ÔÅÞÅÎÉÅ ÜÔÏÇÏ ×ÒÅÍÅÎÉ Á×ÔÏÒÉÚÁÔÏÒ
+ #ÎÅ ÏÔ×ÅÞÁÅÔ, ÐÏÌØÚÏ×ÁÔÅÌØ ÂÕÄÅÔ ÏÔËÌÀÞÅÎ
+ # úÎÁÞÅÎÉÑ: 15...1200
+ UserTimeout = 65
+
+
+ # üÔÏÔ ÐÁÒÁÍÅÔÒ ÏÐÒÅÄÅÌÑÅÔ ÞÔÏ ÂÕÄÅÔ ÐÅÒÅÄÁ×ÁÔØÓÑ ÐÒÏÇÒÁÍÍÅ InetAccess ÏÔ ÓÅÒ×ÅÒÁ
+ # ËÁË ÏÔÓÔÁÔÏË ÐÒÅÄÏÐÌÁÞÅÎÎÏÇÏ ÔÒÁÆÉËÁ
+ # úÎÁÞÅÎÉÑ:
+ # FreeMb = 0 - ËÏÌ-×Ï ÂÅÓÐÌÁÔÎÙÈ ÍÅÇÁÂÁÊÔ × ÐÒÅÓÞÅÔÅ ÎÁ ÃÅÎÕ ÎÕÌÅ×ÏÇÏ ÎÁÐÒÁ×ÌÅÎÉÑ
+ # FreeMb = 1 - ËÏÌ-×Ï ÂÅÓÐÌÁÔÎÙÈ ÍÅÇÁÂÁÊÔ × ÐÒÅÓÞÅÔÅ ÎÁ ÃÅÎÕ ÐÅÒ×ÏÇÏ ÎÁÐÒÁ×ÌÅÎÉÑ
+ # FreeMb = 2 - ËÏÌ-×Ï ÂÅÓÐÌÁÔÎÙÈ ÍÅÇÁÂÁÊÔ × ÐÒÅÓÞÅÔÅ ÎÁ ÃÅÎÕ ×ÔÏÒÏÇÏ ÎÁÐÒÁ×ÌÅÎÉÑ
+ # FreeMb = 3 - ËÏÌ-×Ï ÂÅÓÐÌÁÔÎÙÈ ÍÅÇÁÂÁÊÔ × ÐÒÅÓÞÅÔÅ ÎÁ ÃÅÎÕ ÔÒÅÔØÅÇÏ ÎÁÐÒÁ×ÌÅÎÉÑ
+ # ........................
+ # FreeMb = 9 - ËÏÌ-×Ï ÂÅÓÐÌÁÔÎÙÈ ÍÅÇÁÂÁÊÔ × ÐÒÅÓÞÅÔÅ ÎÁ ÃÅÎÕ ÄÅ×ÑÔÏÇÏ ÎÁÐÒÁ×ÌÅÎÉÑ
+ # FreeMb = cash - ËÏÌ-×Ï ÄÅÎÅÇ ÎÁ ËÏÔÏÒÙÅ ÀÚÅÒ ÍÏÖÅÔ ÂÅÓÐÌÁÔÎÏ ËÁÞÁÔØ
+ # FreeMb = none - ÎÉÞÅÇÏ ÎÅ ÐÅÒÅÄÁ×ÁÔØ
+ FreeMb = cash
+
+ </Module>
+
+
+
+ # íÏÄÕÌÉ ÍÏÖÎÏ ÉÓÐÏÌØÚÏ×ÁÔØ ÎÅÓËÏÌØËÏ ÒÁÚ Ó ÒÁÚÎÙÍÉ ÐÁÒÁÍÅÔÒÁÍÉ
+ #<Module auth_ia>
+ # Port = 7777
+ # UserDelay = 15
+ # UserTimeout = 65
+ # FreeMb = 0
+ #</Module>
+
+
+
+ # îÁÓÔÒÏÊËÉ ÍÏÄÕÌÑ ËÏÎÆÉÇÕÒÁÃÉÉ SgConfig "mod_conf_sg.so"
+ # ÷ÔÏÒÏÊ ÐÁÒÁÍÅÔÒ - ÜÔÏ ÉÍÑ ÍÏÄÕÌÑ ÂÅÚ mod_ × ÎÁÞÁÌÅ É .so × ËÏÎÃÅ
+ <Module conf_sg>
+
+ # ðÏÒÔ ÐÏ ËÏÔÏÒÏÍÕ ÓÅÒ×ÅÒ ×ÚÁÉÍÏÄÅÊÓÔ×ÕÅÔ Ó ËÏÎÆÉÇÕÒÁÔÏÒÏÍ
+ # úÎÁÞÅÎÉÑ: 1...65535
+ Port = 5555
+
+ </Module>
+
+
+
+ # íÏÄÕÌØ ÚÁÈ×ÁÔÁ ÔÒÁÆÉËÁ "mod_cap_ether.so"
+ # ÷ÔÏÒÏÊ ÐÁÒÁÍÅÔÅÒ - ÜÔÏ ÉÍÑ ÍÏÄÕÌÑ ÂÅÚ mod_ × ÎÁÞÁÌÅ É .so × ËÏÎÃÅ
+ # âÅÚ ÐÁÒÁÍÅÔÒÏ×. ôÏÌØËÏ ÉÍÑ ÍÏÄÕÌÑ.
+ <Module cap_ether>
+ # íÏÄÕÌØ ÂÅÚ ÐÁÒÁÍÅÔÒÏ×
+ </Module>
+
+ # íÏÄÕÌØ ÚÁÈ×ÁÔÁ ÔÒÁÆÉËÁ "mod_cap_nf.so"
+ # ðÒÉÎÉÍÁÅÔ ÉÎÆÏÒÍÁÃÉÀ Ï ÔÒÁÆÉËÅ ÐÏ ÐÒÏÔÏËÏÌÕ NetFlow
+ # ÷ÔÏÒÏÊ ÐÁÒÁÍÅÔÅÒ - ÜÔÏ ÉÍÑ ÍÏÄÕÌÑ ÂÅÚ mod_ × ÎÁÞÁÌÅ É .so × ËÏÎÃÅ
+ <Module cap_nf>
+ # TCPPort - ÐÏÒÔ ÄÌÑ TCP-ÓÏÅÄÉÎÅÎÉÊ
+ TCPPort = 42111
+
+ # UDPPort - ÐÏÒÔ ÄÌÑ UDP-ÓÏÅÄÉÎÅÎÉÊ
+ UDPPort = 42111
+
+ # íÏÇÕÔ ÉÍÅÔØ ÓÏ×ÐÁÄÁÀÝÉÅ ÚÎÁÞÅÎÉÑ.
+ # åÓÌÉ ÐÁÒÁÍÅÔÒ ÎÅ ÕËÁÚÁÎ - ÓÏÏÔ×ÅÔÓÔ×ÕÀÝÉÊ ÐÏÒÔ ÎÅ "ÐÒÏÓÌÕÛÉ×ÁÅÔÓÑ".
+ </Module>
+
+
+
+ # îÁÓÔÒÏÊËÉ ÍÏÄÕÌÑ ÐÉÎÇÕÀÝÅÇÏ ÐÏÌØÚÏ×ÁÔÅÌÅÊ "mod_ping.so"
+ # ÷ÔÏÒÏÊ ÐÁÒÁÍÅÔÒ - ÜÔÏ ÉÍÑ ÍÏÄÕÌÑ ÂÅÚ mod_ × ÎÁÞÁÌÅ É .so × ËÏÎÃÅ
+ <Module ping>
+
+ # ÷ÒÅÍÑ, × ÓÅËÕÎÄÁÈ, ÍÅÖÄÕ ÐÉÎÇÁÍÉ ÏÄÎÏÇÏ É ÔÏÇÏ ÖÅ ÐÏÌØÚÏ×ÁÔÅÌÑ
+ # úÎÁÞÅÎÉÑ: 10...3600
+ PingDelay = 15
+
+ </Module>
+
+# # îÁÓÔÒÏÊËÉ ÍÏÄÕÌÑ ÄÌÑ ÕÄÁÌÅÎÎÏÇÏ ×ÙÐÏÌÎÅÎÉÑ ÓËÒÉÐÔÏ× OnConnect É
+# # OnDisconnect "mod_remote_script.so"
+# # ÷ÔÏÒÏÊ ÐÁÒÁÍÅÔÒ - ÜÔÏ ÉÍÑ ÍÏÄÕÌÑ ÂÅÚ mod_ × ÎÁÞÁÌÅ É .so × ËÏÎÃÅ
+# <Module remote_script>
+#
+# # ÷ÒÅÍÑ, × ÓÅËÕÎÄÁÈ, ÍÅÖÄÕ ÐÏÓÙÌËÁÍÉ ÐÏÄÔ×ÅÒÖÄÅÎÉÊ, ÔÏÇÏ, ÞÔÏ ÐÏÌØÚÏ×ÁÔÅÌØ
+# # ×Ó£ ÅÝÅ ÏÎÌÁÊÎ
+# # úÎÁÞÅÎÉÑ: 10...600
+# SendPeriod = 15
+#
+# # óÏÏÔ×ÅÔÓÔ×ÉÅ ÐÏÄÓÅÔÅÊ, × ËÏÔÏÒÏÊ ÎÁÈÏÄÉÔÓÑ ÐÏÌØÚÏ×ÁÔÅÌØ É
+# # ÓÏÏÔ×ÅÔÓÔ×ÕÀÝÅÇÏ ÒÏÕÔÅÒÁ. ðÅÒ×ÁÑ ÞÁÓÔØ ÓÔÒÏËÉ - ÐÏÄÓÅÔØ, ÚÁÄÁÎÎÁÑ
+# # ËÁË IP-ÁÄÒÅÓ É ÍÁÓËÁ, ÞÅÒÅÚ ÐÒÏÂÅÌ - IP-ÁÄÒÅÓ ÒÏÕÔÅÒÁ ÎÁ ËÏÔÏÒÏÍ
+# # ÄÏÌÖÎÙ ×ÙÐÏÌÎÑÔØÓÑ ÓËÒÉÐÔÙ
+# # îÁÐÒÉÍÅÒ ÜÔÁ ÚÁÐÉÓØ "192.168.1.0/24 192.168.1.1" ÏÚÎÁÞÁÅÔ, ÞÔÏ ÄÌÑ
+# # ×ÓÅÈ ÐÏÌØÚÏ×ÁÔÅÌÅÊ ÉÚ ÐÏÄÓÅÔÉ 192.168.1.0/24, ÓËÒÉÐÔÙ ÂÕÄÕÔ
+# # ×ÙÐÏÌÎÑÔØÓÑ ÎÁ ÒÏÕÔÅÒÅ Ó ÁÄÒÅÓÏÍ 192.168.1.1
+# # Subnet0...Subnet100
+# Subnet0 = 192.168.1.0/24 192.168.1.7
+# Subnet1 = 192.168.2.0/24 192.168.2.5
+# Subnet2 = 192.168.3.0/24 192.168.2.5
+# Subnet3 = 192.168.4.0/24 192.168.2.5
+#
+# # ðÁÒÏÌØ ÄÌÑ ÛÉÆÒÏ×ÁÎÉÑ ÐÁËÅÔÏ× ÍÅÖÄÕ stg-ÓÅÒ×ÅÒÏÍ É ÓÅÒ×ÅÒÏÍ,
+# # ×ÙÐÏÌÎÑÀÝÉÍ ÓËÒÉÐÔÙ
+# Password = 123456
+#
+# # üÔÏÔ ÐÁÒÁÍÅÔÒ ÏÐÒÅÄÅÌÑÅÔ ËÁËÉÅ ÐÁÒÁÍÅÔÒÙ ÐÏÌØÚÏ×ÁÔÅÌÑ ÐÅÒÅÄÁÀÔÓÑ
+# # ÎÁ ÕÄÁÌÅÎÎÙÊ ÓÅÒ×ÅÒ
+# # Cash, FreeMb, Passive, Disabled, AlwaysOnline, TariffName, NextTariff, Address,
+# # Note, Group, Email, RealName, Credit, EnabledDirs, Userdata0...Userdata9
+# UserParams=Cash Tariff EnabledDirs
+#
+# # ðÏÒÔ ÐÏ ËÏÔÏÒÏÍÕ ÓÅÒ×ÅÒ ÏÔÓÙÌÁÅÔ ÓÏÏÂÝÅÎÉÑ ÎÁ ÒÏÕÔÅÒ
+# # úÎÁÞÅÎÉÑ: 1...65535
+# Port = 9999
+#
+# </Module>
+
+# <Module radius>
+# Password = 123456
+# ServerIP = 127.0.0.1
+# Port = 6666
+# AuthServices = Login-User
+# AcctServices = Framed-User
+# </Module>
+
+</Modules>
+################################################################################
+
--- /dev/null
+/*
+ * DB migration from v00 to v01 (postgres)
+ */
+
+ALTER TABLE tb_sessions_log ADD free_mb dm_money;
+ALTER TABLE tb_sessions_log ADD reason TEXT;
+
+DROP FUNCTION sp_add_session_log_entry ( dm_name, timestamp without time zone, dm_session_event_type, inet, dm_money);
+
+CREATE FUNCTION sp_add_session_log_entry(_login dm_name,
+ _event_time TIMESTAMP,
+ _event_type dm_session_event_type,
+ _ip INET,
+ _cash dm_money,
+ _free_mb dm_money,
+ _reason TEXT)
+RETURNS INTEGER
+AS $$
+DECLARE
+ _pk_user INTEGER;
+ _pk_session_log INTEGER;
+BEGIN
+ SELECT pk_user INTO _pk_user
+ FROM tb_users
+ WHERE name = _login;
+ IF _pk_user IS NULL THEN
+ RAISE EXCEPTION 'User % not found', _login;
+ RETURN -1;
+ END IF;
+
+ INSERT INTO tb_sessions_log
+ (fk_user,
+ event_time,
+ event_type,
+ ip,
+ cash,
+ free_mb,
+ reason)
+ VALUES
+ (_pk_user,
+ _event_time,
+ _event_type,
+ _ip,
+ _cash,
+ _free_mb,
+ _reason);
+
+ SELECT CURRVAL('tb_sessions_log_pk_session_log_seq') INTO _pk_session_log;
+
+ RETURN _pk_session_log;
+END;
+$$ LANGUAGE plpgsql;
+
+UPDATE tb_info SET version = 6;
--- /dev/null
+/*
+ * DB migration from v00 to v01 (firebird)
+ */
+
+alter table tb_users add disabled_detail_stat dm_bool;
+
+drop procedure sp_add_user;
+
+set term !! ;
+create procedure sp_add_user(name varchar(32), dirs integer)
+as
+declare variable pk_user integer;
+declare variable pk_stat integer;
+begin
+ pk_user = gen_id(gn_pk_user, 1);
+ insert into tb_users(pk_user, fk_tariff, fk_tariff_change, fk_corporation, address, always_online, credit, credit_expire, disabled, disabled_detail_stat, email, grp, note, passive, passwd, phone, name, real_name) values (:pk_user, NULL, NULL, NULL, '', 0, 0, 'now', 0, 0, '', '_', '', 0, '', '', :name, '');
+ pk_stat = gen_id(gn_pk_stat, 1);
+ insert into tb_stats values (:pk_stat, :pk_user, 0, 0, 'now', 0, 'now', 0, 'now');
+ while (dirs > 0) do
+ begin
+ insert into tb_stats_traffic (fk_stat, dir_num, upload, download) values (:pk_stat, :dirs - 1, 0, 0);
+ dirs = dirs - 1;
+ end
+end!!
+set term ; !!
--- /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
+ */
+
+/*
+ *****************************************************************************
+ *
+ * Скрипт генерации структуры базы для хранения данных Stargazer-a
+ *
+ * Примечание.
+ * * dm_permission_flag. Представляет собой битовую маску - rw.
+ * r - чтение, w - изменение параметра.
+ * 0 - дествие запрещено, 1 - действие разрешено
+ *
+ * * dm_traff_type. Число определяющее тип подсчета трафика:
+ * 0 - up - считается по upload
+ * 1 - down - считается по download
+ * 2 - max - считается по максимальному среди upload/download
+ * 3 - up+down - считается по сумме upload и download
+ *
+ * * dm_session_event_type. Указывает тип записи в логе о сессии.
+ * 'c' - connect, 'd' - disconnect.
+ *
+ * * При занесении IP адресса в БД выполнять приведение к
+ * знаковуму целому!!!
+ *
+ *****************************************************************************
+ */
+
+/*
+ * $Revision: 1.12 $
+ * $Date: 2009/08/20 14:58:43 $
+ */
+
+
+/*
+ *****************************************************************************
+ * -= Создание типов и доменов =-
+ *****************************************************************************
+ */
+
+CREATE DOMAIN dm_name AS VARCHAR(32) NOT NULL;
+CREATE DOMAIN dm_password AS VARCHAR(64) NOT NULL;
+CREATE DOMAIN dm_permission_flag AS SMALLINT NOT NULL
+ CHECK ( value BETWEEN 0 AND 3 );
+CREATE DOMAIN dm_money AS NUMERIC(12, 4) NOT NULL DEFAULT 0;
+CREATE DOMAIN dm_traff_type AS SMALLINT NOT NULL
+ CHECK ( value BETWEEN 0 AND 3 );
+CREATE DOMAIN dm_day AS SMALLINT NOT NULL
+ CHECK ( value BETWEEN 0 AND 31 )
+ DEFAULT 0;
+CREATE DOMAIN dm_session_event_type AS CHAR(1) NOT NULL
+ CHECK ( value = 'c' OR value = 'd' );
+
+/*
+ *****************************************************************************
+ * -= Создание таблиц =-
+ *****************************************************************************
+ */
+
+CREATE TABLE tb_info
+(
+ version INTEGER NOT NULL
+);
+
+CREATE TABLE tb_admins
+(
+ pk_admin SERIAL PRIMARY KEY,
+ login dm_name UNIQUE,
+ passwd dm_password NOT NULL,
+ chg_conf dm_permission_flag,
+ chg_password dm_permission_flag,
+ chg_stat dm_permission_flag,
+ chg_cash dm_permission_flag,
+ usr_add_del dm_permission_flag,
+ chg_tariff dm_permission_flag,
+ chg_admin dm_permission_flag,
+ chg_service dm_permission_flag,
+ chg_corporation dm_permission_flag
+);
+
+CREATE TABLE tb_tariffs
+(
+ pk_tariff SERIAL PRIMARY KEY,
+ name dm_name UNIQUE,
+ fee dm_money,
+ free dm_money,
+ passive_cost dm_money,
+ traff_type dm_traff_type
+);
+
+CREATE TABLE tb_tariffs_params
+(
+ pk_tariff_param SERIAL PRIMARY KEY,
+ fk_tariff INTEGER NOT NULL,
+ dir_num SMALLINT NOT NULL,
+ price_day_a dm_money,
+ price_day_b dm_money,
+ price_night_a dm_money,
+ price_night_b dm_money,
+ threshold INTEGER NOT NULL,
+ time_day_begins TIME NOT NULL,
+ time_day_ends TIME NOT NULL,
+
+ FOREIGN KEY (fk_tariff)
+ REFERENCES tb_tariffs (pk_tariff)
+ ON DELETE CASCADE
+);
+
+CREATE TABLE tb_corporations
+(
+ pk_corporation SERIAL PRIMARY KEY,
+ name dm_name UNIQUE,
+ cash dm_money
+);
+
+CREATE TABLE tb_users
+(
+ pk_user SERIAL PRIMARY KEY,
+ fk_tariff INTEGER,
+ fk_tariff_change INTEGER,
+ fk_corporation INTEGER,
+ address VARCHAR(256) NOT NULL,
+ always_online BOOLEAN NOT NULL,
+ credit dm_money,
+ credit_expire TIMESTAMP NOT NULL,
+ disabled BOOLEAN NOT NULL,
+ disabled_detail_stat BOOLEAN NOT NULL,
+ email VARCHAR(256) NOT NULL,
+ grp dm_name,
+ note TEXT NOT NULL,
+ passive BOOLEAN NOT NULL,
+ passwd dm_password,
+ phone VARCHAR(256) NOT NULL,
+ name dm_name UNIQUE,
+ real_name VARCHAR(256) NOT NULL,
+ cash dm_money,
+ free_mb dm_money,
+ last_activity_time TIMESTAMP NOT NULL,
+ last_cash_add dm_money,
+ last_cash_add_time TIMESTAMP NOT NULL,
+ passive_time INTEGER NOT NULL,
+
+ FOREIGN KEY (fk_tariff)
+ REFERENCES tb_tariffs (pk_tariff)
+ ON DELETE CASCADE,
+ FOREIGN KEY (fk_tariff_change)
+ REFERENCES tb_tariffs (pk_tariff)
+ ON DELETE CASCADE,
+ FOREIGN KEY (fk_corporation)
+ REFERENCES tb_corporations (pk_corporation)
+ ON DELETE CASCADE
+);
+
+CREATE TABLE tb_detail_stats
+(
+ pk_detail_stat BIGSERIAL PRIMARY KEY,
+ fk_user INTEGER NOT NULL,
+ dir_num SMALLINT NOT NULL,
+ ip INET NOT NULL,
+ download BIGINT NOT NULL,
+ upload BIGINT NOT NULL,
+ cost dm_money,
+ from_time TIMESTAMP NOT NULL,
+ till_time TIMESTAMP NOT NULL,
+
+ FOREIGN KEY (fk_user)
+ REFERENCES tb_users (pk_user)
+ ON DELETE CASCADE
+);
+
+CREATE TABLE tb_services
+(
+ pk_service SERIAL PRIMARY KEY,
+ name dm_name UNIQUE,
+ comment TEXT NOT NULL,
+ cost dm_money,
+ pay_day dm_day
+);
+
+CREATE TABLE tb_users_services
+(
+ pk_user_service SERIAL PRIMARY KEY,
+ fk_user INTEGER NOT NULL,
+ fk_service INTEGER NOT NULL,
+
+ FOREIGN KEY (fk_user)
+ REFERENCES tb_users (pk_user)
+ ON DELETE CASCADE,
+ FOREIGN KEY (fk_service)
+ REFERENCES tb_services (pk_service)
+);
+
+CREATE TABLE tb_messages
+(
+ pk_message SERIAL PRIMARY KEY,
+ fk_user INTEGER NOT NULL,
+ ver SMALLINT NOT NULL,
+ msg_type SMALLINT NOT NULL,
+ last_send_time TIMESTAMP NOT NULL,
+ creation_time TIMESTAMP NOT NULL,
+ show_time INTEGER NOT NULL,
+ repeat SMALLINT NOT NULL,
+ repeat_period INTEGER NOT NULL,
+ msg_text TEXT NOT NULL,
+
+ FOREIGN KEY (fk_user)
+ REFERENCES tb_users (pk_user)
+ ON DELETE CASCADE
+);
+
+CREATE TABLE tb_stats_traffic
+(
+ pk_stat_traffic BIGSERIAL PRIMARY KEY,
+ fk_user INTEGER NOT NULL,
+ stats_date DATE NOT NULL,
+ dir_num SMALLINT NOT NULL,
+ download BIGINT NOT NULL,
+ upload BIGINT NOT NULL,
+
+ FOREIGN KEY (fk_user)
+ REFERENCES tb_users (pk_user)
+ ON DELETE CASCADE,
+ UNIQUE (fk_user, stats_date, dir_num)
+);
+
+CREATE TABLE tb_users_data
+(
+ pk_user_data SERIAL PRIMARY KEY,
+ fk_user INTEGER NOT NULL,
+ num SMALLINT NOT NULL,
+ data VARCHAR(256) NOT NULL,
+
+ FOREIGN KEY (fk_user)
+ REFERENCES tb_users (pk_user)
+ ON DELETE CASCADE
+);
+
+CREATE TABLE tb_allowed_ip
+(
+ pk_allowed_ip SERIAL PRIMARY KEY,
+ fk_user INTEGER NOT NULL,
+ ip INET NOT NULL,
+
+ FOREIGN KEY (fk_user)
+ REFERENCES tb_users (pk_user)
+ ON DELETE CASCADE
+);
+
+CREATE TABLE tb_sessions_log
+(
+ pk_session_log SERIAL PRIMARY KEY,
+ fk_user INTEGER NOT NULL,
+ event_time TIMESTAMP NOT NULL,
+ event_type dm_session_event_type,
+ ip INET NOT NULL,
+ cash dm_money,
+
+ FOREIGN KEY (fk_user)
+ REFERENCES tb_users (pk_user)
+ ON DELETE CASCADE
+);
+
+CREATE TABLE tb_sessions_data
+(
+ pk_session_data SERIAL PRIMARY KEY,
+ fk_session_log INTEGER NOT NULL,
+ dir_num SMALLINT NOT NULL,
+ session_upload BIGINT NOT NULL,
+ session_download BIGINT NOT NULL,
+ month_upload BIGINT NOT NULL,
+ month_download BIGINT NOT NULL,
+
+ FOREIGN KEY (fk_session_log)
+ REFERENCES tb_sessions_log (pk_session_log)
+ ON DELETE CASCADE
+);
+
+CREATE TABLE tb_parameters
+(
+ pk_parameter SERIAL PRIMARY KEY,
+ name dm_name UNIQUE
+);
+
+CREATE TABLE tb_params_log
+(
+ pk_param_log SERIAL PRIMARY KEY,
+ fk_user INTEGER NOT NULL,
+ fk_parameter INTEGER NOT NULL,
+ fk_admin INTEGER NOT NULL,
+ ip INET NOT NULL,
+ event_time TIMESTAMP NOT NULL,
+ from_val VARCHAR(256),
+ to_val VARCHAR(256),
+ comment TEXT,
+
+ FOREIGN KEY (fk_user)
+ REFERENCES tb_users (pk_user)
+ ON DELETE CASCADE,
+ FOREIGN KEY (fk_parameter)
+ REFERENCES tb_parameters (pk_parameter),
+ FOREIGN KEY (fk_admin)
+ REFERENCES tb_admins (pk_admin)
+ ON DELETE CASCADE
+);
+
+/*
+ *****************************************************************************
+ * -= Создание хранимых процедур =-
+ *****************************************************************************
+ */
+
+CREATE FUNCTION sp_add_message(_login dm_name,
+ _ver SMALLINT,
+ _msg_type SMALLINT,
+ _last_send_time TIMESTAMP,
+ _creation_time TIMESTAMP,
+ _show_time INTEGER,
+ _repeat SMALLINT,
+ _repeat_period INTEGER,
+ _msg_text TEXT)
+RETURNS INTEGER
+AS $$
+DECLARE
+ _pk_user INTEGER;
+BEGIN
+ SELECT pk_user INTO _pk_user
+ FROM tb_users
+ WHERE name = _login;
+ IF _pk_user IS NULL THEN
+ RAISE EXCEPTION 'User % not found', _login;
+ RETURN -1;
+ END IF;
+ INSERT INTO tb_messages
+ (fk_user,
+ ver,
+ msg_type,
+ last_send_time,
+ creation_time,
+ show_time,
+ repeat,
+ repeat_period,
+ msg_text)
+ VALUES
+ (_pk_user,
+ _ver,
+ _msg_type,
+ _last_send_time,
+ _creation_time,
+ _show_time,
+ _repeat,
+ _repeat_period,
+ _msg_text);
+ RETURN CURRVAL('tb_messages_pk_message_seq');
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE FUNCTION sp_add_tariff(_name dm_name, _dirs INTEGER)
+RETURNS INTEGER
+AS $$
+DECLARE
+ pk_tariff INTEGER;
+BEGIN
+ INSERT INTO tb_tariffs
+ (name,
+ fee,
+ free,
+ passive_cost,
+ traff_type)
+ VALUES
+ (_name,
+ 0, 0, 0, 0);
+ SELECT CURRVAL('tb_tariffs_pk_tariff_seq') INTO pk_tariff;
+ FOR i IN 1.._dirs LOOP
+ INSERT INTO tb_tariffs_params
+ (fk_tariff,
+ dir_num,
+ price_day_a,
+ price_day_b,
+ price_night_a,
+ price_night_b,
+ threshold,
+ time_day_begins,
+ time_day_ends)
+ VALUES
+ (pk_tariff,
+ i - 1,
+ 0, 0, 0, 0, 0,
+ CAST('1970-01-01 00:00:00+00' AS TIMESTAMP),
+ CAST('1970-01-01 00:00:00+00' AS TIMESTAMP));
+ END LOOP;
+ RETURN pk_tariff;
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE FUNCTION sp_add_user(_name dm_name)
+RETURNS INTEGER
+AS $$
+DECLARE
+ pk_user INTEGER;
+BEGIN
+ INSERT INTO tb_users
+ (fk_tariff,
+ fk_tariff_change,
+ fk_corporation,
+ address,
+ always_online,
+ credit,
+ credit_expire,
+ disabled,
+ disabled_detail_stat,
+ email,
+ grp,
+ note,
+ passive,
+ passwd,
+ phone,
+ name,
+ real_name,
+ cash,
+ free_mb,
+ last_activity_time,
+ last_cash_add,
+ last_cash_add_time,
+ passive_time)
+ VALUES
+ (NULL, NULL, NULL, '', FALSE, 0, CAST('now' AS TIMESTAMP),
+ FALSE, FALSE, '', '', '', FALSE, '', '', _name, '', 0, 0,
+ CAST('now' AS TIMESTAMP), 0, CAST('now' AS TIMESTAMP), 0);
+ SELECT CURRVAL('tb_users_pk_user_seq') INTO pk_user;
+ RETURN pk_user;
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE FUNCTION sp_add_stats_traffic (_login dm_name,
+ _stats_date DATE,
+ _dir_num SMALLINT,
+ _upload BIGINT,
+ _download BIGINT)
+RETURNS INTEGER
+AS $$
+DECLARE
+ _pk_user INTEGER;
+BEGIN
+ SELECT pk_user INTO _pk_user
+ FROM tb_users
+ WHERE name = _login;
+
+ IF _pk_user IS NULL THEN
+ RAISE EXCEPTION 'User % not found', _login;
+ RETURN -1;
+ END IF;
+
+ UPDATE tb_stats_traffic SET
+ upload = _upload,
+ download = _download
+ WHERE fk_user = _pk_user AND
+ dir_num = _dir_num AND
+ stats_date = _stats_date;
+
+ IF NOT FOUND THEN
+ INSERT INTO tb_stats_traffic
+ (fk_user,
+ dir_num,
+ stats_date,
+ upload,
+ download)
+ VALUES
+ (_pk_user,
+ _dir_num,
+ _stats_date,
+ _upload,
+ _download);
+ END IF;
+
+ RETURN 1;
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE FUNCTION sp_set_user_data (_pk_user INTEGER,
+ _num SMALLINT,
+ _data VARCHAR(256))
+RETURNS INTEGER
+AS $$
+BEGIN
+ UPDATE tb_users_data SET
+ data = _data
+ WHERE fk_user = _pk_user AND num = _num;
+
+ IF NOT FOUND THEN
+ INSERT INTO tb_users_data
+ (fk_user,
+ num,
+ data)
+ VALUES
+ (_pk_user,
+ _num,
+ _data);
+ END IF;
+
+ RETURN 1;
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE FUNCTION sp_add_param_log_entry(_login dm_name,
+ _admin_login dm_name,
+ _ip INET,
+ _param_name dm_name,
+ _event_time TIMESTAMP,
+ _from VARCHAR(256),
+ _to VARCHAR(256),
+ _comment TEXT)
+RETURNS INTEGER
+AS $$
+DECLARE
+ _pk_user INTEGER;
+ _pk_admin INTEGER;
+ _pk_param INTEGER;
+BEGIN
+ SELECT pk_user INTO _pk_user
+ FROM tb_users
+ WHERE name = _login;
+ IF _pk_user IS NULL THEN
+ RAISE EXCEPTION 'User % not found', _login;
+ RETURN -1;
+ END IF;
+
+ SELECT pk_admin INTO _pk_admin
+ FROM tb_admins
+ WHERE login = _admin_login;
+ IF _pk_admin IS NULL THEN
+ RAISE EXCEPTION 'Admin % not found', _admin_login;
+ RETURN -1;
+ END IF;
+
+ SELECT pk_parameter INTO _pk_param
+ FROM tb_parameters
+ WHERE name = _param_name;
+
+ IF NOT FOUND THEN
+ INSERT INTO tb_parameters (name) VALUES (_param_name);
+ SELECT CURRVAL('tb_parameters_pk_parameter_seq') INTO _pk_param;
+ END IF;
+
+ INSERT INTO tb_params_log
+ (fk_user,
+ fk_parameter,
+ fk_admin,
+ ip,
+ event_time,
+ from_val,
+ to_val,
+ comment)
+ VALUES
+ (_pk_user,
+ _pk_param,
+ _pk_admin,
+ _ip,
+ _event_time,
+ _from,
+ _to,
+ _comment);
+
+ RETURN 1;
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE FUNCTION sp_add_session_log_entry(_login dm_name,
+ _event_time TIMESTAMP,
+ _event_type dm_session_event_type,
+ _ip INET,
+ _cash dm_money)
+RETURNS INTEGER
+AS $$
+DECLARE
+ _pk_user INTEGER;
+ _pk_session_log INTEGER;
+BEGIN
+ SELECT pk_user INTO _pk_user
+ FROM tb_users
+ WHERE name = _login;
+ IF _pk_user IS NULL THEN
+ RAISE EXCEPTION 'User % not found', _login;
+ RETURN -1;
+ END IF;
+
+ INSERT INTO tb_sessions_log
+ (fk_user,
+ event_time,
+ event_type,
+ ip,
+ cash)
+ VALUES
+ (_pk_user,
+ _event_time,
+ _event_type,
+ _ip,
+ _cash);
+
+ SELECT CURRVAL('tb_sessions_log_pk_session_log_seq') INTO _pk_session_log;
+
+ RETURN _pk_session_log;
+END;
+$$ LANGUAGE plpgsql;
+
+/*
+ *****************************************************************************
+ * -= Создание администратора =-
+ *
+ * Двоичные права доступа пока не поддерживаются, по этому используются флаги
+ *****************************************************************************
+ */
+INSERT INTO tb_admins
+ (login, passwd,
+ chg_conf, chg_password, chg_stat,
+ chg_cash, usr_add_del, chg_tariff,
+ chg_admin, chg_service, chg_corporation)
+VALUES
+ ('admin',
+ 'geahonjehjfofnhammefahbbbfbmpkmkmmefahbbbfbmpkmkmmefahbbbfbmpkmk',
+ 1, 1, 1, 1, 1, 1, 1, 1, 1);
+
+INSERT INTO tb_info
+ (version)
+VALUES
+ (5);
--- /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
+ */
+
+/*
+ *****************************************************************************
+ *
+ * Скрипт генерации структуры базы для хранения данных Stargazer-a
+ *
+ * $Id: 00-base-00.sql,v 1.7 2010/01/06 14:41:13 faust Exp $
+ *
+ * Примечание.
+ * * dm_permission_flag. Представляет собой битовую маску - rw.
+ * r - чтение, w - изменение параметра.
+ * 0 - дествие запрещено, 1 - действие разрешено
+ *
+ * * dm_traff_type. Число определяющее тип подсчета трафика:
+ * 0 - up - считается по upload
+ * 1 - down - считается по download
+ * 2 - max - считается по максимальному среди upload/download
+ * 3 - up+down - считается по сумме upload и download
+ * Как альтернативу этому полю можно сделать еще одну таблицу - типов
+ * подсчета трафика. И в этом поле хранить ссылку на эту таблицу.
+ * Вопрос только "А надо ли это?"
+ *
+ * * dm_ip. IP адресс в виде четырех байтового целого числа со знаком.
+ * Выполнять приведение к знаковуму целому при занесении IP в БД!!!
+ *
+ * * dm_period. Задает периодичность показа сообщения пользователю.
+ * Период задается целым числом (int16). Если значение равно 0 то
+ * сообщение показывается только при подключении пользователя.
+ * Также этот домен определяет промежуток времени в течении которого
+ * сообщение показывается пользователю.
+ *
+ * * dm_session_event_type. Указывает тип записи в логе о сессии.
+ * 'c' - connect, 'd' - disconnect.
+ *
+ *****************************************************************************
+ */
+
+/*
+ * CONNECT 'localhost:/var/stg/stargazer.fdb' USER 'stg' PASSWORD '123456';
+ * DROP DATABASE;
+ *
+ * CREATE DATABASE 'localhost:/var/stg/stargazer.fdb' USER 'stg' PASSWORD '123456' DEFAULT CHARACTER SET UTF8;
+ */
+
+
+
+/*
+ *****************************************************************************
+ * -= Создание ДОМЕНОВ =-
+ *****************************************************************************
+ */
+
+CREATE DOMAIN dm_id AS INTEGER NOT NULL;
+CREATE DOMAIN dm_null_id AS INTEGER;
+CREATE DOMAIN dm_login AS VARCHAR(32) NOT NULL;
+CREATE DOMAIN dm_tariff_name AS VARCHAR(32) NOT NULL;
+CREATE DOMAIN dm_group_name AS VARCHAR(32);
+CREATE DOMAIN dm_corporation_name AS VARCHAR(32);
+CREATE DOMAIN dm_parameter_name AS VARCHAR(32);
+
+CREATE DOMAIN dm_password AS VARCHAR(64) NOT NULL;
+/* bitmask - rw => Read, Write */
+CREATE DOMAIN dm_permission_flag AS SMALLINT NOT NULL
+ CHECK ( VALUE BETWEEN 0 AND 3 );
+CREATE DOMAIN dm_money AS NUMERIC(10,6) NOT NULL;
+/* (0, 1, 2, 3) => (up, down, max, up+down) */
+CREATE DOMAIN dm_traff_type AS SMALLINT NOT NULL
+ CHECK ( VALUE BETWEEN 0 AND 3 );
+CREATE DOMAIN dm_dir_num AS SMALLINT NOT NULL;
+CREATE DOMAIN dm_num AS SMALLINT NOT NULL;
+CREATE DOMAIN dm_traffic_mb AS INTEGER NOT NULL;
+CREATE DOMAIN dm_traffic_byte AS BIGINT NOT NULL;
+CREATE DOMAIN dm_time AS TIME NOT NULL;
+CREATE DOMAIN dm_moment AS TIMESTAMP NOT NULL;
+CREATE DOMAIN dm_credit_moment AS TIMESTAMP;
+CREATE DOMAIN dm_ip AS INTEGER NOT NULL;
+CREATE DOMAIN dm_mask AS INTEGER NOT NULL;
+CREATE DOMAIN dm_user_address AS VARCHAR(256) DEFAULT '';
+CREATE DOMAIN dm_bool AS CHAR(1) NOT NULL
+ CHECK ( VALUE IN ('0', '1', 't', 'f', 'T', 'F') );
+CREATE DOMAIN dm_email AS VARCHAR(256) DEFAULT '';
+CREATE DOMAIN dm_note AS VARCHAR(256) DEFAULT '';
+CREATE DOMAIN dm_phone AS VARCHAR(256) DEFAULT '';
+CREATE DOMAIN dm_user_name AS VARCHAR(256) DEFAULT '';
+CREATE DOMAIN dm_service_comment AS VARCHAR(256) DEFAULT '';
+CREATE DOMAIN dm_service_name AS VARCHAR(32) DEFAULT '';
+/* TODO: why 0-31? Which is default? */
+CREATE DOMAIN dm_pay_day AS SMALLINT NOT NULL
+ CHECK ( VALUE BETWEEN 0 AND 31 );
+CREATE DOMAIN dm_period AS INTEGER NOT NULL;
+CREATE DOMAIN dm_counter AS SMALLINT NOT NULL;
+/* Is it needded? */
+CREATE DOMAIN dm_message_ver AS INTEGER NOT NULL;
+CREATE DOMAIN dm_message_type AS INTEGER NOT NULL;
+/*----------------*/
+CREATE DOMAIN dm_message AS VARCHAR(256) NOT NULL;
+CREATE DOMAIN dm_user_data AS VARCHAR(256) NOT NULL;
+CREATE DOMAIN dm_session_event_type AS CHAR(1) NOT NULL
+ CHECK ( VALUE IN ('c', 'd') );
+CREATE DOMAIN dm_char_value AS VARCHAR(64) NOT NULL;
+CREATE DOMAIN dm_date AS DATE NOT NULL;
+
+
+
+/*
+ *****************************************************************************
+ * -= Создание ТАБЛИЦ =-
+ *****************************************************************************
+ */
+
+CREATE TABLE tb_admins
+(
+ pk_admin dm_id PRIMARY KEY,
+ login dm_login UNIQUE,
+ passwd dm_password,
+ chg_conf dm_permission_flag,
+ chg_password dm_permission_flag,
+ chg_stat dm_permission_flag,
+ chg_cash dm_permission_flag,
+ usr_add_del dm_permission_flag,
+ chg_tariff dm_permission_flag,
+ chg_admin dm_permission_flag,
+ chg_service dm_permission_flag,
+ chg_corporation dm_permission_flag
+);
+
+CREATE TABLE tb_tariffs
+(
+ pk_tariff dm_id PRIMARY KEY,
+ name dm_tariff_name UNIQUE,
+ fee dm_money,
+ free dm_money,
+ passive_cost dm_money,
+ traff_type dm_traff_type
+);
+
+CREATE TABLE tb_tariffs_params
+(
+ pk_tariff_param dm_id PRIMARY KEY,
+ fk_tariff dm_id,
+ dir_num dm_dir_num,
+ price_day_a dm_money,
+ price_day_b dm_money,
+ price_night_a dm_money,
+ price_night_b dm_money,
+ threshold dm_traffic_mb,
+ time_day_begins dm_time,
+ time_day_ends dm_time,
+
+ FOREIGN KEY (fk_tariff) REFERENCES tb_tariffs (pk_tariff)
+);
+
+CREATE TABLE tb_corporations
+(
+ pk_corporation dm_id PRIMARY KEY,
+ name dm_corporation_name UNIQUE,
+ cash dm_money
+);
+
+CREATE TABLE tb_users
+(
+ pk_user dm_id PRIMARY KEY,
+ fk_tariff dm_null_id,
+ fk_tariff_change dm_null_id,
+ fk_corporation dm_null_id,
+ address dm_user_address,
+ always_online dm_bool,
+ credit dm_money,
+ credit_expire dm_credit_moment,
+ disabled dm_bool,
+ disabled_detail_stat dm_bool,
+ email dm_email,
+ grp dm_group_name,
+ note dm_note,
+ passive dm_bool,
+ passwd dm_password,
+ phone dm_phone,
+ name dm_login UNIQUE,
+ real_name dm_user_name,
+
+ FOREIGN KEY (fk_tariff) REFERENCES tb_tariffs (pk_tariff),
+ FOREIGN KEY (fk_tariff_change) REFERENCES tb_tariffs (pk_tariff),
+ FOREIGN KEY (fk_corporation) REFERENCES tb_corporations (pk_corporation)
+);
+
+CREATE TABLE tb_detail_stats
+(
+ pk_detail_stat dm_id PRIMARY KEY,
+ fk_user dm_id,
+ dir_num dm_dir_num,
+ ip dm_ip,
+ download dm_traffic_byte,
+ upload dm_traffic_byte,
+ cost dm_money,
+ from_time dm_moment,
+ till_time dm_moment,
+
+ FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user)
+);
+
+CREATE TABLE tb_services
+(
+ pk_service dm_id PRIMARY KEY,
+ name dm_service_name UNIQUE,
+ comment dm_service_comment,
+ cost dm_money,
+ pay_day dm_pay_day
+);
+
+CREATE TABLE tb_users_services
+(
+ pk_user_service dm_id PRIMARY KEY,
+ fk_user dm_id,
+ fk_service dm_id,
+
+ FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user),
+ FOREIGN KEY (fk_service) REFERENCES tb_services (pk_service)
+);
+
+CREATE TABLE tb_messages
+(
+ pk_message dm_id PRIMARY KEY,
+ fk_user dm_id,
+ ver dm_message_ver,
+ msg_type dm_message_type,
+ last_send_time dm_period,
+ creation_time dm_period,
+ show_time dm_period,
+ repeat dm_counter,
+ repeat_period dm_period,
+ msg_text dm_message,
+
+ FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user)
+);
+
+CREATE TABLE tb_stats
+(
+ pk_stat dm_id PRIMARY KEY,
+ fk_user dm_id,
+ cash dm_money,
+ free_mb dm_money,
+ last_activity_time dm_moment,
+ last_cash_add dm_money,
+ last_cash_add_time dm_moment,
+ passive_time dm_period,
+ stats_date dm_date,
+
+ FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user)
+);
+
+CREATE TABLE tb_stats_traffic
+(
+ pk_stat_traffic dm_id PRIMARY KEY,
+ fk_stat dm_id,
+ dir_num dm_dir_num,
+ download dm_traffic_byte,
+ upload dm_traffic_byte,
+
+ FOREIGN KEY (fk_stat) REFERENCES tb_stats (pk_stat)
+);
+
+CREATE TABLE tb_users_data
+(
+ pk_user_data dm_id PRIMARY KEY,
+ fk_user dm_id,
+ num dm_num, /* data_id dm_id renamed */
+ data dm_user_data,
+
+ FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user)
+);
+
+CREATE TABLE tb_allowed_ip
+(
+ pk_allowed_ip dm_id PRIMARY KEY,
+ fk_user dm_id,
+ ip dm_ip,
+ mask dm_mask,
+
+ FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user)
+);
+
+CREATE TABLE tb_sessions_log
+(
+ pk_session_log dm_id PRIMARY KEY,
+ fk_user dm_id,
+ event_time dm_moment,
+ event_type dm_session_event_type,
+ ip dm_ip,
+
+ FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user)
+);
+
+CREATE TABLE tb_sessions_data
+(
+ pk_session_data dm_id PRIMARY KEY,
+ fk_session_log dm_id,
+ dir_num dm_dir_num,
+ session_upload dm_traffic_byte,
+ session_download dm_traffic_byte,
+ month_upload dm_traffic_byte,
+ month_download dm_traffic_byte,
+
+ FOREIGN KEY (fk_session_log) REFERENCES tb_sessions_log (pk_session_log)
+);
+
+CREATE TABLE tb_parameters
+(
+ pk_parameter dm_id PRIMARY KEY,
+ name dm_parameter_name UNIQUE
+);
+
+CREATE TABLE tb_params_log
+(
+ pk_param_log dm_id PRIMARY KEY,
+ fk_user dm_id,
+ fk_parameter dm_id,
+ event_time dm_moment,
+ from_val dm_char_value,
+ to_val dm_char_value,
+ comment dm_service_comment,
+
+ FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user),
+ FOREIGN KEY (fk_parameter) REFERENCES tb_parameters (pk_parameter)
+);
+
+
+/*
+ *****************************************************************************
+ * -= Создание ИНДЕКСОВ =-
+ *****************************************************************************
+ */
+
+
+
+/*
+ *****************************************************************************
+ * -= Создание ГЕНЕРАТОРОВ =-
+ *****************************************************************************
+ */
+
+CREATE GENERATOR gn_pk_admin;
+SET GENERATOR gn_pk_admin TO 0;
+CREATE GENERATOR gn_pk_tariff;
+SET GENERATOR gn_pk_tariff TO 0;
+CREATE GENERATOR gn_pk_tariff_param;
+SET GENERATOR gn_pk_tariff_param TO 0;
+CREATE GENERATOR gn_pk_corporation;
+SET GENERATOR gn_pk_corporation TO 0;
+CREATE GENERATOR gn_pk_user;
+SET GENERATOR gn_pk_user TO 0;
+CREATE GENERATOR gn_pk_detail_stat;
+SET GENERATOR gn_pk_detail_stat TO 0;
+CREATE GENERATOR gn_pk_service;
+SET GENERATOR gn_pk_service TO 0;
+CREATE GENERATOR gn_pk_user_service;
+SET GENERATOR gn_pk_user_service TO 0;
+CREATE GENERATOR gn_pk_message;
+SET GENERATOR gn_pk_message TO 0;
+CREATE GENERATOR gn_pk_stat;
+SET GENERATOR gn_pk_stat TO 0;
+CREATE GENERATOR gn_pk_stat_traffic;
+SET GENERATOR gn_pk_stat_traffic TO 0;
+CREATE GENERATOR gn_pk_user_data;
+SET GENERATOR gn_pk_user_data TO 0;
+CREATE GENERATOR gn_pk_allowed_ip;
+SET GENERATOR gn_pk_allowed_ip TO 0;
+CREATE GENERATOR gn_pk_session;
+SET GENERATOR gn_pk_session TO 0;
+CREATE GENERATOR gn_pk_session_log;
+SET GENERATOR gn_pk_session_log TO 0;
+CREATE GENERATOR gn_pk_session_data;
+SET GENERATOR gn_pk_session_data TO 0;
+CREATE GENERATOR gn_pk_parameter;
+SET GENERATOR gn_pk_parameter TO 0;
+CREATE GENERATOR gn_pk_param_log;
+SET GENERATOR gn_pk_param_log TO 0;
+
+
+/*
+ *****************************************************************************
+ * -= Создание ТРИГГЕРОВ =-
+ *****************************************************************************
+ */
+
+SET TERM !! ;
+CREATE TRIGGER tr_admin_bi FOR tb_admins
+ACTIVE BEFORE INSERT POSITION 0
+AS
+BEGIN
+ IF (new.pk_admin IS NULL)
+ THEN new.pk_admin = GEN_ID(gn_pk_admin, 1);
+END !!
+SET TERM ; !!
+
+/*set term !! ;
+create trigger tr_tariff_bi for tb_tariffs active
+before insert position 0
+as
+begin
+ if (new.pk_tariff is null)
+ then new.pk_tariff = gen_id(gn_pk_tariff, 1);
+end !!
+set term ; !!*/
+
+set term !! ;
+create trigger tr_tariff_param_bi for tb_tariffs_params active
+before insert position 0
+as
+begin
+ if (new.pk_tariff_param is null)
+ then new.pk_tariff_param = gen_id(gn_pk_tariff_param, 1);
+end !!
+set term ; !!
+
+set term !! ;
+create trigger tr_corporation_bi for tb_corporations active
+before insert position 0
+as
+begin
+ if (new.pk_corporation is null)
+ then new.pk_corporation = gen_id(gn_pk_corporation, 1);
+end !!
+set term ; !!
+
+/*set term !! ;
+create trigger tr_user_bi for tb_users active
+before insert position 0
+as
+begin
+ if (new.pk_user is null)
+ then new.pk_user = gen_id(gn_pk_user, 1);
+end !!
+set term ; !!*/
+
+set term !! ;
+create trigger tr_detail_stat_bi for tb_detail_stats active
+before insert position 0
+as
+begin
+ if (new.pk_detail_stat is null)
+ then new.pk_detail_stat = gen_id(gn_pk_detail_stat, 1);
+end !!
+set term ; !!
+
+set term !! ;
+create trigger tr_service_bi for tb_services active
+before insert position 0
+as
+begin
+ if (new.pk_service is null)
+ then new.pk_service = gen_id(gn_pk_service, 1);
+end !!
+set term ; !!
+
+set term !! ;
+create trigger tr_user_service_bi for tb_users_services active
+before insert position 0
+as
+begin
+ if (new.pk_user_service is null)
+ then new.pk_user_service = gen_id(gn_pk_user_service, 1);
+end !!
+set term ; !!
+
+/*set term !! ;
+create trigger tr_message_bi for tb_messages active
+before insert position 0
+as
+begin
+ if (new.pk_message is null)
+ then new.pk_message = gen_id(gn_pk_message, 1);
+end !!
+set term ; !!*/
+
+/*set term !! ;
+create trigger tr_stat_bi for tb_stats active
+before insert position 0
+as
+begin
+ if (new.pk_stat is null)
+ then new.pk_stat = gen_id(gn_pk_stat, 1);
+end !!
+set term ; !!*/
+
+set term !! ;
+create trigger tr_stat_traffic_bi for tb_stats_traffic active
+before insert position 0
+as
+begin
+ if (new.pk_stat_traffic is null)
+ then new.pk_stat_traffic = gen_id(gn_pk_stat_traffic, 1);
+end !!
+set term ; !!
+
+set term !! ;
+create trigger tr_user_data_bi for tb_users_data active
+before insert position 0
+as
+begin
+ if (new.pk_user_data is null)
+ then new.pk_user_data = gen_id(gn_pk_user_data, 1);
+end !!
+set term ; !!
+
+set term !! ;
+create trigger tr_allowed_ip_bi for tb_allowed_ip active
+before insert position 0
+as
+begin
+ if (new.pk_allowed_ip is null)
+ then new.pk_allowed_ip = gen_id(gn_pk_allowed_ip, 1);
+end !!
+set term ; !!
+
+/*set term !! ;
+create trigger tr_session_log_bi for tb_sessions_log active
+before insert position 0
+as
+begin
+ if (new.pk_session_log is null)
+ then new.pk_session_log = gen_id(gn_pk_session_log, 1);
+end !!
+set term ; !!*/
+
+set term !! ;
+create trigger tr_session_data_bi for tb_sessions_data active
+before insert position 0
+as
+begin
+ if (new.pk_session_data is null)
+ then new.pk_session_data = gen_id(gn_pk_session_data, 1);
+end !!
+set term ; !!
+
+set term !! ;
+create trigger tr_parameter_bi for tb_parameters active
+before insert position 0
+as
+begin
+ if (new.pk_parameter is null)
+ then new.pk_parameter = gen_id(gn_pk_parameter, 1);
+end !!
+set term ; !!
+
+set term !! ;
+create trigger tr_param_log_bi for tb_params_log active
+before insert position 0
+as
+begin
+ if (new.pk_param_log is null)
+ then new.pk_param_log = gen_id(gn_pk_param_log, 1);
+end !!
+set term ; !!
+
+/*
+ *****************************************************************************
+ * -= Создание stored procedure =-
+ *****************************************************************************
+ */
+
+/*
+ * Add a message returning it's ID
+ */
+set term !! ;
+create procedure sp_add_message(pk_message integer, login varchar(32), ver integer, msg_type integer, last_send_time integer, creation_time integer, show_time integer, repeat integer, repeat_period integer, msg_text varchar(256))
+returns(res integer)
+as
+begin
+ if (:pk_message is null) then
+ begin
+ pk_message = gen_id(gn_pk_message, 1);
+ insert into tb_messages values (:pk_message,
+ (select pk_user from tb_users where name = :login),
+ :ver,
+ :msg_type,
+ :last_send_time,
+ :creation_time,
+ :show_time,
+ :repeat,
+ :repeat_period,
+ :msg_text);
+ end
+ else
+ begin
+ update tb_messages set fk_user = (select pk_user from tb_users where name = :login),
+ ver = :ver,
+ msg_type = :msg_type,
+ last_send_time = :last_send_time,
+ creation_time = :creation_time,
+ show_time = :show_time,
+ repeat = :repeat_period,
+ repeat_period = :repeat_period,
+ msg_text = :msg_text
+ where pk_message = :pk_message;
+ end
+ res = :pk_message;
+end !!
+set term ; !!
+
+set term !! ;
+create procedure sp_delete_service(name varchar(32))
+as
+declare variable pk_service integer;
+begin
+ select pk_service from tb_services where name = :name into pk_service;
+ if (pk_service is not null) then
+ begin
+ delete from tb_users_services where fk_service = :pk_service;
+ delete from tb_services where pk_service = :pk_service;
+ end
+end !!
+set term ; !!
+
+set term !! ;
+create procedure sp_add_tariff(name varchar(32), dirs integer)
+as
+declare variable pk_tariff integer;
+begin
+ pk_tariff = gen_id(gn_pk_tariff, 1);
+ insert into tb_tariffs (pk_tariff, name, fee, free, passive_cost, traff_type) values (:pk_tariff, :name, 0, 0, 0, 0);
+ while (dirs > 0) do
+ begin
+ insert into tb_tariffs_params (fk_tariff, dir_num, price_day_a,
+ price_day_b, price_night_a, price_night_b,
+ threshold, time_day_begins, time_day_ends)
+ values (:pk_tariff, :dirs - 1, 0, 0, 0, 0, 0, '0:0', '0:0');
+ dirs = dirs - 1;
+ end
+end !!
+set term ; !!
+
+set term !! ;
+create procedure sp_delete_tariff(name varchar(32))
+as
+declare variable pk_tariff integer;
+begin
+ select pk_tariff from tb_tariffs where name = :name into pk_tariff;
+ if (pk_tariff is not null) then
+ begin
+ delete from tb_tariffs_params where fk_tariff = :pk_tariff;
+ delete from tb_tariffs where pk_tariff = :pk_tariff;
+ end
+end !!
+set term ; !!
+
+set term !! ;
+create procedure sp_add_user(name varchar(32), dirs integer)
+as
+declare variable pk_user integer;
+declare variable pk_stat integer;
+begin
+ pk_user = gen_id(gn_pk_user, 1);
+ insert into tb_users(pk_user, fk_tariff, fk_tariff_change, fk_corporation, address, always_online, credit, credit_expire, disabled, disabled_detail_stat, email, grp, note, passive, passwd, phone, name, real_name) values (:pk_user, NULL, NULL, NULL, '', 0, 0, 'now', 0, 0, '', '_', '', 0, '', '', :name, '');
+ pk_stat = gen_id(gn_pk_stat, 1);
+ insert into tb_stats values (:pk_stat, :pk_user, 0, 0, 'now', 0, 'now', 0, 'now');
+ while (dirs > 0) do
+ begin
+ insert into tb_stats_traffic (fk_stat, dir_num, upload, download) values (:pk_stat, :dirs - 1, 0, 0);
+ dirs = dirs - 1;
+ end
+end!!
+set term ; !!
+
+set term !! ;
+create procedure sp_delete_user(name varchar(32))
+as
+declare variable pk_user integer;
+begin
+ select pk_user from tb_users where name = :name into pk_user;
+ if (pk_user is not null) then
+ begin
+ delete from tb_users_services where fk_user = :pk_user;
+ delete from tb_params_log where fk_user = :pk_user;
+ delete from tb_detail_stats where fk_user = :pk_user;
+ delete from tb_stats_traffic where fk_stat in (select pk_stat from tb_stats where fk_user = :pk_user);
+ delete from tb_stats where fk_user = :pk_user;
+ delete from tb_sessions_data where fk_session_log in (select pk_session_log from tb_sessions_log where fk_user = :pk_user);
+ delete from tb_sessions_log where fk_user = :pk_user;
+ delete from tb_allowed_ip where fk_user = :pk_user;
+ delete from tb_users_data where fk_user = :pk_user;
+ delete from tb_messages where fk_user = :pk_user;
+ delete from tb_users where pk_user = :pk_user;
+ end
+end !!
+set term ; !!
+
+set term !! ;
+create procedure sp_append_session_log(name varchar(32), event_time timestamp, event_type char(1), ip integer)
+returns(pk_session_log integer)
+as
+begin
+ pk_session_log = gen_id(gn_pk_session_log, 1);
+ insert into tb_sessions_log (pk_session_log, fk_user, event_time, event_type, ip) values (:pk_session_log, (select pk_user from tb_users where name = :name), :event_time, :event_type, :ip);
+end !!
+set term ; !!
+
+set term !! ;
+create procedure sp_add_stat(name varchar(32), cash numeric(10,6), free_mb numeric(10,6), last_activity_time timestamp, last_cash_add numeric(10,6), last_cash_add_time timestamp, passive_time integer, stats_date date)
+returns(pk_stat integer)
+as
+begin
+ pk_stat = gen_id(gn_pk_stat, 1);
+ insert into tb_stats (pk_stat, fk_user, cash, free_mb, last_activity_time, last_cash_add, last_cash_add_time, passive_time, stats_date) values (:pk_stat, (select pk_user from tb_users where name = :name), :cash, :free_mb, :last_activity_time, :last_cash_add, :last_cash_add_time, :passive_time, :stats_date);
+end !!
+set term ; !!
+
+/*
+ *****************************************************************************
+ * -= Создание администратора =-
+ *****************************************************************************
+ */
+
+insert into tb_admins values(0, 'admin', 'geahonjehjfofnhammefahbbbfbmpkmkmmefahbbbfbmpkmkmmefahbbbfbmpkmk', 1, 1, 1, 1, 1, 1, 1, 1, 1);
+
+/* EOF */
+
--- /dev/null
+/*
+ * DB migration from v00 to v01 (mysql)
+ */
+
+ALTER TABLE users ADD DisabledDetailStat INT(3) DEFAULT 0;
--- /dev/null
+password=geahonjehjfofnhammefahbbbfbmpkmkmmefahbbbfbmpkmkmmefahbbbfbmpkmkaa
+ChgConf=1
+ChgPassword=1
+ChgStat=1
+ChgCash=1
+UsrAddDel=1
+ChgTariff=1
+ChgAdmin=1
--- /dev/null
+Fee=10.000000
+Free=0
+NoDiscount0=1
+NoDiscount1=1
+NoDiscount2=1
+NoDiscount3=1
+NoDiscount4=1
+NoDiscount5=1
+NoDiscount6=1
+NoDiscount7=1
+NoDiscount8=1
+NoDiscount9=1
+PassiveCost=0.000000
+PriceDayA0=0.000000
+PriceDayA1=0.750000
+PriceDayA2=0.000000
+PriceDayA3=0.000000
+PriceDayA4=0.000000
+PriceDayA5=0.000000
+PriceDayA6=0.000000
+PriceDayA7=0.000000
+PriceDayA8=0.000000
+PriceDayA9=0.000000
+PriceDayB0=0.000000
+PriceDayB1=0.750000
+PriceDayB2=0.000000
+PriceDayB3=0.000000
+PriceDayB4=0.000000
+PriceDayB5=0.000000
+PriceDayB6=0.000000
+PriceDayB7=0.000000
+PriceDayB8=0.000000
+PriceDayB9=0.000000
+PriceNightA0=1.000000
+PriceNightA1=0.000000
+PriceNightA2=0.000000
+PriceNightA3=0.000000
+PriceNightA4=0.000000
+PriceNightA5=0.000000
+PriceNightA6=0.000000
+PriceNightA7=0.000000
+PriceNightA8=0.000000
+PriceNightA9=0.000000
+PriceNightB0=1.000000
+PriceNightB1=0.000000
+PriceNightB2=0.000000
+PriceNightB3=0.000000
+PriceNightB4=0.000000
+PriceNightB5=0.000000
+PriceNightB6=0.000000
+PriceNightB7=0.000000
+PriceNightB8=0.000000
+PriceNightB9=0.000000
+SinglePrice0=1
+SinglePrice1=1
+SinglePrice2=0
+SinglePrice3=0
+SinglePrice4=0
+SinglePrice5=0
+SinglePrice6=0
+SinglePrice7=0
+SinglePrice8=0
+SinglePrice9=0
+Threshold0=0
+Threshold1=0
+Threshold2=0
+Threshold3=0
+Threshold4=0
+Threshold5=0
+Threshold6=0
+Threshold7=0
+Threshold8=0
+Threshold9=0
+Time0=0:0-0:0
+Time1=0:0-0:0
+Time2=0:0-0:0
+Time3=0:0-0:0
+Time4=0:0-0:0
+Time5=0:0-0:0
+Time6=0:0-0:0
+Time7=0:0-0:0
+Time8=0:0-0:0
+Time9=0:0-0:0
+TraffType=up+down
--- /dev/null
+Address=
+AlwaysOnline=0
+CreationTime=1123487395
+Credit=0.000000
+CreditExpire=0
+Down=0
+Email=
+Group=
+Iface=eth1
+IP=192.168.1.1
+Note=
+Passive=0
+Password=123456
+Phone=
+RealName=
+Tariff=tariff
+TariffChange=
+Userdata0=
+Userdata1=
--- /dev/null
+Cash=10.000000
+D0=0
+D1=0
+D2=0
+D3=0
+D4=0
+D5=0
+D6=0
+D7=0
+D8=0
+D9=0
+FreeMb=0.000000
+LastActivityTime=0
+LastCashAdd=0
+LastCashAddTime=0
+PassiveTime=0
+U0=0
+U1=0
+U2=0
+U3=0
+U4=0
+U5=0
+U6=0
+U7=0
+U8=0
+U9=0
--- /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>
+ */
+
+ /*
+ $Revision: 1.124 $
+ $Date: 2010/10/04 20:19:12 $
+ $Author: faust $
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <dlfcn.h>
+#include <signal.h>
+#include <fcntl.h>
+
+#include <fstream>
+#include <vector>
+#include <set>
+#include <list>
+
+#include "settings.h"
+#include "user.h"
+#include "users.h"
+#include "admins.h"
+#include "common.h"
+#include "traffcounter.h"
+#include "base_plugin.h"
+#include "stg_logger.h"
+#include "stg_timer.h"
+#include "plugin_runner.h"
+#include "script_executer.h"
+#include "conffiles.h"
+#include "version.h"
+#include "store_loader.h"
+#include "pidfile.h"
+#include "eventloop.h"
+
+using namespace std;
+uint32_t eip;
+
+#ifdef DEBUG
+ #define MAIN_DEBUG (1)
+ #define NO_DAEMON (1)
+#endif
+
+#define START_FILE "/._ST_ART_ED_"
+
+static bool needRulesReloading = false;
+static bool childExited = false;
+//static pid_t executerPid;
+set<pid_t> executersPid;
+static pid_t stgChildPid;
+
+#include "pinger.h"
+
+//-----------------------------------------------------------------------------
+bool StartModCmp(const PLUGIN_RUNNER & lhs, const PLUGIN_RUNNER & rhs)
+{
+return lhs.GetStartPosition() < rhs.GetStartPosition();
+}
+//-----------------------------------------------------------------------------
+bool StopModCmp(const PLUGIN_RUNNER & lhs, const PLUGIN_RUNNER & rhs)
+{
+return lhs.GetStopPosition() > rhs.GetStopPosition();
+}
+//-----------------------------------------------------------------------------
+class STG_STOPPER
+{
+public:
+ STG_STOPPER() { nonstop = true; }
+ bool GetStatus() { return nonstop; };
+ #ifdef NO_DAEMON
+ void Stop(const char * __file__, int __line__)
+ #else
+ void Stop(const char *, int)
+ #endif
+ {
+ #ifdef NO_DAEMON
+ printfd(__FILE__, "Stg stopped at %s:%d\n", __file__, __line__);
+ #endif
+ nonstop = false;
+ }
+private:
+ bool nonstop;
+};
+//-----------------------------------------------------------------------------
+STG_STOPPER nonstop;
+//-----------------------------------------------------------------------------
+static void StartTimer()
+{
+STG_LOGGER & WriteServLog = GetStgLogger();
+
+if (RunStgTimer())
+ {
+ WriteServLog("Cannot start timer. Fatal.");
+ //printfd(__FILE__, "Cannot start timer. Fatal.\n");
+ exit(1);
+ }
+else
+ {
+ WriteServLog("Timer thread started successfully.");
+ //printfd(__FILE__, "Timer thread started successfully.\n");
+ }
+}
+//-----------------------------------------------------------------------------
+void CatchPROF(int)
+{
+/*STG_LOGGER & WriteServLog = GetStgLogger();
+WriteServLog("CatchPROF");*/
+}
+//-----------------------------------------------------------------------------
+void CatchUSR1(int)
+{
+
+}
+//-----------------------------------------------------------------------------
+void CatchTERM(int sig)
+{
+/*
+ *Function Name:CatchINT
+ *Parameters: sig_num - ÎÏÍÅÒ ÓÉÇÎÁÌÁ
+ *Description: ïÂÒÁÂÏÔÞÉË ÓÉÇÎÁÌÁ INT
+ *Returns: îÉÞÅÇÏ
+ */
+STG_LOGGER & WriteServLog = GetStgLogger();
+WriteServLog("Shutting down... %d", sig);
+
+//nonstop = false;
+nonstop.Stop(__FILE__, __LINE__);
+
+struct sigaction newsa, oldsa;
+sigset_t sigmask;
+
+sigemptyset(&sigmask);
+sigaddset(&sigmask, SIGTERM);
+newsa.sa_handler = SIG_IGN;
+newsa.sa_mask = sigmask;
+newsa.sa_flags = 0;
+sigaction(SIGTERM, &newsa, &oldsa);
+
+sigemptyset(&sigmask);
+sigaddset(&sigmask, SIGINT);
+newsa.sa_handler = SIG_IGN;
+newsa.sa_mask = sigmask;
+newsa.sa_flags = 0;
+sigaction(SIGINT, &newsa, &oldsa);
+}
+//-----------------------------------------------------------------------------
+void CatchPIPE(int)
+{
+STG_LOGGER & WriteServLog = GetStgLogger();
+WriteServLog("Broken pipe!");
+}
+//-----------------------------------------------------------------------------
+void CatchHUP(int)
+{
+needRulesReloading = true;
+}
+//-----------------------------------------------------------------------------
+void CatchCHLD(int)
+{
+int status;
+pid_t childPid;
+childPid = waitpid(-1, &status, WNOHANG);
+
+set<pid_t>::iterator pid;
+pid = executersPid.find(childPid);
+if (pid != executersPid.end())
+ {
+ executersPid.erase(pid);
+ if (executersPid.empty() && nonstop.GetStatus())
+ {
+ nonstop.Stop(__FILE__, __LINE__);
+ }
+ }
+if (childPid == stgChildPid)
+ {
+ childExited = true;
+ }
+}
+//-----------------------------------------------------------------------------
+void CatchSEGV(int, siginfo_t *, void *)
+{
+/*char fileName[50];
+sprintf(fileName, "/tmp/stg_segv.%d", getpid());
+FILE * f = fopen(fileName, "wt");
+if (f)
+ {
+ fprintf(f, "\nSignal info:\n~~~~~~~~~~~~\n");
+ fprintf(f, "numb:\t %d (%d)\n", sinfo->si_signo, sig);
+ fprintf(f, "errn:\t %d\n", sinfo->si_errno);
+ fprintf(f, "code:\t %d ", sinfo->si_code);
+
+ switch (sinfo->si_code)
+ {
+ case SEGV_MAPERR:
+ fprintf(f, "(SEGV_MAPERR - address not mapped to object)\n");
+ break;
+
+ case SEGV_ACCERR:
+ fprintf(f, "(SEGV_ACCERR - invalid permissions for mapped object)\n");
+ break;
+
+ default:
+ fprintf(f, "???\n");
+ }
+
+ fprintf(f, "addr:\t 0x%.8X\n",
+ (unsigned int)sinfo->si_addr);
+
+ Dl_info dlinfo;
+ //asm("movl %eip, eip");
+ if (dladdr((void*)CatchCHLD, &dlinfo))
+ {
+ fprintf(f, "SEGV point: %s %s\n", dlinfo.dli_fname, dlinfo.dli_sname);
+ }
+ else
+ {
+ fprintf(f, "Cannot find SEGV point\n");
+ }
+
+ fclose(f);
+ }
+
+struct sigaction segv_action, segv_action_old;
+
+segv_action.sa_handler = SIG_DFL;
+segv_action.sa_sigaction = NULL;
+segv_action.sa_flags = SA_SIGINFO;
+segv_action.sa_restorer = NULL;
+
+sigaction(SIGSEGV, &segv_action, &segv_action_old);*/
+}
+//-----------------------------------------------------------------------------
+static void SetSignalHandlers()
+{
+struct sigaction newsa, oldsa;
+sigset_t sigmask;
+///////
+sigemptyset(&sigmask);
+sigaddset(&sigmask, SIGTERM);
+newsa.sa_handler = CatchTERM;
+newsa.sa_mask = sigmask;
+newsa.sa_flags = 0;
+sigaction(SIGTERM, &newsa, &oldsa);
+///////
+sigemptyset(&sigmask);
+sigaddset(&sigmask, SIGUSR1);
+newsa.sa_handler = CatchUSR1;
+newsa.sa_mask = sigmask;
+newsa.sa_flags = 0;
+sigaction(SIGUSR1, &newsa, &oldsa);
+///////
+sigemptyset(&sigmask);
+sigaddset(&sigmask, SIGINT);
+newsa.sa_handler = CatchTERM;
+newsa.sa_mask = sigmask;
+newsa.sa_flags = 0;
+sigaction(SIGINT, &newsa, &oldsa);
+/*///////
+sigemptyset(&sigmask);
+sigaddset(&sigmask, SIGPROF);
+newsa.sa_handler = CatchPROF;
+newsa.sa_mask = sigmask;
+newsa.sa_flags = 0;
+sigaction(SIGPROF, &newsa, &oldsa);*/
+//////
+sigemptyset(&sigmask);
+sigaddset(&sigmask, SIGPIPE);
+newsa.sa_handler = CatchPIPE;
+newsa.sa_mask = sigmask;
+newsa.sa_flags = 0;
+sigaction(SIGPIPE, &newsa, &oldsa);
+//////
+sigemptyset(&sigmask);
+sigaddset(&sigmask, SIGHUP);
+newsa.sa_handler = CatchHUP;
+newsa.sa_mask = sigmask;
+newsa.sa_flags = 0;
+sigaction(SIGHUP, &newsa, &oldsa);
+//////
+sigemptyset(&sigmask);
+sigaddset(&sigmask, SIGCHLD);
+newsa.sa_handler = CatchCHLD;
+newsa.sa_mask = sigmask;
+newsa.sa_flags = 0;
+sigaction(SIGCHLD, &newsa, &oldsa);
+
+/*newsa.sa_handler = NULL;
+newsa.sa_sigaction = CatchSEGV;
+newsa.sa_flags = SA_SIGINFO;
+newsa.sa_restorer = NULL;
+sigaction(SIGSEGV, &newsa, &oldsa);*/
+
+return;
+}
+//-----------------------------------------------------------------------------
+int StartScriptExecuter(char * procName, int msgKey, int * msgID, SETTINGS * settings)
+{
+STG_LOGGER & WriteServLog = GetStgLogger();
+
+if (*msgID == -11) // If msgID == -11 - first call. Create queue
+ {
+ for (int i = 0; i < 2; i++)
+ {
+ //WriteServLog("Creating queue with key=%d ...", msgKey);
+ *msgID = msgget(msgKey, IPC_CREAT | IPC_EXCL | 0600);
+
+ if (*msgID == -1)
+ {
+ *msgID = msgget(msgKey, 0);
+ if (*msgID == -1)
+ {
+ WriteServLog("Message queue not created.");
+ return -1;
+ }
+ else
+ {
+ msgctl(*msgID, IPC_RMID, NULL);
+ //printfd(__FILE__, "Queue removed!");
+ }
+ }
+ else
+ {
+ WriteServLog("Message queue created successfully. msgKey=%d msgID=%d", msgKey, *msgID);
+ break;
+ }
+ }
+ }
+
+pid_t executerPid = fork();
+
+switch (executerPid)
+ {
+ case -1: // ìÁÖÁ
+ WriteServLog("Fork error!");
+ return -1;
+
+ case 0: // ðÏÔÏÍÏË
+ //close(0);
+ //close(1);
+ //close(2);
+ //setsid();
+ delete settings;
+ Executer(msgKey, *msgID, executerPid, procName);
+ return 1;
+
+ default: // ïÓÎÏ×ÎÏÊ ÐÒÏÃÅÓÓ
+ if (executersPid.empty()) {
+ Executer(msgKey, *msgID, executerPid, NULL);
+ }
+ executersPid.insert(executerPid);
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+#ifndef NO_DAEMON
+int ForkAndWait(const string & confDir)
+#else
+int ForkAndWait(const string &)
+#endif
+{
+#ifndef NO_DAEMON
+stgChildPid = fork();
+string startFile = confDir + START_FILE;
+unlink(startFile.c_str());
+
+switch (stgChildPid)
+ {
+ case -1: // ìÁÖÁ
+ return -1;
+ break;
+
+ case 0: // ðÏÔÏÍÏË
+ //close(0);
+ close(1);
+ close(2);
+ setsid();
+ break;
+
+ default: // ïÓÎÏ×ÎÏÊ ÐÒÏÃÅÓÓ
+ for (int i = 0; i < 120 * 5; i++)
+ {
+ if (access(startFile.c_str(), F_OK) == 0)
+ {
+ //printf("Fork successfull. Exit.\n");
+ unlink(startFile.c_str());
+ exit(0);
+ }
+
+ if (childExited)
+ {
+ unlink(startFile.c_str());
+ exit(1);
+ }
+ usleep(200000);
+ }
+ unlink(startFile.c_str());
+ exit(1);
+ break;
+ }
+#endif
+return 0;
+}
+//-----------------------------------------------------------------------------
+void KillExecuters()
+{
+set<pid_t>::iterator pid;
+pid = executersPid.begin();
+while (pid != executersPid.end())
+ {
+ printfd(__FILE__, "KillExecuters pid=%d\n", *pid);
+ kill(*pid, SIGUSR1);
+ ++pid;
+ }
+}
+//-----------------------------------------------------------------------------
+int main(int argc, char * argv[])
+{
+
+/*
+ Initialization order:
+ - Logger
+ - Stg timer
+ - Settings
+ - Plugins
+ - Plugins settings
+ - Read Admins
+ - Read Tariffs
+ - Read Users
+ - Start Users
+ - Start Traffcounter
+ - Start Plugins
+ - Start pinger
+ - Set signal nandlers
+ - Fork and exit
+ * */
+
+SETTINGS * settings = NULL;
+BASE_STORE * dataStore = NULL;
+TARIFFS * tariffs = NULL;
+ADMINS * admins = NULL;
+USERS * users = NULL;
+TRAFFCOUNTER * traffCnt = NULL;
+int msgID = -11;
+
+ {
+ STG_LOGGER & WriteServLog = GetStgLogger();
+ WriteServLog.SetLogFileName("/var/log/stargazer.log");
+ }
+
+vector<MODULE_SETTINGS> modSettings;
+list<PLUGIN_RUNNER> modules;
+
+list<PLUGIN_RUNNER>::iterator modIter;
+
+if (getuid())
+ {
+ printf("You must be root. Exit.\n");
+ exit(1);
+ }
+
+if (argc == 2)
+ settings = new SETTINGS(argv[1]);
+else
+ settings = new SETTINGS();
+
+if (settings->ReadSettings())
+ {
+ //printfd(__FILE__, "ReadSettings error.\n");
+ STG_LOGGER & WriteServLog = GetStgLogger();
+
+ if (settings->GetLogFileName() != "")
+ WriteServLog.SetLogFileName(settings->GetLogFileName());
+
+ WriteServLog("ReadSettings error. %s", settings->GetStrError().c_str());
+ exit(1);
+ }
+
+#ifndef NO_DAEMON
+string startFile(settings->GetConfDir() + START_FILE);
+#endif
+
+//SetSignalHandlers();
+if (ForkAndWait(settings->GetConfDir()) < 0)
+ {
+ STG_LOGGER & WriteServLog = GetStgLogger();
+ WriteServLog("Fork error!");
+ exit(1);
+ }
+
+STG_LOGGER & WriteServLog = GetStgLogger();
+WriteServLog.SetLogFileName(settings->GetLogFileName());
+WriteServLog("Stg v. %s", SERVER_VERSION);
+
+for (int i = 0; i < settings->GetExecutersNum(); i++)
+ {
+ int ret = StartScriptExecuter(argv[0], settings->GetExecMsgKey(), &msgID, settings);
+ if (ret < 0)
+ {
+ STG_LOGGER & WriteServLog = GetStgLogger();
+ WriteServLog("Start Script Executer error!");
+ //goto exitLbl;
+ return 1;
+ }
+ if (ret == 1)
+ {
+ // Stopping child
+ return 0;
+ }
+ }
+
+PIDFile pidFile(settings->GetPIDFileName());
+
+StartTimer();
+WaitTimer();
+if (!IsStgTimerRunning())
+ {
+ printfd(__FILE__, "Timer thread not started in 1 sec!\n");
+ WriteServLog("Timer thread not started in 1 sec!");
+ }
+
+EVENT_LOOP & loop(EVENT_LOOP_SINGLETON::GetInstance());
+
+STORE_LOADER storeLoader(*settings);
+if (storeLoader.Load())
+ {
+ WriteServLog("Storage plugin: '%s'", storeLoader.GetStrError().c_str());
+ goto exitLblNotStarted;
+ }
+
+if (loop.Start())
+ {
+ WriteServLog("Event loop not started.");
+ goto exitLblNotStarted;
+ }
+
+dataStore = storeLoader.GetStore();
+WriteServLog("Storage plugin: %s. Loading successfull.", dataStore->GetVersion().c_str());
+
+tariffs = new TARIFFS(dataStore);
+admins = new ADMINS(dataStore);
+users = new USERS(settings, dataStore, tariffs, admins->GetSysAdmin());
+traffCnt = new TRAFFCOUNTER(users, tariffs, settings->GetRulesFileName());
+traffCnt->SetMonitorDir(settings->GetMonitorDir());
+//tariffs->SetUsers(users);
+
+modSettings = settings->GetModulesSettings();
+
+for (unsigned i = 0; i < modSettings.size(); i++)
+ {
+ string modulePath = settings->GetModulesPath();
+ modulePath += "/mod_";
+ modulePath += modSettings[i].moduleName;
+ modulePath += ".so";
+ printfd(__FILE__, "Module: %s\n", modulePath.c_str());
+ modules.push_back(
+ PLUGIN_RUNNER(modulePath,
+ modSettings[i],
+ admins,
+ tariffs,
+ users,
+ traffCnt,
+ dataStore,
+ settings)
+ );
+ }
+
+modIter = modules.begin();
+
+while (modIter != modules.end())
+ {
+ //Loading modules
+ if (modIter->Load())
+ {
+ WriteServLog("Error: %s",
+ modIter->GetStrError().c_str());
+ goto exitLblNotStarted;
+ }
+ ++modIter;
+ }
+
+//Start section
+if (users->Start())
+ {
+ goto exitLblNotStarted;
+ }
+WriteServLog("Users started successfully.");
+
+if (traffCnt->Start())
+ {
+ goto exitLblNotStarted;
+ }
+WriteServLog("Traffcounter started successfully.");
+
+//Sort by start order
+modules.sort(StartModCmp);
+modIter = modules.begin();
+
+while (modIter != modules.end())
+ {
+ if (modIter->Start())
+ {
+ WriteServLog("Error: %s",
+ modIter->GetStrError().c_str());
+ //printfd(__FILE__, "Error: %s\n", capRunner.GetStrError().c_str());
+ goto exitLbl;
+ }
+ WriteServLog("Module: \'%s\'. Start successfull. %d", modIter->GetPlugin()->GetVersion().c_str(),
+ modIter->GetPlugin()->GetStartPosition());
+ ++modIter;
+ }
+SetSignalHandlers();
+
+srandom(stgTime);
+
+/*
+ * Note that an implementation in which nice returns the new nice value
+ * can legitimately return -1. To reliably detect an error, set
+ * errno to 0 before the call, and check its value when nice returns -1.
+ *
+ *
+ * (c) man 2 nice
+ */
+errno = 0;
+if (nice(-19) && errno) {
+ printfd(__FILE__, "nice failed: '%s'\n", strerror(errno));
+ WriteServLog("nice failed: '%s'", strerror(errno));
+}
+
+WriteServLog("Stg started successfully.");
+WriteServLog("+++++++++++++++++++++++++++++++++++++++++++++");
+
+#ifndef NO_DAEMON
+creat(startFile.c_str(), S_IRUSR);
+#endif
+
+//*a_kill_it = 0;
+
+while (nonstop.GetStatus())
+ {
+ if (needRulesReloading)
+ {
+ needRulesReloading = false;
+ traffCnt->Reload();
+
+ modIter = modules.begin();
+ for (; modIter != modules.end(); ++modIter)
+ {
+ if (modIter->Reload())
+ {
+ WriteServLog("Error reloading %s ('%s')", modIter->GetPlugin()->GetVersion().c_str(),
+ modIter->GetStrError().c_str());
+ printfd(__FILE__, "Error reloading %s ('%s')\n", modIter->GetPlugin()->GetVersion().c_str(),
+ modIter->GetStrError().c_str());
+ }
+ }
+ }
+ stgUsleep(100000);
+ }
+
+exitLbl:
+
+WriteServLog("+++++++++++++++++++++++++++++++++++++++++++++");
+
+//Sort by start order
+modules.sort(StopModCmp);
+modIter = modules.begin();
+while (modIter != modules.end())
+ {
+ std::string name = modIter->GetFileName();
+ printfd(__FILE__, "Stopping module '%s'\n", name.c_str());
+ if (modIter->Stop())
+ {
+ WriteServLog("Module \'%s\': Error: %s",
+ modIter->GetPlugin()->GetVersion().c_str(),
+ modIter->GetStrError().c_str());
+ printfd(__FILE__, "Failed to stop module '%s'\n", name.c_str());
+ //printfd(__FILE__, "Error: %s\n", capRunner.GetStrError().c_str());
+ //goto exitLbl;
+ }
+ WriteServLog("Module: \'%s\'. Stop successfull.", modIter->GetPlugin()->GetVersion().c_str());
+ ++modIter;
+ }
+
+if (loop.Stop())
+ {
+ WriteServLog("Event loop not stopped.");
+ }
+
+exitLblNotStarted:
+
+/*modIter = modules.begin();
+while (modIter != modules.end())
+ {
+ std::string name = modIter->GetFileName();
+ printfd(__FILE__, "Unloading module '%s'\n", name.c_str());
+ if (modIter->Unload())
+ {
+ WriteServLog("Module \'%s\': Error: %s",
+ name.c_str(),
+ modIter->GetStrError().c_str());
+ printfd(__FILE__, "Failed to unload module '%s'\n", name.c_str());
+ }
+ ++modIter;
+ }*/
+
+if (traffCnt)
+ {
+ traffCnt->Stop();
+ WriteServLog("Traffcounter: Stop successfull.");
+ }
+
+if (users)
+ {
+ users->Stop();
+ WriteServLog("Users: Stop successfull.");
+ }
+
+sleep(1);
+int res = msgctl(msgID, IPC_RMID, NULL);
+if (res)
+ WriteServLog("Queue was not removed. id=%d", msgID);
+else
+ WriteServLog("Queue removed successfully.");
+
+/*struct sigaction newsa, oldsa;
+sigset_t sigmask;
+sigemptyset(&sigmask);
+sigaddset(&sigmask, SIGCHLD);
+newsa.sa_handler = SIG_IGN;
+newsa.sa_mask = sigmask;
+newsa.sa_flags = 0;
+sigaction(SIGCHLD, &newsa, &oldsa);*/
+
+KillExecuters();
+
+StopStgTimer();
+WriteServLog("StgTimer: Stop successfull.");
+
+WriteServLog("Stg stopped successfully.");
+sleep(1);
+WriteServLog("---------------------------------------------");
+
+delete traffCnt;
+delete users;
+delete admins;
+delete tariffs;
+delete settings;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
+
--- /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>
+ */
+
+/*
+ $Revision: 1.2 $
+ $Date: 2009/06/09 09:07:32 $
+ $Author: faust $
+ */
+
+/*
+ * An implementation of RAII pid-file writer
+ */
+
+#include <fstream>
+#include <unistd.h>
+
+#include "pidfile.h"
+
+PIDFile::PIDFile(const std::string & fn)
+ : fileName(fn)
+{
+if (fileName != "")
+ {
+ std::ofstream pf(fileName.c_str());
+ pf << getpid() << std::endl;
+ pf.close();
+ }
+}
+
+PIDFile::~PIDFile()
+{
+if (fileName != "")
+ {
+ unlink(fileName.c_str());
+ }
+}
--- /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>
+ */
+
+/*
+ * Header file for RAII pid-file writer
+ */
+
+/*
+ $Revision: 1.2 $
+ $Date: 2009/06/09 09:07:32 $
+ $Author: faust $
+ */
+
+#ifndef __PID_FILE_H__
+#define __PID_FILE_H__
+
+#include <string>
+
+class PIDFile {
+public:
+ PIDFile(const std::string & fn);
+ ~PIDFile();
+private:
+ std::string fileName;
+};
+
+#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>
+ */
+
+/*
+ $Revision: 1.17 $
+ $Date: 2010/09/13 05:52:46 $
+ $Author: faust $
+ */
+
+#include <dlfcn.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include "plugin_runner.h"
+#include "common.h"
+#include "conffiles.h"
+
+//-----------------------------------------------------------------------------
+PLUGIN_RUNNER::PLUGIN_RUNNER(const string & pFileName,
+ const MODULE_SETTINGS & ms,
+ ADMINS * a,
+ TARIFFS * t,
+ USERS * u,
+ TRAFFCOUNTER * tc,
+ BASE_STORE * st,
+ const SETTINGS * s)
+ : pluginFileName(pFileName),
+ pluginSettingFileName(),
+ plugin(NULL),
+ isPluginLoaded(false),
+ errorStr(),
+ libHandle(NULL),
+ isRunning(false),
+ admins(a),
+ tariffs(t),
+ users(u),
+ store(st),
+ traffCnt(tc),
+ stgSettings(s),
+ modSettings(ms)
+{
+}
+//-----------------------------------------------------------------------------
+PLUGIN_RUNNER::PLUGIN_RUNNER(const PLUGIN_RUNNER & rvalue)
+ : pluginFileName(rvalue.pluginFileName),
+ pluginSettingFileName(rvalue.pluginSettingFileName),
+ plugin(rvalue.plugin),
+ isPluginLoaded(rvalue.isPluginLoaded),
+ errorStr(rvalue.errorStr),
+ libHandle(rvalue.libHandle),
+ isRunning(rvalue.isRunning),
+ admins(rvalue.admins),
+ tariffs(rvalue.tariffs),
+ users(rvalue.users),
+ store(rvalue.store),
+ traffCnt(rvalue.traffCnt),
+ stgSettings(rvalue.stgSettings),
+ modSettings(rvalue.modSettings)
+{
+}
+//-----------------------------------------------------------------------------
+PLUGIN_RUNNER & PLUGIN_RUNNER::operator=(const PLUGIN_RUNNER & rvalue)
+{
+pluginFileName = rvalue.pluginFileName;
+pluginSettingFileName = rvalue.pluginSettingFileName;
+plugin = rvalue.plugin;
+isPluginLoaded = rvalue.isPluginLoaded;
+errorStr = rvalue.errorStr;
+libHandle = rvalue.libHandle;
+isRunning = rvalue.isRunning;
+admins = rvalue.admins;
+tariffs = rvalue.tariffs;
+users = rvalue.users;
+store = rvalue.store;
+traffCnt = rvalue.traffCnt;
+stgSettings = rvalue.stgSettings;
+modSettings = rvalue.modSettings;
+
+return *this;
+}
+//-----------------------------------------------------------------------------
+PLUGIN_RUNNER::~PLUGIN_RUNNER()
+{
+if (isPluginLoaded)
+ {
+ Unload();
+ }
+
+isPluginLoaded = 0;
+}
+//-----------------------------------------------------------------------------
+BASE_PLUGIN * PLUGIN_RUNNER::GetPlugin()
+{
+return plugin;
+}
+//-----------------------------------------------------------------------------
+int PLUGIN_RUNNER::Start()
+{
+if (!isPluginLoaded)
+ if (Load())
+ return -1;
+
+plugin->SetTariffs(tariffs);
+plugin->SetAdmins(admins);
+plugin->SetUsers(users);
+plugin->SetTraffcounter(traffCnt);
+plugin->SetStore(store);
+plugin->SetStgSettings(stgSettings);
+
+if (plugin->Start())
+ {
+ errorStr = plugin->GetStrError();
+ return -1;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int PLUGIN_RUNNER::Stop()
+{
+plugin->Stop();
+
+//if (Unload())
+// return -1;
+return 0;
+}
+//-----------------------------------------------------------------------------
+int PLUGIN_RUNNER::Reload()
+{
+int res = plugin->Reload();
+errorStr = plugin->GetStrError();
+return res;
+}
+//-----------------------------------------------------------------------------
+bool PLUGIN_RUNNER::IsRunning()
+{
+if (!isPluginLoaded)
+ return false;
+return plugin->IsRunning();
+}
+//-----------------------------------------------------------------------------
+int PLUGIN_RUNNER::Load()
+{
+if (!pluginFileName.size())
+ {
+ errorStr = "Plugin loading failed. No plugin";
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+
+libHandle = dlopen(pluginFileName.c_str(), RTLD_NOW);
+
+if (!libHandle)
+ {
+ errorStr = string("Plugin loading failed. ") + dlerror();
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+
+BASE_PLUGIN * (*GetPlugin)();
+GetPlugin = (BASE_PLUGIN * (*)())dlsym(libHandle, "GetPlugin");
+if (!GetPlugin)
+ {
+ errorStr = string("GetPlugin() not found. ") + dlerror();
+ return -1;
+ }
+plugin = GetPlugin();
+isPluginLoaded++;
+
+if (!plugin)
+ {
+ errorStr = "Plugin was not created!";
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+
+plugin->SetSettings(modSettings);
+printfd(__FILE__, "Plugin %s parsesettings\n", plugin->GetVersion().c_str());
+if (plugin->ParseSettings())
+ {
+ errorStr = "Plugin \'" + plugin->GetVersion() + "\' error: " + plugin->GetStrError();
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int PLUGIN_RUNNER::Unload()
+{
+if (isPluginLoaded)
+ {
+ if (dlclose(libHandle))
+ {
+ errorStr = dlerror();
+ printfd(__FILE__, "Error unloading plugin '%s': '%s'", pluginFileName.c_str(), dlerror());
+ return -1;
+ }
+ isPluginLoaded--;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+const string & PLUGIN_RUNNER::GetStrError() const
+{
+return errorStr;
+}
+//-----------------------------------------------------------------------------
+uint16_t PLUGIN_RUNNER::GetStartPosition() const
+{
+return plugin->GetStartPosition();
+}
+//-----------------------------------------------------------------------------
+uint16_t PLUGIN_RUNNER::GetStopPosition() const
+{
+return plugin->GetStopPosition();
+}
+//-----------------------------------------------------------------------------
+
--- /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>
+ */
+
+/*
+ $Revision: 1.13 $
+ $Date: 2010/03/04 12:22:41 $
+ $Author: faust $
+ */
+
+#ifndef PLUGIN_RUNNER_H
+#define PLUGIN_RUNNER_H
+#include <pthread.h>
+#include <string>
+
+#include "base_plugin.h"
+#include "base_settings.h"
+#include "traffcounter.h"
+#include "tariffs.h"
+#include "admins.h"
+#include "users.h"
+
+using namespace std;
+//-----------------------------------------------------------------------------
+class PLUGIN_RUNNER
+{
+public:
+ PLUGIN_RUNNER(const string & pluginFileName,
+ const MODULE_SETTINGS & ms,
+ ADMINS * admins,
+ TARIFFS * tariffs,
+ USERS * users,
+ TRAFFCOUNTER * tc,
+ BASE_STORE * store,
+ const SETTINGS * s);
+ PLUGIN_RUNNER(const PLUGIN_RUNNER & rvalue);
+ ~PLUGIN_RUNNER();
+
+ PLUGIN_RUNNER & operator=(const PLUGIN_RUNNER & rvalue);
+
+ int Start();
+ int Stop();
+ int Reload();
+ int Restart();
+ bool IsRunning();
+
+ const string & GetStrError() const;
+ BASE_PLUGIN * GetPlugin();
+ const string & GetFileName() const { return pluginFileName; };
+
+ int Load();
+ int Unload();
+
+ uint16_t GetStartPosition() const;
+ uint16_t GetStopPosition() const;
+
+private:
+ string pluginFileName;
+ string pluginSettingFileName;
+
+ BASE_PLUGIN * plugin;
+ int isPluginLoaded;
+ string errorStr;
+
+ void * libHandle;
+ bool isRunning;
+
+ ADMINS * admins;
+ TARIFFS * tariffs;
+ USERS * users;
+ BASE_STORE * store;
+ TRAFFCOUNTER * traffCnt;
+ const SETTINGS * stgSettings;
+ MODULE_SETTINGS modSettings;
+};
+//-----------------------------------------------------------------------------
+#endif //PLUGIN_RUNNER_H
+
+
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.1 2007/09/26 13:55:45 faust Exp $
+###############################################################################
+
+include ../../../Makefile.conf
+
+.PHONY: clean install uninstall
+.PHONY: all $(PLUGINS)
+
+all: $(PLUGINS)
+
+$(PLUGINS):
+ $(MAKE) $(MAKECMDGOALS) -C $@
+
+clean: all
+
+install: all
+
+uninstall: all
+
--- /dev/null
+###############################################################################
+# $Id: Makefile.in,v 1.11 2009/03/03 15:49:35 faust Exp $
+###############################################################################
+
+SEARCH_DIRS = -I $(DIR_INCLUDE)
+
+OBJS = $(notdir $(patsubst %.cpp, %.o, $(patsubst %.c, %.o, $(SRCS))))
+
+LN = ln
+
+CXXFLAGS += -fPIC
+LDFLAGS += -shared -L$(DIR_LIB) -Wl,-rpath,$(PREFIX)/usr/lib/stg
+
+vpath %.so $(DIR_LIB)
+
+all: $(PROG)
+
+$(PROG): $(OBJS) $(STGLIBS)
+ $(CC) $^ $(LDFLAGS) $(LIBS) -o $(PROG)
+ $(LN) -fs "`pwd`/$(PROG)" $(DIR_MOD)/$(PROG)
+
+clean:
+ rm -f deps $(PROG) *.o tags *.*~
+
+install:
+ mkdir -m $(BIN_MODE) -p $(PREFIX)/usr/lib/stg
+ install -m $(BIN_MODE) -o $(OWNER) -s $(PROG) $(PREFIX)/usr/lib/stg/$(PROG)
+
+uninstall:
+ rm -f $(PREFIX)/usr/lib/stg/$(PROG)
+
+ifneq ($(MAKECMDGOALS),clean)
+ifneq ($(MAKECMDGOALS),uninstall)
+-include deps
+endif
+endif
+
+deps: $(SRCS) ../../../../../Makefile.conf
+ @>deps ;\
+ for file in $(SRCS); do\
+ echo "`$(CC) $(CXXFLAGS) $(DEFS) $(SEARCH_DIRS) -MM $$file` Makefile ../../../../../Makefile.conf" >> deps ;\
+ echo -e '\t$$(CC) -c $$< $(CXXFLAGS) $(SEARCH_DIRS) $(DEFS)' >> deps ;\
+ done
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.10 2008/12/04 15:41:03 faust Exp $
+###############################################################################
+
+include ../../../../../Makefile.conf
+
+PROG = mod_auth_ao.so
+
+SRCS = ./ao.cpp
+
+STGLIBS = -lstg_common
+
+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 : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+/*
+$Revision: 1.30 $
+$Date: 2010/03/04 12:29:06 $
+$Author: faust $
+*/
+
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include "ao.h"
+#include "../../../user.h"
+#include "../../../eventloop.h"
+
+class AO_CREATOR
+{
+private:
+ AUTH_AO * ao;
+
+public:
+ AO_CREATOR()
+ : ao(new AUTH_AO())
+ {
+ };
+ ~AO_CREATOR()
+ {
+ delete ao;
+ };
+
+ AUTH_AO * GetPlugin()
+ {
+ return ao;
+ };
+};
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+AO_CREATOR aoc;
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// ëÌÁÓÓ ÄÌÑ ÐÏÉÓËÁ ÀÚÅÒÁ × ÓÐÉÓËÅ ÎÏÔÉÆÉËÁÔÏÒÏ×
+template <typename varType>
+class IS_CONTAINS_USER: public binary_function<varType, user_iter, bool>
+{
+public:
+ bool operator()(varType notifier, user_iter user) const
+ {
+ return notifier.GetUser() == user;
+ };
+};
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+BASE_PLUGIN * GetPlugin()
+{
+return aoc.GetPlugin();
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+const string AUTH_AO::GetVersion() const
+{
+return "Always Online authorizator v.1.0";
+}
+//-----------------------------------------------------------------------------
+AUTH_AO::AUTH_AO()
+{
+isRunning = false;
+}
+//-----------------------------------------------------------------------------
+void AUTH_AO::SetUsers(USERS * u)
+{
+users = u;
+}
+//-----------------------------------------------------------------------------
+void AUTH_AO::SetSettings(const MODULE_SETTINGS & s)
+{
+settings = s;
+}
+//-----------------------------------------------------------------------------
+int AUTH_AO::ParseSettings()
+{
+return 0;
+}
+//-----------------------------------------------------------------------------
+const string & AUTH_AO::GetStrError() const
+{
+return errorStr;
+}
+//-----------------------------------------------------------------------------
+int AUTH_AO::Start()
+{
+GetUsers();
+
+list<user_iter>::iterator users_iter;
+
+onAddUserNotifier.SetAuthorizator(this);
+onDelUserNotifier.SetAuthorizator(this);
+users->AddNotifierUserAdd(&onAddUserNotifier);
+users->AddNotifierUserDel(&onDelUserNotifier);
+
+users_iter = usersList.begin();
+while (users_iter != usersList.end())
+ {
+ UpdateUserAuthorization(*users_iter);
+ ++users_iter;
+ }
+isRunning = true;
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_AO::Stop()
+{
+if (!isRunning)
+ return 0;
+
+users->DelNotifierUserAdd(&onAddUserNotifier);
+users->DelNotifierUserDel(&onDelUserNotifier);
+
+list<user_iter>::iterator users_iter;
+users_iter = usersList.begin();
+while (users_iter != usersList.end())
+ {
+ Unauthorize(*users_iter);
+ UnSetUserNotifiers(*users_iter);
+ ++users_iter;
+ }
+isRunning = false;
+return 0;
+}
+//-----------------------------------------------------------------------------
+bool AUTH_AO::IsRunning()
+{
+return isRunning;
+}
+//-----------------------------------------------------------------------------
+uint16_t AUTH_AO::GetStartPosition() const
+{
+return 70;
+}
+//-----------------------------------------------------------------------------
+uint16_t AUTH_AO::GetStopPosition() const
+{
+return 70;
+}
+//-----------------------------------------------------------------------------
+void AUTH_AO::SetUserNotifiers(user_iter u)
+{
+// ---------- AlwaysOnline -------------------
+CHG_BEFORE_NOTIFIER<int> BeforeChgAONotifier;
+CHG_AFTER_NOTIFIER<int> AfterChgAONotifier;
+
+BeforeChgAONotifier.SetAuthorizator(this);
+BeforeChgAONotifier.SetUser(u);
+BeforeChgAONotifierList.push_front(BeforeChgAONotifier);
+
+AfterChgAONotifier.SetAuthorizator(this);
+AfterChgAONotifier.SetUser(u);
+AfterChgAONotifierList.push_front(AfterChgAONotifier);
+
+u->property.alwaysOnline.AddBeforeNotifier(&(*BeforeChgAONotifierList.begin()));
+u->property.alwaysOnline.AddAfterNotifier(&(*AfterChgAONotifierList.begin()));
+// ---------- AlwaysOnline end ---------------
+
+// ---------- IP -------------------
+CHG_BEFORE_NOTIFIER<USER_IPS> BeforeChgIPNotifier;
+CHG_AFTER_NOTIFIER<USER_IPS> AfterChgIPNotifier;
+
+BeforeChgIPNotifier.SetAuthorizator(this);
+BeforeChgIPNotifier.SetUser(u);
+BeforeChgIPNotifierList.push_front(BeforeChgIPNotifier);
+
+AfterChgIPNotifier.SetAuthorizator(this);
+AfterChgIPNotifier.SetUser(u);
+AfterChgIPNotifierList.push_front(AfterChgIPNotifier);
+
+u->property.ips.AddBeforeNotifier(&(*BeforeChgIPNotifierList.begin()));
+u->property.ips.AddAfterNotifier(&(*AfterChgIPNotifierList.begin()));
+// ---------- IP end ---------------
+}
+//-----------------------------------------------------------------------------
+void AUTH_AO::UnSetUserNotifiers(user_iter u)
+{
+// --- AlwaysOnline ---
+IS_CONTAINS_USER<CHG_BEFORE_NOTIFIER<int> > IsContainsUserAOB;
+IS_CONTAINS_USER<CHG_AFTER_NOTIFIER<int> > IsContainsUserAOA;
+
+list<CHG_BEFORE_NOTIFIER<int> >::iterator aoBIter;
+list<CHG_AFTER_NOTIFIER<int> >::iterator aoAIter;
+
+aoBIter = find_if(BeforeChgAONotifierList.begin(),
+ BeforeChgAONotifierList.end(),
+ bind2nd(IsContainsUserAOB, u));
+
+if (aoBIter != BeforeChgAONotifierList.end())
+ {
+ aoBIter->GetUser()->property.alwaysOnline.DelBeforeNotifier(&(*aoBIter));
+ BeforeChgAONotifierList.erase(aoBIter);
+ }
+
+aoAIter = find_if(AfterChgAONotifierList.begin(),
+ AfterChgAONotifierList.end(),
+ bind2nd(IsContainsUserAOA, u));
+
+if (aoAIter != AfterChgAONotifierList.end())
+ {
+ aoAIter->GetUser()->property.alwaysOnline.DelAfterNotifier(&(*aoAIter));
+ AfterChgAONotifierList.erase(aoAIter);
+ }
+// --- AlwaysOnline end ---
+
+// --- IP ---
+IS_CONTAINS_USER<CHG_BEFORE_NOTIFIER<USER_IPS> > IsContainsUserIPB;
+IS_CONTAINS_USER<CHG_AFTER_NOTIFIER<USER_IPS> > IsContainsUserIPA;
+
+list<CHG_BEFORE_NOTIFIER<USER_IPS> >::iterator ipBIter;
+list<CHG_AFTER_NOTIFIER<USER_IPS> >::iterator ipAIter;
+
+ipBIter = find_if(BeforeChgIPNotifierList.begin(),
+ BeforeChgIPNotifierList.end(),
+ bind2nd(IsContainsUserIPB, u));
+
+if (ipBIter != BeforeChgIPNotifierList.end())
+ {
+ ipBIter->GetUser()->property.ips.DelBeforeNotifier(&(*ipBIter));
+ BeforeChgIPNotifierList.erase(ipBIter);
+ }
+
+ipAIter = find_if(AfterChgIPNotifierList.begin(),
+ AfterChgIPNotifierList.end(),
+ bind2nd(IsContainsUserIPA, u));
+
+if (ipAIter != AfterChgIPNotifierList.end())
+ {
+ ipAIter->GetUser()->property.ips.DelAfterNotifier(&(*ipAIter));
+ AfterChgIPNotifierList.erase(ipAIter);
+ }
+// --- IP end ---
+}
+//-----------------------------------------------------------------------------
+void AUTH_AO::GetUsers()
+{
+user_iter u;
+int h = users->OpenSearch();
+if (!h)
+ {
+ printfd(__FILE__, "users->OpenSearch() error\n");
+ return;
+ }
+
+while (1)
+ {
+ if (users->SearchNext(h, &u))
+ {
+ break;
+ }
+ usersList.push_back(u);
+ SetUserNotifiers(u);
+ }
+
+users->CloseSearch(h);
+}
+//-----------------------------------------------------------------------------
+void AUTH_AO::Unauthorize(user_iter u) const
+{
+u->Unauthorize(this);
+}
+//-----------------------------------------------------------------------------
+void AUTH_AO::UpdateUserAuthorization(user_iter u) const
+{
+if (u->property.alwaysOnline)
+ {
+ USER_IPS ips = u->property.ips;
+ if (ips.OnlyOneIP())
+ {
+ if (u->Authorize(ips[0].ip, "", 0xFFffFFff, this) == 0)
+ {
+ }
+ }
+ }
+}
+//-----------------------------------------------------------------------------
+void AUTH_AO::AddUser(user_iter u)
+{
+SetUserNotifiers(u);
+usersList.push_back(u);
+UpdateUserAuthorization(u);
+}
+//-----------------------------------------------------------------------------
+void AUTH_AO::DelUser(user_iter u)
+{
+Unauthorize(u);
+UnSetUserNotifiers(u);
+
+list<user_iter>::iterator users_iter;
+users_iter = usersList.begin();
+
+while (users_iter != usersList.end())
+ {
+ if (u == *users_iter)
+ {
+ usersList.erase(users_iter);
+ break;
+ }
+ ++users_iter;
+ }
+}
+//-----------------------------------------------------------------------------
+int AUTH_AO::SendMessage(const STG_MSG &, uint32_t) const
+{
+errorStr = "Authorization modele \'AlwaysOnline\' does not support sending messages";
+return -1;
+}
+//-----------------------------------------------------------------------------
+template <typename varParamType>
+void CHG_BEFORE_NOTIFIER<varParamType>::Notify(const varParamType &, const varParamType &)
+{
+EVENT_LOOP_SINGLETON::GetInstance().Enqueue(*auth, &AUTH_AO::Unauthorize, user);
+}
+//-----------------------------------------------------------------------------
+template <typename varParamType>
+void CHG_AFTER_NOTIFIER<varParamType>::Notify(const varParamType &, const varParamType &)
+{
+EVENT_LOOP_SINGLETON::GetInstance().Enqueue(*auth, &AUTH_AO::UpdateUserAuthorization, user);
+}
+//-----------------------------------------------------------------------------
+
--- /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>
+ */
+
+/*
+ $Revision: 1.21 $
+ $Date: 2010/09/10 06:38:26 $
+ $Author: faust $
+*/
+
+#ifndef AO_H
+#define AO_H
+
+#include <string>
+#include <pthread.h>
+#include "base_auth.h"
+#include "base_store.h"
+#include "notifer.h"
+#include "user_ips.h"
+#include "../../../users.h"
+
+using namespace std;
+
+extern "C" BASE_PLUGIN * GetPlugin();
+
+class AUTH_AO;
+//-----------------------------------------------------------------------------
+template <typename varParamType>
+class CHG_BEFORE_NOTIFIER: public PROPERTY_NOTIFIER_BASE<varParamType>
+{
+public:
+ void Notify(const varParamType & oldValue, const varParamType & newValue);
+ void SetUser(user_iter u) { user = u; }
+ user_iter GetUser() {return user; }
+ void SetAuthorizator(const AUTH_AO * a) { auth = a; }
+
+private:
+ user_iter user;
+ const AUTH_AO * auth;
+};
+//-----------------------------------------------------------------------------
+template <typename varParamType>
+class CHG_AFTER_NOTIFIER: public PROPERTY_NOTIFIER_BASE<varParamType>
+{
+public:
+ void Notify(const varParamType & oldValue, const varParamType & newValue);
+ void SetUser(user_iter u) { user = u; }
+ user_iter GetUser() {return user; }
+ void SetAuthorizator(const AUTH_AO * a) { auth = a; }
+
+private:
+ user_iter user;
+ const AUTH_AO * auth;
+};
+//-----------------------------------------------------------------------------
+class AUTH_AO_SETTINGS
+{
+public:
+ const string& GetStrError() const { static string s; return s; }
+ int ParseSettings(const MODULE_SETTINGS &) { return 0; }
+};
+//-----------------------------------------------------------------------------
+class AUTH_AO :public BASE_AUTH
+{
+public:
+ AUTH_AO();
+ virtual ~AUTH_AO(){};
+
+ void SetUsers(USERS * u);
+ void SetTariffs(TARIFFS *){};
+ void SetAdmins(ADMINS *){};
+ void SetTraffcounter(TRAFFCOUNTER *){};
+ void SetStore(BASE_STORE *){};
+ void SetStgSettings(const SETTINGS *){};
+
+ int Start();
+ int Stop();
+ int Reload() { return 0; };
+ bool IsRunning();
+ void SetSettings(const MODULE_SETTINGS & s);
+ int ParseSettings();
+ const string & GetStrError() const;
+ const string GetVersion() const;
+ uint16_t GetStartPosition() const;
+ uint16_t GetStopPosition() const;
+
+ void AddUser(user_iter u);
+ void DelUser(user_iter u);
+
+ void UpdateUserAuthorization(user_iter u) const;
+ void Unauthorize(user_iter u) const;
+
+ int SendMessage(const STG_MSG & msg, uint32_t ip) const;
+
+private:
+ void GetUsers();
+ void SetUserNotifiers(user_iter u);
+ void UnSetUserNotifiers(user_iter u);
+
+ mutable string errorStr;
+ AUTH_AO_SETTINGS aoSettings;
+ USERS * users;
+ list<user_iter> usersList;
+ bool isRunning;
+ MODULE_SETTINGS settings;
+
+ /*
+ ÍÙ ÄÏÌÖÎÙ ÐÅÒÅÐÒÏ×ÅÒÉÔØ ×ÏÚÍÏÖÎÏÓÔØ Á×ÔÏÒÉÚÁÃÉÉ ÀÚÅÒÁ ÐÒÉ ÉÚÍÅÎÅÎÉÉ
+ ÓÌÅÄÕÀÝÉÈ ÅÇÏ ÐÁÒÁÍÅÔÒÏ×:
+ - alwaysOnline
+ - ips
+ */
+
+ list<CHG_BEFORE_NOTIFIER<int> > BeforeChgAONotifierList;
+ list<CHG_AFTER_NOTIFIER<int> > AfterChgAONotifierList;
+
+ list<CHG_BEFORE_NOTIFIER<USER_IPS> > BeforeChgIPNotifierList;
+ list<CHG_AFTER_NOTIFIER<USER_IPS> > AfterChgIPNotifierList;
+
+ class ADD_USER_NONIFIER: public NOTIFIER_BASE<user_iter>
+ {
+ public:
+ ADD_USER_NONIFIER(){};
+ virtual ~ADD_USER_NONIFIER(){};
+
+ void SetAuthorizator(AUTH_AO * a) { auth = a; }
+ void Notify(const user_iter & user)
+ {
+ auth->AddUser(user);
+ }
+
+ private:
+ AUTH_AO * auth;
+ } onAddUserNotifier;
+
+ class DEL_USER_NONIFIER: public NOTIFIER_BASE<user_iter>
+ {
+ public:
+ DEL_USER_NONIFIER(){};
+ virtual ~DEL_USER_NONIFIER(){};
+
+ void SetAuthorizator(AUTH_AO * a) { auth = a; }
+ void Notify(const user_iter & user)
+ {
+ auth->DelUser(user);
+ }
+
+ private:
+ AUTH_AO * auth;
+ } onDelUserNotifier;
+
+};
+//-----------------------------------------------------------------------------
+
+#endif
+
+
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.10 2010/02/16 11:41:00 faust Exp $
+###############################################################################
+
+include ../../../../../Makefile.conf
+
+LIBS += $(LIB_THREAD)
+
+PROG = mod_auth_ia.so
+
+SRCS = ./inetaccess.cpp
+
+STGLIBS = -lstg_common -lstg_crypto
+
+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
+ */
+
+/*
+ * Date: 27.10.2002
+ */
+
+/*
+ * Author : Boris Mikhailenko <stg34@ua.fm>
+ */
+
+
+#include <string.h>
+
+#include "antiflood.h"
+#include "common.h"
+
+//-----------------------------------------------------------------------------
+int FloodIPCompare(void * p1, void * p2)
+{
+/*
+óÒÁ×ÎÉ×ÁÅÍ Ä×Á éð × ÓÔÒÕËÔÒÕ Ó ÁÎÔÉÆÌÕÄÏÍ
+ * */
+
+FLOOD_NODE * n1, *n2;
+
+n1 = (FLOOD_NODE *)p1;
+n2 = (FLOOD_NODE *)p2;
+printfd(__FILE__, "FloodIPCompare %X %X\n", n1->ip, n2->ip);
+return n1->ip - n2->ip;
+}
+//-----------------------------------------------------------------------------
+ANTIFLOOD::ANTIFLOOD():
+floodTree(FloodIPCompare)
+{
+/*
+óÒÅÄÎÅÅ ÎÁÉÍÅÎØÛÅÅ ÒÁÚÒÅÛÅÎÎÏÅ ×ÒÅÍÑ ÍÅÖÄÕ ÐÁËÅÔÁÍÉ. ÍÓ.
+ * */
+
+avrgTime = 500;
+}
+//-----------------------------------------------------------------------------
+bool ANTIFLOOD::AllowIP(uint32_t ip, bool * logged)
+{
+/*
+ðÒÏ×ÅÒËÁ ÔÏÇÏ ÎÅ ÓÌÉÛËÏÍ ÌÉ ÞÁÓÔÏ ÐÒÉÈÏÄÑÔ ÐÁËÅÔÙ Ó ÕËÁÚÁÎÎÏÇÏ ÁÊÐÉÛÎÉËÁ
+ * */
+
+BSPNODE * findNode;
+FLOOD_NODE floodNode;
+
+floodNode.ip = ip;
+findNode = floodTree.Find(&floodNode);
+
+gettimeofday(&tv, NULL);
+currentTime = ((uint64_t)tv.tv_sec)*1000 + ((uint64_t)tv.tv_usec)/1000;
+
+if (findNode == NULL)
+ {
+ AddNode(ip);
+ printfd(__FILE__, "AddNode(%X)\n", ip);
+ return true;
+ }
+else
+ {
+ printfd(__FILE__, "UpdateNodeTime(%X)\n", findNode->record);
+ UpdateNodeTime((FLOOD_NODE*)(findNode->record));
+ }
+
+if (currentTime - CalcAvrgNodeTime((FLOOD_NODE*)findNode->record) < avrgTime)
+ {
+ if (((FLOOD_NODE*)findNode->record)->logged == false)
+ {
+ *logged = false;
+ ((FLOOD_NODE*)findNode->record)->logged = true;
+ //floodNode.logged = true;
+ }
+ else
+ {
+ *logged = true;
+ }
+ return false;
+ }
+
+((FLOOD_NODE*)findNode->record)->logged = false;
+return true;
+}
+//-----------------------------------------------------------------------------
+void ANTIFLOOD::UpdateNodeTime(FLOOD_NODE * node)
+{
+/*
+ïÂÎÏ×ÌÑÅÍ ×ÒÅÍÑ ÐÏÓÌÅÄÎÅÇÏ ÐÒÅÛÅÄÛÅÇÏ ÐÁËÅÔÁ
+ * */
+
+node->timeIP[node->pos] = currentTime;
+
+node->pos++;
+if (node->pos >= FLOOD_LBL_MAX)
+ node->pos = 0;
+
+}
+//-----------------------------------------------------------------------------
+void ANTIFLOOD::Clean()
+{
+/*
+þÍÓÔËÁ ÄÅÒÅ×Á ÓÏ ÓÌÉÛËÏÍ ÓÔÁÒÙÍÉ ÄÁÎÎÙÍÉ
+ * */
+
+BSPNODE * bspNode = floodTree.Max(floodTree.GetRoot());
+FLOOD_NODE * n;
+BSPNODE * delNode;
+currentTime = ((uint64_t)tv.tv_sec)*1000 + ((uint64_t)tv.tv_usec)/1000;
+
+while (bspNode)
+ {
+ n = (FLOOD_NODE*)bspNode->record;
+ if (currentTime - CalcAvrgNodeTime(n) > 2 * 60)
+ {
+ delNode = floodTree.Delete(bspNode);
+ delete (FLOOD_NODE*)delNode->record;
+ delete delNode;
+ }
+ bspNode = floodTree.Max(floodTree.GetRoot());
+ }
+
+printfd(__FILE__, "after clean max=%X\n", floodTree.Max(floodTree.GetRoot()));
+printfd(__FILE__, "after clean min=%X\n", floodTree.Min(floodTree.GetRoot()));
+
+}
+//-----------------------------------------------------------------------------
+void ANTIFLOOD::AddNode(uint32_t ip)
+{
+/*
+äÏÂÁ×ÌÑÅÍ ÎÏ×ÙÊ éð × ÄÅÒÅ×Ï
+ * */
+
+FLOOD_NODE * fn;
+BSPNODE * node;
+
+fn = new FLOOD_NODE;
+
+fn->pos = 0;
+fn->ip = ip;
+fn->logged = false;
+
+memset(fn->timeIP, 0, sizeof(uint64_t) * FLOOD_LBL_MAX);
+fn->timeIP[0] = currentTime;
+
+node = new BSPNODE;
+node->record = fn;
+
+floodTree.Add(node);
+}
+//-----------------------------------------------------------------------------
+uint64_t ANTIFLOOD::CalcAvrgNodeTime(FLOOD_NODE * fn)
+{
+/*
+÷ÙÞÉÓÌÑÅÍ ÓÒÅÄÎÅÅ ×ÒÅÍÑ ÐÏÓÌÅÄÎÉÈ ÐÒÅÛÅÄÛÉÈ ÐÁËÅÔÏ×
+ * */
+
+uint64_t t = 0;
+for (int i = 0; i < FLOOD_LBL_MAX; i++)
+ t += fn->timeIP[i];
+
+printfd(__FILE__, "node time %lld\n", t/FLOOD_LBL_MAX);
+printfd(__FILE__, "current time %lld\n", currentTime);
+
+return t/FLOOD_LBL_MAX;
+}
+//-----------------------------------------------------------------------------
+void ANTIFLOOD::SetAvrgTime(uint64_t t)
+{
+avrgTime = t;
+}
+//-----------------------------------------------------------------------------
+
+
--- /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@ua.fm>
+ */
+
+
+#ifndef ANTIFLOOD_H
+#define ANTIFLOOD_H
+
+
+#include <sys/time.h>
+
+#include "bsp.h"
+#include "os_int.h"
+
+#define FLOOD_LBL_MAX (10)
+
+//-----------------------------------------------------------------------------
+struct FLOOD_NODE
+{
+uint32_t ip;
+uint64_t timeIP[FLOOD_LBL_MAX];
+int pos;
+bool logged;
+};
+
+//-----------------------------------------------------------------------------
+class ANTIFLOOD
+{
+public:
+ ANTIFLOOD();
+ bool AllowIP(uint32_t ip, bool * logged);
+ void Clean();
+ void SetAvrgTime(uint64_t);
+
+private:
+ uint64_t CalcAvrgNodeTime(FLOOD_NODE * fn);
+ void AddNode(uint32_t ip);
+ void UpdateNodeTime(FLOOD_NODE * node);
+
+ TREE floodTree;
+ struct timeval tv;
+ uint64_t avrgTime;
+ uint64_t currentTime;
+};
+//-----------------------------------------------------------------------------
+
+#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>
+ */
+
+/*
+ $Revision: 1.79 $
+ $Date: 2010/03/25 15:18:48 $
+ $Author: faust $
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <csignal>
+#include <cstdlib>
+#include <algorithm>
+
+#include "inetaccess.h"
+#include "common.h"
+
+extern volatile const time_t stgTime;
+
+//-----------------------------------------------------------------------------
+class IA_CREATOR
+{
+private:
+ AUTH_IA * ia;
+
+public:
+ IA_CREATOR()
+ : ia(new AUTH_IA())
+ {
+ };
+ ~IA_CREATOR()
+ {
+ delete ia;
+ };
+
+ AUTH_IA * GetPlugin()
+ {
+ return ia;
+ };
+};
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+IA_CREATOR iac;
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+BASE_PLUGIN * GetPlugin()
+{
+return iac.GetPlugin();
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+AUTH_IA_SETTINGS::AUTH_IA_SETTINGS()
+ : userDelay(0),
+ userTimeout(0),
+ port(0),
+ freeMbShowType(freeMbCash)
+{
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA_SETTINGS::ParseIntInRange(const string & str, int min, int max, int * val)
+{
+if (str2x(str.c_str(), *val))
+ {
+ errorStr = "Incorrect value \'" + str + "\'.";
+ return -1;
+ }
+if (*val < min || *val > max)
+ {
+ errorStr = "Value \'" + str + "\' out of range.";
+ return -1;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA_SETTINGS::ParseSettings(const MODULE_SETTINGS & s)
+{
+int p;
+PARAM_VALUE pv;
+vector<PARAM_VALUE>::const_iterator pvi;
+///////////////////////////
+pv.param = "Port";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end())
+ {
+ errorStr = "Parameter \'Port\' not found.";
+ printfd(__FILE__, "Parameter 'Port' not found\n");
+ return -1;
+ }
+if (ParseIntInRange(pvi->value[0], 2, 65535, &p))
+ {
+ errorStr = "Cannot parse parameter \'Port\': " + errorStr;
+ printfd(__FILE__, "Cannot parse parameter 'Port'\n");
+ return -1;
+ }
+port = p;
+///////////////////////////
+pv.param = "UserDelay";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end())
+ {
+ errorStr = "Parameter \'UserDelay\' not found.";
+ printfd(__FILE__, "Parameter 'UserDelay' not found\n");
+ return -1;
+ }
+
+if (ParseIntInRange(pvi->value[0], 5, 600, &userDelay))
+ {
+ errorStr = "Cannot parse parameter \'UserDelay\': " + errorStr;
+ printfd(__FILE__, "Cannot parse parameter 'UserDelay'\n");
+ return -1;
+ }
+///////////////////////////
+pv.param = "UserTimeout";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end())
+ {
+ errorStr = "Parameter \'UserTimeout\' not found.";
+ printfd(__FILE__, "Parameter 'UserTimeout' not found\n");
+ return -1;
+ }
+
+if (ParseIntInRange(pvi->value[0], 15, 1200, &userTimeout))
+ {
+ errorStr = "Cannot parse parameter \'UserTimeout\': " + errorStr;
+ printfd(__FILE__, "Cannot parse parameter 'UserTimeout'\n");
+ return -1;
+ }
+/////////////////////////////////////////////////////////////
+string freeMbType;
+int n = 0;
+pv.param = "FreeMb";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end())
+ {
+ errorStr = "Parameter \'FreeMb\' not found.";
+ printfd(__FILE__, "Parameter 'FreeMb' not found\n");
+ return -1;
+ }
+freeMbType = pvi->value[0];
+
+if (strcasecmp(freeMbType.c_str(), "cash") == 0)
+ {
+ freeMbShowType = freeMbCash;
+ }
+else if (strcasecmp(freeMbType.c_str(), "none") == 0)
+ {
+ freeMbShowType = freeMbNone;
+ }
+else if (!str2x(freeMbType.c_str(), n))
+ {
+ if (n < 0 || n >= DIR_NUM)
+ {
+ errorStr = "Incorrect parameter \'" + freeMbType + "\'.";
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+ freeMbShowType = (FREEMB)(freeMb0 + n);
+ }
+else
+ {
+ errorStr = "Incorrect parameter \'" + freeMbType + "\'.";
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+/////////////////////////////////////////////////////////////
+return 0;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+#ifdef IA_PHASE_DEBUG
+IA_PHASE::IA_PHASE()
+ : phase(1),
+ flog(NULL)
+{
+gettimeofday(&phaseTime, NULL);
+}
+#else
+IA_PHASE::IA_PHASE()
+ : phase(1)
+{
+gettimeofday(&phaseTime, NULL);
+}
+#endif
+//-----------------------------------------------------------------------------
+IA_PHASE::~IA_PHASE()
+{
+#ifdef IA_PHASE_DEBUG
+flog = fopen(log.c_str(), "at");
+if (flog)
+ {
+ fprintf(flog, "IA %s D\n", login.c_str());
+ fclose(flog);
+ }
+#endif
+}
+//-----------------------------------------------------------------------------
+#ifdef IA_PHASE_DEBUG
+void IA_PHASE::SetLogFileName(const string & logFileName)
+{
+log = logFileName + ".ia.log";
+}
+//-----------------------------------------------------------------------------
+void IA_PHASE::SetUserLogin(const string & login)
+{
+IA_PHASE::login = login;
+}
+//-----------------------------------------------------------------------------
+void IA_PHASE::WritePhaseChange(int newPhase)
+{
+UTIME newPhaseTime;
+gettimeofday(&newPhaseTime, NULL);
+flog = fopen(log.c_str(), "at");
+/*int64_t tn = newPhaseTime.GetSec()*1000000 + newPhaseTime.GetUSec();
+int64_t to = phaseTime.GetSec()*1000000 + phaseTime.GetUSec();*/
+if (flog)
+ {
+ string action = newPhase == phase ? "U" : "C";
+ double delta = newPhaseTime.GetSec() - phaseTime.GetSec();
+ delta += (newPhaseTime.GetUSec() - phaseTime.GetUSec()) * 1.0e-6;
+ fprintf(flog, "IA %s %s oldPhase = %d, newPhase = %d. dt = %.6f\n",
+ login.c_str(),
+ action.c_str(),
+ phase,
+ newPhase,
+ delta);
+ fclose(flog);
+ }
+}
+#endif
+//-----------------------------------------------------------------------------
+void IA_PHASE::SetPhase1()
+{
+#ifdef IA_PHASE_DEBUG
+WritePhaseChange(1);
+#endif
+phase = 1;
+gettimeofday(&phaseTime, NULL);
+}
+//-----------------------------------------------------------------------------
+void IA_PHASE::SetPhase2()
+{
+#ifdef IA_PHASE_DEBUG
+WritePhaseChange(2);
+#endif
+phase = 2;
+gettimeofday(&phaseTime, NULL);
+}
+//-----------------------------------------------------------------------------
+void IA_PHASE::SetPhase3()
+{
+#ifdef IA_PHASE_DEBUG
+WritePhaseChange(3);
+#endif
+phase = 3;
+gettimeofday(&phaseTime, NULL);
+}
+//-----------------------------------------------------------------------------
+void IA_PHASE::SetPhase4()
+{
+#ifdef IA_PHASE_DEBUG
+WritePhaseChange(4);
+#endif
+phase = 4;
+gettimeofday(&phaseTime, NULL);
+}
+//-----------------------------------------------------------------------------
+void IA_PHASE::SetPhase5()
+{
+#ifdef IA_PHASE_DEBUG
+WritePhaseChange(5);
+#endif
+phase = 5;
+gettimeofday(&phaseTime, NULL);
+}
+//-----------------------------------------------------------------------------
+int IA_PHASE::GetPhase() const
+{
+return phase;
+}
+//-----------------------------------------------------------------------------
+void IA_PHASE::UpdateTime()
+{
+#ifdef IA_PHASE_DEBUG
+WritePhaseChange(phase);
+#endif
+gettimeofday(&phaseTime, NULL);
+}
+//-----------------------------------------------------------------------------
+const UTIME & IA_PHASE::GetTime() const
+{
+return phaseTime;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+AUTH_IA::AUTH_IA()
+ : nonstop(false),
+ isRunningRun(false),
+ isRunningRunTimeouter(false),
+ WriteServLog(GetStgLogger()),
+ enabledDirs(0xFFffFFff),
+ onDelUserNotifier(*this)
+{
+InitEncrypt(&ctxS, "pr7Hhen");
+
+pthread_mutexattr_t attr;
+pthread_mutexattr_init(&attr);
+pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+pthread_mutex_init(&mutex, &attr);
+
+memset(&connSynAck6, 0, sizeof(CONN_SYN_ACK_6));
+memset(&connSynAck8, 0, sizeof(CONN_SYN_ACK_8));
+memset(&disconnSynAck6, 0, sizeof(DISCONN_SYN_ACK_6));
+memset(&disconnSynAck8, 0, sizeof(DISCONN_SYN_ACK_8));
+memset(&aliveSyn6, 0, sizeof(ALIVE_SYN_6));
+memset(&aliveSyn8, 0, sizeof(ALIVE_SYN_8));
+memset(&fin6, 0, sizeof(FIN_6));
+memset(&fin8, 0, sizeof(FIN_8));
+
+printfd(__FILE__, "sizeof(CONN_SYN_6) = %d %d\n", sizeof(CONN_SYN_6), Min8(sizeof(CONN_SYN_6)));
+printfd(__FILE__, "sizeof(CONN_SYN_8) = %d %d\n", sizeof(CONN_SYN_8), Min8(sizeof(CONN_SYN_8)));
+printfd(__FILE__, "sizeof(CONN_SYN_ACK_6) = %d %d\n", sizeof(CONN_SYN_ACK_6), Min8(sizeof(CONN_SYN_ACK_6)));
+printfd(__FILE__, "sizeof(CONN_SYN_ACK_8) = %d %d\n", sizeof(CONN_SYN_ACK_8), Min8(sizeof(CONN_SYN_ACK_8)));
+printfd(__FILE__, "sizeof(CONN_ACK_6) = %d %d\n", sizeof(CONN_ACK_6), Min8(sizeof(CONN_ACK_6)));
+printfd(__FILE__, "sizeof(ALIVE_SYN_6) = %d %d\n", sizeof(ALIVE_SYN_6), Min8(sizeof(ALIVE_SYN_6)));
+printfd(__FILE__, "sizeof(ALIVE_SYN_8) = %d %d\n", sizeof(ALIVE_SYN_8), Min8(sizeof(ALIVE_SYN_8)));
+printfd(__FILE__, "sizeof(ALIVE_ACK_6) = %d %d\n", sizeof(ALIVE_ACK_6), Min8(sizeof(ALIVE_ACK_6)));
+printfd(__FILE__, "sizeof(DISCONN_SYN_6) = %d %d\n", sizeof(DISCONN_SYN_6), Min8(sizeof(DISCONN_SYN_6)));
+printfd(__FILE__, "sizeof(DISCONN_SYN_ACK_6) = %d %d\n", sizeof(DISCONN_SYN_ACK_6), Min8(sizeof(DISCONN_SYN_ACK_6)));
+printfd(__FILE__, "sizeof(DISCONN_SYN_ACK_8) = %d %d\n", sizeof(DISCONN_SYN_ACK_8), Min8(sizeof(DISCONN_SYN_ACK_8)));
+printfd(__FILE__, "sizeof(DISCONN_ACK_6) = %d %d\n", sizeof(DISCONN_ACK_6), Min8(sizeof(DISCONN_ACK_6)));
+printfd(__FILE__, "sizeof(FIN_6) = %d %d\n", sizeof(FIN_6), Min8(sizeof(FIN_6)));
+printfd(__FILE__, "sizeof(FIN_8) = %d %d\n", sizeof(FIN_8), Min8(sizeof(FIN_8)));
+printfd(__FILE__, "sizeof(ERR) = %d %d\n", sizeof(ERR), Min8(sizeof(ERR)));
+printfd(__FILE__, "sizeof(INFO_6) = %d %d\n", sizeof(INFO_6), Min8(sizeof(INFO_6)));
+printfd(__FILE__, "sizeof(INFO_7) = %d %d\n", sizeof(INFO_7), Min8(sizeof(INFO_7)));
+printfd(__FILE__, "sizeof(INFO_8) = %d %d\n", sizeof(INFO_8), Min8(sizeof(INFO_8)));
+
+packetTypes["CONN_SYN"] = CONN_SYN_N;
+packetTypes["CONN_SYN_ACK"] = CONN_SYN_ACK_N;
+packetTypes["CONN_ACK"] = CONN_ACK_N;
+packetTypes["ALIVE_SYN"] = ALIVE_SYN_N;
+packetTypes["ALIVE_ACK"] = ALIVE_ACK_N;
+packetTypes["DISCONN_SYN"] = DISCONN_SYN_N;
+packetTypes["DISCONN_SYN_ACK"] = DISCONN_SYN_ACK_N;
+packetTypes["DISCONN_ACK"] = DISCONN_ACK_N;
+packetTypes["FIN"] = FIN_N;
+packetTypes["ERR"] = ERROR_N;
+}
+//-----------------------------------------------------------------------------
+AUTH_IA::~AUTH_IA()
+{
+pthread_mutex_destroy(&mutex);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Start()
+{
+users->AddNotifierUserDel(&onDelUserNotifier);
+nonstop = true;
+
+if (PrepareNet())
+ {
+ return -1;
+ }
+
+if (!isRunningRun)
+ {
+ if (pthread_create(&recvThread, NULL, Run, this))
+ {
+ errorStr = "Cannot create thread.";
+ printfd(__FILE__, "Cannot create recv thread\n");
+ return -1;
+ }
+ }
+
+if (!isRunningRunTimeouter)
+ {
+ if (pthread_create(&timeouterThread, NULL, RunTimeouter, this))
+ {
+ errorStr = "Cannot create thread.";
+ printfd(__FILE__, "Cannot create timeouter thread\n");
+ return -1;
+ }
+ }
+errorStr = "";
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Stop()
+{
+if (!IsRunning())
+ return 0;
+
+nonstop = false;
+
+std::for_each(
+ ip2user.begin(),
+ ip2user.end(),
+ UnauthorizeUser(this)
+ );
+
+if (isRunningRun)
+ {
+ //5 seconds to thread stops itself
+ for (int i = 0; i < 25 && isRunningRun; i++)
+ {
+ usleep(200000);
+ }
+
+ //after 5 seconds waiting thread still running. now killing it
+ if (isRunningRun)
+ {
+ //TODO pthread_cancel()
+ if (pthread_kill(recvThread, SIGINT))
+ {
+ errorStr = "Cannot kill thread.";
+ printfd(__FILE__, "Cannot kill thread\n");
+ return -1;
+ }
+ for (int i = 0; i < 25 && isRunningRun; ++i)
+ usleep(200000);
+ if (isRunningRun)
+ {
+ printfd(__FILE__, "Failed to stop recv thread\n");
+ }
+ else
+ {
+ pthread_join(recvThread, NULL);
+ }
+ printfd(__FILE__, "AUTH_IA killed Run\n");
+ }
+ }
+
+FinalizeNet();
+
+if (isRunningRunTimeouter)
+ {
+ //5 seconds to thread stops itself
+ for (int i = 0; i < 25 && isRunningRunTimeouter; i++)
+ {
+ usleep(200000);
+ }
+
+ //after 5 seconds waiting thread still running. now killing it
+ if (isRunningRunTimeouter)
+ {
+ //TODO pthread_cancel()
+ if (pthread_kill(timeouterThread, SIGINT))
+ {
+ errorStr = "Cannot kill thread.";
+ return -1;
+ }
+ for (int i = 0; i < 25 && isRunningRunTimeouter; ++i)
+ usleep(200000);
+ if (isRunningRunTimeouter)
+ {
+ printfd(__FILE__, "Failed to stop timeouter thread\n");
+ }
+ else
+ {
+ pthread_join(timeouterThread, NULL);
+ }
+ printfd(__FILE__, "AUTH_IA killed Timeouter\n");
+ }
+ }
+printfd(__FILE__, "AUTH_IA::Stoped successfully.\n");
+users->DelNotifierUserDel(&onDelUserNotifier);
+return 0;
+}
+//-----------------------------------------------------------------------------
+void * AUTH_IA::Run(void * d)
+{
+AUTH_IA * ia = static_cast<AUTH_IA *>(d);
+
+ia->isRunningRun = true;
+
+char buffer[512];
+
+time_t touchTime = stgTime - MONITOR_TIME_DELAY_SEC;
+
+while (ia->nonstop)
+ {
+ ia->RecvData(buffer, sizeof(buffer));
+ if ((touchTime + MONITOR_TIME_DELAY_SEC <= stgTime) && ia->stgSettings->GetMonitoring())
+ {
+ touchTime = stgTime;
+ string monFile = ia->stgSettings->GetMonitorDir() + "/inetaccess_r";
+ TouchFile(monFile.c_str());
+ }
+ }
+
+ia->isRunningRun = false;
+return NULL;
+}
+//-----------------------------------------------------------------------------
+void * AUTH_IA::RunTimeouter(void * d)
+{
+AUTH_IA * ia = static_cast<AUTH_IA *>(d);
+
+ia->isRunningRunTimeouter = true;
+
+int a = -1;
+string monFile = ia->stgSettings->GetMonitorDir() + "/inetaccess_t";
+while (ia->nonstop)
+ {
+ usleep(20000);
+ ia->Timeouter();
+ // TODO cahange counter to timer and MONITOR_TIME_DELAY_SEC
+ if (++a % (50*60) == 0 && ia->stgSettings->GetMonitoring())
+ {
+ TouchFile(monFile.c_str());
+ }
+ }
+
+ia->isRunningRunTimeouter = false;
+return NULL;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::ParseSettings()
+{
+int ret = iaSettings.ParseSettings(settings);
+if (ret)
+ errorStr = iaSettings.GetStrError();
+return ret;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::PrepareNet()
+{
+struct sockaddr_in listenAddr;
+
+listenSocket = socket(AF_INET, SOCK_DGRAM, 0);
+
+if (listenSocket < 0)
+ {
+ errorStr = "Cannot create socket.";
+ return -1;
+ }
+
+listenAddr.sin_family = AF_INET;
+listenAddr.sin_port = htons(iaSettings.GetUserPort());
+listenAddr.sin_addr.s_addr = inet_addr("0.0.0.0");
+
+if (bind(listenSocket, (struct sockaddr*)&listenAddr, sizeof(listenAddr)) < 0)
+ {
+ errorStr = "AUTH_IA: Bind failed.";
+ return -1;
+ }
+
+/*int buffLen;
+if (getsockopt(listenSocket, SOL_SOCKET, SO_SNDBUF, &buffLen, sizeof(buffLen)) < 0)
+ {
+
+ errorStr = "Getsockopt failed. " + string(strerror(errno));
+ return -1;
+ }*/
+
+//WriteServLog("buffLen = %d", buffLen);
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::FinalizeNet()
+{
+close(listenSocket);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::RecvData(char * buffer, int bufferSize)
+{
+if (!WaitPackets(listenSocket)) // Timeout
+ {
+ return 0;
+ }
+
+struct sockaddr_in outerAddr;
+socklen_t outerAddrLen(sizeof(outerAddr));
+int dataLen = recvfrom(listenSocket, buffer, bufferSize, 0, (struct sockaddr *)&outerAddr, &outerAddrLen);
+
+if (!dataLen) // EOF
+ {
+ return 0;
+ }
+
+if (dataLen <= 0) // Error
+ {
+ if (errno != EINTR)
+ {
+ printfd(__FILE__, "recvfrom res=%d, error: '%s'\n", dataLen, strerror(errno));
+ return -1;
+ }
+ return 0;
+ }
+
+if (dataLen > 256)
+ return -1;
+
+int protoVer;
+if (CheckHeader(buffer, &protoVer))
+ return -1;
+
+char login[PASSWD_LEN]; //TODO why PASSWD_LEN ?
+memset(login, 0, PASSWD_LEN);
+
+Decrypt(&ctxS, login, buffer + 8, PASSWD_LEN / 8);
+
+uint32_t sip = *((uint32_t*)&outerAddr.sin_addr);
+uint16_t sport = htons(outerAddr.sin_port);
+
+user_iter user;
+if (users->FindByName(login, &user) == 0)
+ {
+ printfd(__FILE__, "User %s FOUND!\n", user->GetLogin().c_str());
+ PacketProcessor(buffer, dataLen, sip, sport, protoVer, &user);
+ }
+else
+ {
+ WriteServLog("User\'s connect failed:: user \'%s\' not found. IP \'%s\'",
+ login,
+ inet_ntostring(sip).c_str());
+ printfd(__FILE__, "User %s NOT found!\n", login);
+ SendError(sip, sport, protoVer, "îÅÐÒÁ×ÉÌØÎÙÊ ÌÏÇÉÎ ÉÌÉ ÐÁÒÏÌØ!");
+ }
+
+return 0;
+
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::CheckHeader(const char * buffer, int * protoVer)
+{
+if (strncmp(IA_ID, buffer, strlen(IA_ID)) != 0)
+ {
+ //SendError(userIP, updateMsg);
+ printfd(__FILE__, "update needed - IA_ID\n");
+ //SendError(userIP, "Incorrect header!");
+ return -1;
+ }
+
+if (buffer[6] != 0) //proto[0] shoud be 0
+ {
+ printfd(__FILE__, "update needed - PROTO major: %d\n", buffer[6]);
+ //SendError(userIP, updateMsg);
+ return -1;
+ }
+
+if (buffer[7] < 6)
+ {
+ // need update
+ //SendError(userIP, updateMsg);
+ printfd(__FILE__, "update needed - PROTO minor: %d\n", buffer[7]);
+ return -1;
+ }
+else
+ {
+ *protoVer = buffer[7];
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Timeouter()
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+map<uint32_t, IA_USER>::iterator it;
+it = ip2user.begin();
+uint32_t sip;
+
+while (it != ip2user.end())
+ {
+ sip = it->first;
+
+ static UTIME currTime;
+ gettimeofday(&currTime, NULL);
+
+ if ((it->second.phase.GetPhase() == 2)
+ && (currTime - it->second.phase.GetTime()) > iaSettings.GetUserDelay())
+ {
+ it->second.phase.SetPhase1();
+ printfd(__FILE__, "Phase changed from 2 to 1. Reason: timeout\n");
+ }
+
+ if (it->second.phase.GetPhase() == 3)
+ {
+ if (!it->second.messagesToSend.empty())
+ {
+ if (it->second.protoVer == 6)
+ RealSendMessage6(*it->second.messagesToSend.begin(), sip, it->second);
+
+ if (it->second.protoVer == 7)
+ RealSendMessage7(*it->second.messagesToSend.begin(), sip, it->second);
+
+ if (it->second.protoVer == 8)
+ RealSendMessage8(*it->second.messagesToSend.begin(), sip, it->second);
+
+ it->second.messagesToSend.erase(it->second.messagesToSend.begin());
+ }
+
+ if((currTime - it->second.lastSendAlive) > iaSettings.GetUserDelay())
+ {
+ switch (it->second.protoVer)
+ {
+ case 6:
+ Send_ALIVE_SYN_6(&(it->second), sip);
+ break;
+ case 7:
+ Send_ALIVE_SYN_7(&(it->second), sip);
+ break;
+ case 8:
+ Send_ALIVE_SYN_8(&(it->second), sip);
+ break;
+ }
+
+ gettimeofday(&it->second.lastSendAlive, NULL);
+ }
+
+ if ((currTime - it->second.phase.GetTime()) > iaSettings.GetUserTimeout())
+ {
+ it->second.user->Unauthorize(this);
+ ip2user.erase(it++);
+ continue;
+ }
+ }
+
+ if ((it->second.phase.GetPhase() == 4)
+ && ((currTime - it->second.phase.GetTime()) > iaSettings.GetUserDelay()))
+ {
+ it->second.phase.SetPhase3();
+ printfd(__FILE__, "Phase changed from 4 to 3. Reason: timeout\n");
+ }
+
+ ++it;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::PacketProcessor(char * buff, int dataLen, uint32_t sip, uint16_t sport, int protoVer, user_iter * user)
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+// ôÕÔ ÓÏÂÒÁÎÙ ÏÂÒÁÂÏÔÞÉËÉ ÒÁÚÎÙÈ ÐÁËÅÔÏ×
+int pn = -1;
+int packetLen;
+const int offset = LOGIN_LEN + 2 + 6; // LOGIN_LEN + sizeOfMagic + sizeOfVer;
+
+IA_USER * iaUser = NULL;
+
+CONN_SYN_6 * connSyn6;
+CONN_SYN_7 * connSyn7;
+CONN_SYN_8 * connSyn8;
+
+CONN_ACK_6 * connAck;
+ALIVE_ACK_6 * aliveAck;
+DISCONN_SYN_6 * disconnSyn;
+DISCONN_ACK_6 * disconnAck;
+
+map<uint32_t, IA_USER>::iterator it;
+it = ip2user.find(sip);
+
+if (it == ip2user.end() || (*user)->GetID() != it->second.user->GetID())
+ {
+ // åÝÅ ÎÅ ÂÙÌÏ ÚÁÐÒÏÓÏ× Ó ÜÔÏÇÏ IP
+ printfd(__FILE__, "Add new user\n");
+ ip2user[sip].protoVer = protoVer;
+ ip2user[sip].user = *user;
+ ip2user[sip].port = sport;
+ #ifdef IA_PHASE_DEBUG
+ ip2user[sip].phase.SetLogFileName(stgSettings->GetLogFileName());
+ ip2user[sip].phase.SetUserLogin((*user)->GetLogin());
+ #endif
+
+
+ it = ip2user.find(sip); //TODO
+ if (it == ip2user.end())
+ {
+ printfd(__FILE__, "+++ ERROR +++\n");
+ return -1;
+ }
+ }
+
+iaUser = &(it->second);
+
+if (iaUser->port != sport)
+ iaUser->port = sport;
+
+if (iaUser->password != (*user)->property.password.Get())
+ {
+ InitEncrypt(&iaUser->ctx, (*user)->property.password.Get());
+ iaUser->password = (*user)->property.password.Get();
+ }
+
+buff += offset;
+Decrypt(&iaUser->ctx, buff, buff, (dataLen - offset) / 8);
+
+char packetName[IA_MAX_TYPE_LEN];
+strncpy(packetName, buff + 4, IA_MAX_TYPE_LEN);
+packetName[IA_MAX_TYPE_LEN - 1] = 0;
+
+map<string, int>::iterator pi;
+pi = packetTypes.find(packetName);
+if (pi == packetTypes.end())
+ {
+ SendError(sip, sport, protoVer, "îÅÐÒÁ×ÉÌØÎÙÊ ÌÏÇÉÎ ÉÌÉ ÐÁÒÏÌØ!");
+ printfd(__FILE__, "Login or password is wrong!\n");
+ WriteServLog("User's connect failed. IP \'%s\'. Wrong login or password", inet_ntostring(sip).c_str());
+ return 0;
+ }
+else
+ {
+ pn = pi->second;
+ }
+
+packetLen = *(int*)buff;
+
+if ((*user)->property.disabled.Get())
+ {
+ SendError(sip, sport, protoVer, "õÞÅÔÎÁÑ ÚÁÐÉÓØ ÚÁÂÌÏËÉÒÏ×ÁÎÁ");
+ return 0;
+ }
+
+if ((*user)->property.passive.Get())
+ {
+ SendError(sip, sport, protoVer, "õÞÅÔÎÁÑ ÚÁÐÉÓØ ÚÁÍÏÒÏÖÅÎÁ");
+ return 0;
+ }
+
+if ((*user)->GetAuthorized() && (*user)->GetCurrIP() != sip)
+ {
+ printfd(__FILE__, "Login %s alredy in use. IP \'%s\'\n", (*user)->GetLogin().c_str(), inet_ntostring(sip).c_str());
+ WriteServLog("Login %s alredy in use. IP \'%s\'", (*user)->GetLogin().c_str(), inet_ntostring(sip).c_str());
+ SendError(sip, sport, protoVer, "÷ÁÛ ÌÏÇÉÎ ÕÖÅ ÉÓÐÏÌØÚÕÅÔÓÑ!");
+ return 0;
+ }
+
+user_iter u;
+if (users->FindByIPIdx(sip, &u) == 0 && u->GetLogin() != (*user)->GetLogin())
+ {
+ printfd(__FILE__, "IP address alredy in use. IP \'%s\'", inet_ntostring(sip).c_str());
+ WriteServLog("IP address alredy in use. IP \'%s\'", inet_ntostring(sip).c_str());
+ SendError(sip, sport, protoVer, "÷ÁÛ IP ÁÄÒÅÓ ÕÖÅ ÉÓÐÏÌØÚÕÅÔÓÑ!");
+ return 0;
+ }
+
+// ôÅÐÅÒØ ÍÙ ÄÏÌÖÎÙ ÐÒÏ×ÅÒÉÔØ, ÍÏÖÅÔ ÌÉ ÐÏÌØÚÏ×ÁÔÅÌØ ÐÏÄËÌÀÞÉÔÓÑ Ó ÜÔÏÇÏ ÁÄÒÅÓÁ.
+int ipFound = (*user)->property.ips.Get().IsIPInIPS(sip);
+if (!ipFound)
+ {
+ printfd(__FILE__, "User %s. IP address is incorrect. IP \'%s\'\n", (*user)->GetLogin().c_str(), inet_ntostring(sip).c_str());
+ WriteServLog("User %s. IP address is incorrect. IP \'%s\'", (*user)->GetLogin().c_str(), inet_ntostring(sip).c_str());
+ SendError(sip, sport, protoVer, "ðÏÌØÚÏ×ÁÔÅÌØ ÎÅ ÏÐÏÚÎÁÎ! ðÒÏ×ÅÒØÔÅ IP ÁÄÒÅÓ.");
+ return 0;
+ }
+
+int ret = -1;
+
+switch (pn)
+ {
+ case CONN_SYN_N:
+ switch (protoVer)
+ {
+ case 6:
+ connSyn6 = (CONN_SYN_6*)(buff - offset);
+ ret = Process_CONN_SYN_6(connSyn6, &(it->second), user, sip);
+ break;
+ case 7:
+ connSyn7 = (CONN_SYN_7*)(buff - offset);
+ ret = Process_CONN_SYN_7(connSyn7, &(it->second), user, sip);
+ break;
+ case 8:
+ connSyn8 = (CONN_SYN_8*)(buff - offset);
+ ret = Process_CONN_SYN_8(connSyn8, &(it->second), user, sip);
+ break;
+ }
+
+ if (ret != 0)
+ {
+ return 0;
+ }
+ switch (protoVer)
+ {
+ case 6:
+ Send_CONN_SYN_ACK_6(iaUser, user, sip);
+ break;
+ case 7:
+ Send_CONN_SYN_ACK_7(iaUser, user, sip);
+ break;
+ case 8:
+ Send_CONN_SYN_ACK_8(iaUser, user, sip);
+ break;
+ }
+ break;
+
+ case CONN_ACK_N:
+ connAck = (CONN_ACK_6*)(buff - offset);
+ switch (protoVer)
+ {
+ case 6:
+ ret = Process_CONN_ACK_6(connAck, iaUser, user, sip);
+ break;
+ case 7:
+ ret = Process_CONN_ACK_7(connAck, iaUser, user, sip);
+ break;
+ case 8:
+ ret = Process_CONN_ACK_8((CONN_ACK_8*)(buff - offset), iaUser, user, sip);
+ break;
+ }
+
+ if (ret != 0)
+ {
+ SendError(sip, sport, protoVer, errorStr);
+ return 0;
+ }
+
+ switch (protoVer)
+ {
+ case 6:
+ Send_ALIVE_SYN_6(iaUser, sip);
+ break;
+ case 7:
+ Send_ALIVE_SYN_7(iaUser, sip);
+ break;
+ case 8:
+ Send_ALIVE_SYN_8(iaUser, sip);
+ break;
+ }
+
+ break;
+
+ // ðÒÉÂÙÌ ÏÔ×ÅÔ Ó ÐÏÄÔ×ÅÒÖÄÅÎÉÅÍ ALIVE
+ case ALIVE_ACK_N:
+ aliveAck = (ALIVE_ACK_6*)(buff - offset);
+ switch (protoVer)
+ {
+ case 6:
+ ret = Process_ALIVE_ACK_6(aliveAck, iaUser, user, sip);
+ break;
+ case 7:
+ ret = Process_ALIVE_ACK_7(aliveAck, iaUser, user, sip);
+ break;
+ case 8:
+ ret = Process_ALIVE_ACK_8((ALIVE_ACK_8*)(buff - offset), iaUser, user, sip);
+ break;
+ }
+ break;
+
+ // úÁÐÒÏÓ ÎÁ ÏÔËÌÀÞÅÎÉÅ
+ case DISCONN_SYN_N:
+
+ disconnSyn = (DISCONN_SYN_6*)(buff - offset);
+ switch (protoVer)
+ {
+ case 6:
+ ret = Process_DISCONN_SYN_6(disconnSyn, iaUser, user, sip);
+ break;
+ case 7:
+ ret = Process_DISCONN_SYN_7(disconnSyn, iaUser, user, sip);
+ break;
+ case 8:
+ ret = Process_DISCONN_SYN_8((DISCONN_SYN_8*)(buff - offset), iaUser, user, sip);
+ break;
+ }
+
+ if (ret != 0)
+ return 0;
+
+ switch (protoVer)
+ {
+ case 6:
+ Send_DISCONN_SYN_ACK_6(iaUser, sip);
+ break;
+ case 7:
+ Send_DISCONN_SYN_ACK_7(iaUser, sip);
+ break;
+ case 8:
+ Send_DISCONN_SYN_ACK_8(iaUser, sip);
+ break;
+ }
+ break;
+
+ case DISCONN_ACK_N:
+ disconnAck = (DISCONN_ACK_6*)(buff - offset);
+
+ switch (protoVer)
+ {
+ case 6:
+ ret = Process_DISCONN_ACK_6(disconnAck, iaUser, user, sip, it);
+ break;
+ case 7:
+ ret = Process_DISCONN_ACK_7(disconnAck, iaUser, user, sip, it);
+ break;
+ case 8:
+ ret = Process_DISCONN_ACK_8((DISCONN_ACK_8*)(buff - offset), iaUser, user, sip, it);
+ break;
+ }
+
+ switch (protoVer)
+ {
+ case 6:
+ Send_FIN_6(iaUser, sip, it);
+ break;
+ case 7:
+ Send_FIN_7(iaUser, sip, it);
+ break;
+ case 8:
+ Send_FIN_8(iaUser, sip, it);
+ break;
+ }
+ break;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+void AUTH_IA::DelUser(user_iter u)
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+uint32_t ip = u->GetCurrIP();
+
+if (!ip)
+ return;
+
+map<uint32_t, IA_USER>::iterator it;
+it = ip2user.find(ip);
+if (it == ip2user.end())
+ {
+ //Nothing to delete
+ printfd(__FILE__, "Nothing to delete\n");
+ return;
+ }
+
+if (it->second.user == u)
+ {
+ printfd(__FILE__, "User removed!\n");
+ it->second.user->Unauthorize(this);
+ ip2user.erase(it);
+ }
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::SendError(uint32_t ip, uint16_t port, int protoVer, const string & text)
+{
+struct sockaddr_in sendAddr;
+switch (protoVer)
+ {
+ int res;
+ case 6:
+ case 7:
+ ERR err;
+ memset(&err, 0, sizeof(ERR));
+
+ sendAddr.sin_family = AF_INET;
+ sendAddr.sin_port = htons(port);
+
+ sendAddr.sin_addr.s_addr = ip;// IP ÐÏÌØÚÏ×ÁÔÅÌÑ
+
+ err.len = 1;
+ strncpy((char*)err.type, "ERR", 16);
+ strncpy((char*)err.text, text.c_str(), MAX_MSG_LEN);
+
+ #ifdef ARCH_BE
+ SwapBytes(err.len);
+ #endif
+
+ res = sendto(listenSocket, &err, sizeof(err), 0, (struct sockaddr*)&sendAddr, sizeof(sendAddr));
+ printfd(__FILE__, "SendError %d bytes sent\n", res);
+ break;
+
+ case 8:
+ ERR_8 err8;
+ memset(&err8, 0, sizeof(ERR_8));
+
+ sendAddr.sin_family = AF_INET;
+ sendAddr.sin_port = htons(port);
+
+ sendAddr.sin_addr.s_addr = ip;// IP ÐÏÌØÚÏ×ÁÔÅÌÑ
+
+ err8.len = 256;
+ strncpy((char*)err8.type, "ERR", 16);
+ strncpy((char*)err8.text, text.c_str(), MAX_MSG_LEN);
+
+ #ifdef ARCH_BE
+ SwapBytes(err8.len);
+ #endif
+
+ res = sendto(listenSocket, &err8, sizeof(err8), 0, (struct sockaddr*)&sendAddr, sizeof(sendAddr));
+ printfd(__FILE__, "SendError_8 %d bytes sent\n", res);
+ break;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send(uint32_t ip, uint16_t port, const char * buffer, int len)
+{
+struct sockaddr_in sendAddr;
+int res;
+
+sendAddr.sin_family = AF_INET;
+sendAddr.sin_port = htons(port);
+sendAddr.sin_addr.s_addr = ip;
+
+res = sendto(listenSocket, buffer, len, 0, (struct sockaddr*)&sendAddr, sizeof(sendAddr));
+
+static struct timeval tv;
+gettimeofday(&tv, NULL);
+
+return res;
+}
+//-----------------------------------------------------------------------------
+void AUTH_IA::InitEncrypt(BLOWFISH_CTX * ctx, const string & password)
+{
+unsigned char keyL[PASSWD_LEN]; // ðÁÒÏÌØ ÄÌÑ ÛÉÆÒÏ×ËÉ
+memset(keyL, 0, PASSWD_LEN);
+strncpy((char *)keyL, password.c_str(), PASSWD_LEN);
+Blowfish_Init(ctx, keyL, PASSWD_LEN);
+}
+//-----------------------------------------------------------------------------
+void AUTH_IA::Decrypt(BLOWFISH_CTX * ctx, char * dst, const char * src, int len8)
+{
+// len8 - ÄÌÉÎÁ × 8-ÍÉ ÂÁÊÔÏ×ÙÈ ÂÌÏËÁÈ
+
+for (int i = 0; i < len8; i++)
+ DecodeString(dst + i * 8, src + i * 8, ctx);
+}
+//-----------------------------------------------------------------------------
+void AUTH_IA::Encrypt(BLOWFISH_CTX * ctx, char * dst, const char * src, int len8)
+{
+// len8 - ÄÌÉÎÁ × 8-ÍÉ ÂÁÊÔÏ×ÙÈ ÂÌÏËÁÈ
+
+for (int i = 0; i < len8; i++)
+ EncodeString(dst + i * 8, src + i * 8, ctx);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::SendMessage(const STG_MSG & msg, uint32_t ip) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+printfd(__FILE__, "SendMessage userIP=%s\n", inet_ntostring(ip).c_str());
+
+map<uint32_t, IA_USER>::iterator it;
+it = ip2user.find(ip);
+if (it == ip2user.end())
+ {
+ errorStr = "Unknown user.";
+ return -1;
+ }
+it->second.messagesToSend.push_back(msg);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::RealSendMessage6(const STG_MSG & msg, uint32_t ip, IA_USER & user)
+{
+printfd(__FILE__, "RealSendMessage 6 user=%s\n", user.user->GetLogin().c_str());
+
+char buffer[256];
+INFO_6 info;
+
+memset(&info, 0, sizeof(INFO_6));
+
+info.len = 256;
+strncpy((char*)info.type, "INFO", 16);
+info.infoType = 'I';
+strncpy((char*)info.text, msg.text.c_str(), 235);
+info.text[234] = 0;
+
+size_t len = info.len;
+#ifdef ARCH_BE
+SwapBytes(info.len);
+#endif
+
+memcpy(buffer, &info, sizeof(INFO_6));
+Encrypt(&user.ctx, buffer, buffer, len / 8);
+Send(ip, iaSettings.GetUserPort(), buffer, len);
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::RealSendMessage7(const STG_MSG & msg, uint32_t ip, IA_USER & user)
+{
+printfd(__FILE__, "RealSendMessage 7 user=%s\n", user.user->GetLogin().c_str());
+
+char buffer[300];
+INFO_7 info;
+
+memset(&info, 0, sizeof(INFO_7));
+
+info.len = 264;
+strncpy((char*)info.type, "INFO_7", 16);
+info.infoType = msg.header.type;
+info.showTime = msg.header.showTime;
+
+info.sendTime = msg.header.creationTime;
+
+size_t len = info.len;
+#ifdef ARCH_BE
+SwapBytes(info.len);
+SwapBytes(info.sendTime);
+#endif
+
+strncpy((char*)info.text, msg.text.c_str(), MAX_MSG_LEN - 1);
+info.text[MAX_MSG_LEN - 1] = 0;
+
+memcpy(buffer, &info, sizeof(INFO_7));
+
+Encrypt(&user.ctx, buffer, buffer, len / 8);
+Send(ip, iaSettings.GetUserPort(), buffer, len);
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::RealSendMessage8(const STG_MSG & msg, uint32_t ip, IA_USER & user)
+{
+printfd(__FILE__, "RealSendMessage 8 user=%s\n", user.user->GetLogin().c_str());
+
+char buffer[1500];
+memset(buffer, 0, sizeof(buffer));
+
+INFO_8 info;
+
+memset(&info, 0, sizeof(INFO_8));
+
+info.len = 1056;
+strncpy((char*)info.type, "INFO_8", 16);
+info.infoType = msg.header.type;
+info.showTime = msg.header.showTime;
+info.sendTime = msg.header.creationTime;
+
+strncpy((char*)info.text, msg.text.c_str(), IA_MAX_MSG_LEN_8 - 1);
+info.text[IA_MAX_MSG_LEN_8 - 1] = 0;
+
+size_t len = info.len;
+#ifdef ARCH_BE
+SwapBytes(info.len);
+SwapBytes(info.sendTime);
+#endif
+
+memcpy(buffer, &info, sizeof(INFO_8));
+
+Encrypt(&user.ctx, buffer, buffer, len / 8);
+Send(ip, user.port, buffer, len);
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_CONN_SYN_6(CONN_SYN_6 *, IA_USER * iaUser, user_iter *, uint32_t)
+{
+if (!(iaUser->phase.GetPhase() == 1 || iaUser->phase.GetPhase() == 3))
+ return -1;
+
+enabledDirs = 0xFFffFFff;
+
+iaUser->phase.SetPhase2();
+printfd(__FILE__, "Phase changed from %d to 2. Reason: CONN_SYN_6\n", iaUser->phase.GetPhase());
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_CONN_SYN_7(CONN_SYN_7 * connSyn, IA_USER * iaUser, user_iter * user, uint32_t sip)
+{
+return Process_CONN_SYN_6(connSyn, iaUser, user, sip);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_CONN_SYN_8(CONN_SYN_8 * connSyn, IA_USER * iaUser, user_iter * user, uint32_t sip)
+{
+#ifdef ARCH_BE
+SwapBytes(connSyn->dirs);
+#endif
+int ret = Process_CONN_SYN_6((CONN_SYN_6*)connSyn, iaUser, user, sip);
+enabledDirs = connSyn->dirs;
+return ret;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_CONN_ACK_6(CONN_ACK_6 * connAck, IA_USER * iaUser, user_iter *, uint32_t sip)
+{
+#ifdef ARCH_BE
+SwapBytes(connAck->len);
+SwapBytes(connAck->rnd);
+#endif
+printfd( __FILE__, "CONN_ACK_6 %s\n", connAck->type);
+// ÕÓÔÁÎÏ×ÉÔØ ÎÏ×ÕÀ ÆÁÚÕ É ×ÒÅÍÑ É ÒÁÚÒÅÛÉÔØ ÉÎÅÔ
+if ((iaUser->phase.GetPhase() == 2) && (connAck->rnd == iaUser->rnd + 1))
+ {
+ iaUser->phase.UpdateTime();
+
+ iaUser->lastSendAlive = iaUser->phase.GetTime();
+ if (iaUser->user->Authorize(sip, "", enabledDirs, this) == 0)
+ {
+ iaUser->phase.SetPhase3();
+ printfd(__FILE__, "Phase changed from 2 to 3. Reason: CONN_ACK_6\n");
+ return 0;
+ }
+ else
+ {
+ errorStr = iaUser->user->GetStrError();
+ iaUser->phase.SetPhase1();
+ printfd(__FILE__, "Phase changed from 2 to 1. Reason: failed to authorize user\n");
+ return -1;
+ }
+ }
+printfd(__FILE__, "Invalid phase or control number. Phase: %d. Control number: %d\n", iaUser->phase.GetPhase(), connAck->rnd);
+return -1;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_CONN_ACK_7(CONN_ACK_7 * connAck, IA_USER * iaUser, user_iter * user, uint32_t sip)
+{
+return Process_CONN_ACK_6(connAck, iaUser, user, sip);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_CONN_ACK_8(CONN_ACK_8 * connAck, IA_USER * iaUser, user_iter *, uint32_t sip)
+{
+#ifdef ARCH_BE
+SwapBytes(connAck->len);
+SwapBytes(connAck->rnd);
+#endif
+printfd( __FILE__, "CONN_ACK_8 %s\n", connAck->type);
+
+if ((iaUser->phase.GetPhase() == 2) && (connAck->rnd == iaUser->rnd + 1))
+ {
+ iaUser->phase.UpdateTime();
+ iaUser->lastSendAlive = iaUser->phase.GetTime();
+ if (iaUser->user->Authorize(sip, "", enabledDirs, this) == 0)
+ {
+ iaUser->phase.SetPhase3();
+ printfd(__FILE__, "Phase changed from 2 to 3. Reason: CONN_ACK_8\n");
+ return 0;
+ }
+ else
+ {
+ errorStr = iaUser->user->GetStrError();
+ iaUser->phase.SetPhase1();
+ printfd(__FILE__, "Phase changed from 2 to 1. Reason: failed to authorize user\n");
+ return -1;
+ }
+ }
+printfd(__FILE__, "Invalid phase or control number. Phase: %d. Control number: %d\n", iaUser->phase.GetPhase(), connAck->rnd);
+return -1;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_ALIVE_ACK_6(ALIVE_ACK_6 * aliveAck, IA_USER * iaUser, user_iter *, uint32_t)
+{
+#ifdef ARCH_BE
+SwapBytes(aliveAck->len);
+SwapBytes(aliveAck->rnd);
+#endif
+printfd(__FILE__, "ALIVE_ACK_6\n");
+if ((iaUser->phase.GetPhase() == 3) && (aliveAck->rnd == iaUser->rnd + 1))
+ {
+ iaUser->phase.UpdateTime();
+ #ifdef IA_DEBUG
+ iaUser->aliveSent = false;
+ #endif
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_ALIVE_ACK_7(ALIVE_ACK_7 * aliveAck, IA_USER * iaUser, user_iter * user, uint32_t sip)
+{
+return Process_ALIVE_ACK_6(aliveAck, iaUser, user, sip);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_ALIVE_ACK_8(ALIVE_ACK_8 * aliveAck, IA_USER * iaUser, user_iter *, uint32_t)
+{
+#ifdef ARCH_BE
+SwapBytes(aliveAck->len);
+SwapBytes(aliveAck->rnd);
+#endif
+printfd(__FILE__, "ALIVE_ACK_8\n");
+if ((iaUser->phase.GetPhase() == 3) && (aliveAck->rnd == iaUser->rnd + 1))
+ {
+ iaUser->phase.UpdateTime();
+ #ifdef IA_DEBUG
+ iaUser->aliveSent = false;
+ #endif
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_DISCONN_SYN_6(DISCONN_SYN_6 *, IA_USER * iaUser, user_iter *, uint32_t)
+{
+printfd(__FILE__, "DISCONN_SYN_6\n");
+if (iaUser->phase.GetPhase() != 3)
+ {
+ printfd(__FILE__, "Invalid phase. Expected 3, actual %d\n", iaUser->phase.GetPhase());
+ errorStr = "Incorrect request DISCONN_SYN";
+ return -1;
+ }
+
+iaUser->phase.SetPhase4();
+printfd(__FILE__, "Phase changed from 3 to 4. Reason: DISCONN_SYN_6\n");
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_DISCONN_SYN_7(DISCONN_SYN_7 * disconnSyn, IA_USER * iaUser, user_iter * user, uint32_t sip)
+{
+return Process_DISCONN_SYN_6(disconnSyn, iaUser, user, sip);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_DISCONN_SYN_8(DISCONN_SYN_8 *, IA_USER * iaUser, user_iter *, uint32_t)
+{
+if (iaUser->phase.GetPhase() != 3)
+ {
+ errorStr = "Incorrect request DISCONN_SYN";
+ printfd(__FILE__, "Invalid phase. Expected 3, actual %d\n", iaUser->phase.GetPhase());
+ return -1;
+ }
+
+iaUser->phase.SetPhase4();
+printfd(__FILE__, "Phase changed from 3 to 4. Reason: DISCONN_SYN_6\n");
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_DISCONN_ACK_6(DISCONN_ACK_6 * disconnAck,
+ IA_USER * iaUser,
+ user_iter *,
+ uint32_t,
+ map<uint32_t, IA_USER>::iterator)
+{
+#ifdef ARCH_BE
+SwapBytes(disconnAck->len);
+SwapBytes(disconnAck->rnd);
+#endif
+printfd(__FILE__, "DISCONN_ACK_6\n");
+if (!((iaUser->phase.GetPhase() == 4) && (disconnAck->rnd == iaUser->rnd + 1)))
+ {
+ printfd(__FILE__, "Invalid phase or control number. Phase: %d. Control number: %d\n", iaUser->phase.GetPhase(), disconnAck->rnd);
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_DISCONN_ACK_7(DISCONN_ACK_7 * disconnAck, IA_USER * iaUser, user_iter * user, uint32_t sip, map<uint32_t, IA_USER>::iterator it)
+{
+return Process_DISCONN_ACK_6(disconnAck, iaUser, user, sip, it);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_DISCONN_ACK_8(DISCONN_ACK_8 * disconnAck, IA_USER * iaUser, user_iter *, uint32_t, map<uint32_t, IA_USER>::iterator)
+{
+#ifdef ARCH_BE
+SwapBytes(disconnAck->len);
+SwapBytes(disconnAck->rnd);
+#endif
+printfd(__FILE__, "DISCONN_ACK_8\n");
+if (!((iaUser->phase.GetPhase() == 4) && (disconnAck->rnd == iaUser->rnd + 1)))
+ {
+ printfd(__FILE__, "Invalid phase or control number. Phase: %d. Control number: %d\n", iaUser->phase.GetPhase(), disconnAck->rnd);
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send_CONN_SYN_ACK_6(IA_USER * iaUser, user_iter *, uint32_t sip)
+{
+//+++ Fill static data in connSynAck +++
+// TODO Move this code. It must be executed only once
+connSynAck6.len = Min8(sizeof(CONN_SYN_ACK_6));
+strcpy((char*)connSynAck6.type, "CONN_SYN_ACK");
+for (int j = 0; j < DIR_NUM; j++)
+ {
+ strncpy((char*)connSynAck6.dirName[j],
+ stgSettings->GetDirName(j).c_str(),
+ sizeof(string16));
+
+ connSynAck6.dirName[j][sizeof(string16) - 1] = 0;
+ }
+//--- Fill static data in connSynAck ---
+
+iaUser->rnd = random();
+connSynAck6.rnd = iaUser->rnd;
+
+connSynAck6.userTimeOut = iaSettings.GetUserTimeout();
+connSynAck6.aliveDelay = iaSettings.GetUserDelay();
+
+#ifdef ARCH_BE
+SwapBytes(connSynAck6.len);
+SwapBytes(connSynAck6.rnd);
+SwapBytes(connSynAck6.userTimeOut);
+SwapBytes(connSynAck6.aliveDelay);
+#endif
+
+Encrypt(&iaUser->ctx, (char*)&connSynAck6, (char*)&connSynAck6, Min8(sizeof(CONN_SYN_ACK_6))/8);
+return Send(sip, iaSettings.GetUserPort(), (char*)&connSynAck6, Min8(sizeof(CONN_SYN_ACK_6)));;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send_CONN_SYN_ACK_7(IA_USER * iaUser, user_iter * user, uint32_t sip)
+{
+return Send_CONN_SYN_ACK_6(iaUser, user, sip);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send_CONN_SYN_ACK_8(IA_USER * iaUser, user_iter *, uint32_t sip)
+{
+strcpy((char*)connSynAck8.hdr.magic, IA_ID);
+connSynAck8.hdr.protoVer[0] = 0;
+connSynAck8.hdr.protoVer[1] = 8;
+
+//+++ Fill static data in connSynAck +++
+// TODO Move this code. It must be executed only once
+connSynAck8.len = Min8(sizeof(CONN_SYN_ACK_8));
+strcpy((char*)connSynAck8.type, "CONN_SYN_ACK");
+for (int j = 0; j < DIR_NUM; j++)
+ {
+ strncpy((char*)connSynAck8.dirName[j],
+ stgSettings->GetDirName(j).c_str(),
+ sizeof(string16));
+
+ connSynAck8.dirName[j][sizeof(string16) - 1] = 0;
+ }
+//--- Fill static data in connSynAck ---
+
+iaUser->rnd = random();
+connSynAck8.rnd = iaUser->rnd;
+
+connSynAck8.userTimeOut = iaSettings.GetUserTimeout();
+connSynAck8.aliveDelay = iaSettings.GetUserDelay();
+
+#ifdef ARCH_BE
+SwapBytes(connSynAck8.len);
+SwapBytes(connSynAck8.rnd);
+SwapBytes(connSynAck8.userTimeOut);
+SwapBytes(connSynAck8.aliveDelay);
+#endif
+
+Encrypt(&iaUser->ctx, (char*)&connSynAck8, (char*)&connSynAck8, Min8(sizeof(CONN_SYN_ACK_8))/8);
+return Send(sip, iaUser->port, (char*)&connSynAck8, Min8(sizeof(CONN_SYN_ACK_8)));
+//return Send(sip, iaUser->port, (char*)&connSynAck8, 384);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send_ALIVE_SYN_6(IA_USER * iaUser, uint32_t sip)
+{
+aliveSyn6.len = Min8(sizeof(ALIVE_SYN_6));
+aliveSyn6.rnd = iaUser->rnd = random();
+
+strcpy((char*)aliveSyn6.type, "ALIVE_SYN");
+
+for (int i = 0; i < DIR_NUM; i++)
+ {
+ aliveSyn6.md[i] = iaUser->user->property.down.Get()[i];
+ aliveSyn6.mu[i] = iaUser->user->property.up.Get()[i];
+
+ aliveSyn6.sd[i] = iaUser->user->GetSessionDownload()[i];
+ aliveSyn6.su[i] = iaUser->user->GetSessionUpload()[i];
+ }
+
+//TODO
+int dn = iaSettings.GetFreeMbShowType();
+const TARIFF * tf = iaUser->user->GetTariff();
+
+if (dn < DIR_NUM)
+ {
+ double p = tf->GetPriceWithTraffType(aliveSyn6.mu[dn],
+ aliveSyn6.md[dn],
+ dn,
+ stgTime);
+ p *= (1024 * 1024);
+ if (p == 0)
+ {
+ snprintf((char*)aliveSyn6.freeMb, IA_FREEMB_LEN, "---");
+ }
+ else
+ {
+ double fmb = iaUser->user->property.freeMb;
+ fmb = fmb < 0 ? 0 : fmb;
+ snprintf((char*)aliveSyn6.freeMb, IA_FREEMB_LEN, "%.3f", fmb / p);
+ }
+ }
+else
+ {
+ if (freeMbNone == iaSettings.GetFreeMbShowType())
+ {
+ aliveSyn6.freeMb[0] = 0;
+ }
+ else
+ {
+ double fmb = iaUser->user->property.freeMb;
+ fmb = fmb < 0 ? 0 : fmb;
+ snprintf((char*)aliveSyn6.freeMb, IA_FREEMB_LEN, "C%.3f", fmb);
+ }
+ }
+
+#ifdef IA_DEBUG
+if (iaUser->aliveSent)
+ {
+ printfd(__FILE__, "========= ALIVE_ACK_6(7) TIMEOUT !!! %s =========\n", iaUser->user->GetLogin().c_str());
+ }
+iaUser->aliveSent = true;
+#endif
+
+aliveSyn6.cash =(int64_t) (iaUser->user->property.cash.Get() * 1000.0);
+if (!stgSettings->GetShowFeeInCash())
+ aliveSyn6.cash -= (int64_t)(tf->GetFee() * 1000.0);
+
+#ifdef ARCH_BE
+SwapBytes(aliveSyn6.len);
+SwapBytes(aliveSyn6.rnd);
+SwapBytes(aliveSyn6.cash);
+for (int i = 0; i < DIR_NUM; ++i)
+ {
+ SwapBytes(aliveSyn6.mu[i]);
+ SwapBytes(aliveSyn6.md[i]);
+ SwapBytes(aliveSyn6.su[i]);
+ SwapBytes(aliveSyn6.sd[i]);
+ }
+#endif
+
+Encrypt(&(iaUser->ctx), (char*)&aliveSyn6, (char*)&aliveSyn6, Min8(sizeof(aliveSyn6))/8);
+return Send(sip, iaSettings.GetUserPort(), (char*)&aliveSyn6, Min8(sizeof(aliveSyn6)));
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send_ALIVE_SYN_7(IA_USER * iaUser, uint32_t sip)
+{
+return Send_ALIVE_SYN_6(iaUser, sip);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send_ALIVE_SYN_8(IA_USER * iaUser, uint32_t sip)
+{
+strcpy((char*)aliveSyn8.hdr.magic, IA_ID);
+aliveSyn8.hdr.protoVer[0] = 0;
+aliveSyn8.hdr.protoVer[1] = 8;
+
+aliveSyn8.len = Min8(sizeof(ALIVE_SYN_8));
+aliveSyn8.rnd = iaUser->rnd = random();
+
+strcpy((char*)aliveSyn8.type, "ALIVE_SYN");
+
+for (int i = 0; i < DIR_NUM; i++)
+ {
+ aliveSyn8.md[i] = iaUser->user->property.down.Get()[i];
+ aliveSyn8.mu[i] = iaUser->user->property.up.Get()[i];
+
+ aliveSyn8.sd[i] = iaUser->user->GetSessionDownload()[i];
+ aliveSyn8.su[i] = iaUser->user->GetSessionUpload()[i];
+ }
+
+//TODO
+int dn = iaSettings.GetFreeMbShowType();
+
+if (dn < DIR_NUM)
+ {
+ const TARIFF * tf = iaUser->user->GetTariff();
+ double p = tf->GetPriceWithTraffType(aliveSyn8.mu[dn],
+ aliveSyn8.md[dn],
+ dn,
+ stgTime);
+ p *= (1024 * 1024);
+ if (p == 0)
+ {
+ snprintf((char*)aliveSyn8.freeMb, IA_FREEMB_LEN, "---");
+ }
+ else
+ {
+ double fmb = iaUser->user->property.freeMb;
+ fmb = fmb < 0 ? 0 : fmb;
+ snprintf((char*)aliveSyn8.freeMb, IA_FREEMB_LEN, "%.3f", fmb / p);
+ }
+ }
+else
+ {
+ if (freeMbNone == iaSettings.GetFreeMbShowType())
+ {
+ aliveSyn8.freeMb[0] = 0;
+ }
+ else
+ {
+ double fmb = iaUser->user->property.freeMb;
+ fmb = fmb < 0 ? 0 : fmb;
+ snprintf((char*)aliveSyn8.freeMb, IA_FREEMB_LEN, "C%.3f", fmb);
+ }
+ }
+
+#ifdef IA_DEBUG
+if (iaUser->aliveSent)
+ {
+ printfd(__FILE__, "========= ALIVE_ACK_8 TIMEOUT !!! =========\n");
+ }
+iaUser->aliveSent = true;
+#endif
+
+const TARIFF * tf = iaUser->user->GetTariff();
+
+aliveSyn8.cash =(int64_t) (iaUser->user->property.cash.Get() * 1000.0);
+if (!stgSettings->GetShowFeeInCash())
+ aliveSyn8.cash -= (int64_t)(tf->GetFee() * 1000.0);
+
+#ifdef ARCH_BE
+SwapBytes(aliveSyn8.len);
+SwapBytes(aliveSyn8.rnd);
+SwapBytes(aliveSyn8.cash);
+SwapBytes(aliveSyn8.status);
+for (int i = 0; i < DIR_NUM; ++i)
+ {
+ SwapBytes(aliveSyn8.mu[i]);
+ SwapBytes(aliveSyn8.md[i]);
+ SwapBytes(aliveSyn8.su[i]);
+ SwapBytes(aliveSyn8.sd[i]);
+ }
+#endif
+
+Encrypt(&(iaUser->ctx), (char*)&aliveSyn8, (char*)&aliveSyn8, Min8(sizeof(aliveSyn8))/8);
+return Send(sip, iaUser->port, (char*)&aliveSyn8, Min8(sizeof(aliveSyn8)));
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send_DISCONN_SYN_ACK_6(IA_USER * iaUser, uint32_t sip)
+{
+disconnSynAck6.len = Min8(sizeof(DISCONN_SYN_ACK_6));
+strcpy((char*)disconnSynAck6.type, "DISCONN_SYN_ACK");
+disconnSynAck6.rnd = iaUser->rnd = random();
+
+#ifdef ARCH_BE
+SwapBytes(disconnSynAck6.len);
+SwapBytes(disconnSynAck6.rnd);
+#endif
+
+Encrypt(&iaUser->ctx, (char*)&disconnSynAck6, (char*)&disconnSynAck6, Min8(sizeof(disconnSynAck6))/8);
+return Send(sip, iaSettings.GetUserPort(), (char*)&disconnSynAck6, Min8(sizeof(disconnSynAck6)));
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send_DISCONN_SYN_ACK_7(IA_USER * iaUser, uint32_t sip)
+{
+return Send_DISCONN_SYN_ACK_6(iaUser, sip);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send_DISCONN_SYN_ACK_8(IA_USER * iaUser, uint32_t sip)
+{
+strcpy((char*)disconnSynAck8.hdr.magic, IA_ID);
+disconnSynAck8.hdr.protoVer[0] = 0;
+disconnSynAck8.hdr.protoVer[1] = 8;
+
+disconnSynAck8.len = Min8(sizeof(DISCONN_SYN_ACK_8));
+strcpy((char*)disconnSynAck8.type, "DISCONN_SYN_ACK");
+disconnSynAck8.rnd = iaUser->rnd = random();
+
+#ifdef ARCH_BE
+SwapBytes(disconnSynAck8.len);
+SwapBytes(disconnSynAck8.rnd);
+#endif
+
+Encrypt(&iaUser->ctx, (char*)&disconnSynAck8, (char*)&disconnSynAck8, Min8(sizeof(disconnSynAck8))/8);
+return Send(sip, iaUser->port, (char*)&disconnSynAck8, Min8(sizeof(disconnSynAck8)));
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send_FIN_6(IA_USER * iaUser, uint32_t sip, map<uint32_t, IA_USER>::iterator it)
+{
+fin6.len = Min8(sizeof(FIN_6));
+strcpy((char*)fin6.type, "FIN");
+strcpy((char*)fin6.ok, "OK");
+
+#ifdef ARCH_BE
+SwapBytes(fin6.len);
+#endif
+
+Encrypt(&iaUser->ctx, (char*)&fin6, (char*)&fin6, Min8(sizeof(fin6))/8);
+
+iaUser->user->Unauthorize(this);
+
+int ret = Send(sip, iaSettings.GetUserPort(), (char*)&fin6, Min8(sizeof(fin6)));
+ip2user.erase(it);
+return ret;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send_FIN_7(IA_USER * iaUser, uint32_t sip, map<uint32_t, IA_USER>::iterator it)
+{
+return Send_FIN_6(iaUser, sip, it);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send_FIN_8(IA_USER * iaUser, uint32_t sip, map<uint32_t, IA_USER>::iterator it)
+{
+strcpy((char*)fin8.hdr.magic, IA_ID);
+fin8.hdr.protoVer[0] = 0;
+fin8.hdr.protoVer[1] = 8;
+
+fin8.len = Min8(sizeof(FIN_8));
+strcpy((char*)fin8.type, "FIN");
+strcpy((char*)fin8.ok, "OK");
+
+#ifdef ARCH_BE
+SwapBytes(fin8.len);
+#endif
+
+Encrypt(&iaUser->ctx, (char*)&fin8, (char*)&fin8, Min8(sizeof(fin8))/8);
+
+iaUser->user->Unauthorize(this);
+
+int ret = Send(sip, iaUser->port, (char*)&fin8, Min8(sizeof(fin8)));
+ip2user.erase(it);
+return ret;
+}
+//-----------------------------------------------------------------------------
+bool AUTH_IA::WaitPackets(int sd) const
+{
+fd_set rfds;
+FD_ZERO(&rfds);
+FD_SET(sd, &rfds);
+
+struct timeval tv;
+tv.tv_sec = 0;
+tv.tv_usec = 500000;
+
+int res = select(sd + 1, &rfds, NULL, NULL, &tv);
+if (res == -1) // Error
+ {
+ if (errno != EINTR)
+ {
+ printfd(__FILE__, "Error on select: '%s'\n", strerror(errno));
+ }
+ return false;
+ }
+
+if (res == 0) // Timeout
+ {
+ return false;
+ }
+
+return true;
+}
--- /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>
+ */
+
+/*
+ $Revision: 1.34 $
+ $Date: 2010/09/10 06:39:19 $
+ $Author: faust $
+ */
+
+#ifndef INETACCESS_H
+#define INETACCESS_H
+
+#include <sys/time.h>
+#include <pthread.h>
+#include <cstring>
+#include <ctime>
+#include <string>
+#include <map>
+#include <functional>
+#include <utility>
+
+#include "os_int.h"
+#include "base_auth.h"
+#include "base_store.h"
+#include "notifer.h"
+#include "user_ips.h"
+#include "../../../user.h"
+#include "../../../users.h"
+#include "ia_packets.h"
+#include "blowfish.h"
+#include "stg_logger.h"
+#include "utime.h"
+
+using namespace std;
+
+extern "C" BASE_PLUGIN * GetPlugin();
+
+#define IA_PROTO_VER (6)
+
+//#define IA_DEBUG (1)
+//#define IA_PHASE_DEBUG (1)
+
+class AUTH_IA;
+//-----------------------------------------------------------------------------
+enum FREEMB
+{
+ freeMb0 = 0,
+ freeMb1,
+ freeMb2,
+ freeMb3,
+ freeMb4,
+ freeMb5,
+ freeMb6,
+ freeMb7,
+ freeMb8,
+ freeMb9,
+ freeMb10,
+ freeMb11,
+ freeMb12,
+ freeMb13,
+ freeMb14,
+ freeMb15,
+ freeMb16,
+ freeMb17,
+ freeMb18,
+ freeMb19,
+ freeMbCash = 100,
+ freeMbNone = 101
+};
+//-----------------------------------------------------------------------------
+class IA_PHASE
+{
+public:
+ IA_PHASE();
+ ~IA_PHASE();
+
+ void SetPhase1();
+ void SetPhase2();
+ void SetPhase3();
+ void SetPhase4();
+ void SetPhase5();
+ int GetPhase() const;
+
+ void UpdateTime();
+ const UTIME & GetTime() const;
+
+ #ifdef IA_PHASE_DEBUG
+ void SetUserLogin(const string & login);
+ void SetLogFileName(const string & logFileName);
+ #endif
+
+private:
+ int phase;
+ UTIME phaseTime;
+
+ #ifdef IA_PHASE_DEBUG
+ void WritePhaseChange(int newPhase);
+ string log;
+ string login;
+ FILE * flog;
+ #endif
+};
+//-----------------------------------------------------------------------------
+struct IA_USER
+{
+ IA_USER()
+ {
+ //phase = 1;
+ //phaseTime = 0;
+ lastSendAlive = 0;
+ rnd = random();
+ port = 0;
+ password = "NO PASSWORD";
+ // +++ Preparing CTX +++
+ unsigned char keyL[PASSWD_LEN]; // ðÁÒÏÌØ ÄÌÑ ÛÉÆÒÏ×ËÉ
+ memset(keyL, 0, PASSWD_LEN);
+ strncpy((char *)keyL, password.c_str(), PASSWD_LEN);
+ Blowfish_Init(&ctx, keyL, PASSWD_LEN);
+ // --- Preparing CTX ---
+ #ifdef IA_DEBUG
+ aliveSent = false;
+ #endif
+ };
+
+ IA_USER(const IA_USER & u)
+ {
+ user = u.user;
+ phase = u.phase;
+ //phaseTime = u.phaseTime;
+ lastSendAlive = u.lastSendAlive;
+ rnd = u.rnd;
+ password = u.password;
+ protoVer = u.protoVer;
+ port = u.port;
+ #ifdef IA_DEBUG
+ aliveSent = u.aliveSent;
+ #endif
+ memcpy(&ctx, &u.ctx, sizeof(BLOWFISH_CTX));
+ };
+
+ user_iter user;
+ //int phase;
+ //UTIME phaseTime;
+ IA_PHASE phase;
+ UTIME lastSendAlive;
+ uint32_t rnd;
+ uint16_t port;
+ BLOWFISH_CTX ctx;
+ list<STG_MSG> messagesToSend;
+ int protoVer;
+ string password;
+ #ifdef IA_DEBUG
+ bool aliveSent;
+ #endif
+};
+//-----------------------------------------------------------------------------
+class AUTH_IA_SETTINGS
+{
+public:
+ AUTH_IA_SETTINGS();
+ virtual ~AUTH_IA_SETTINGS() {};
+ const string& GetStrError() const { return errorStr; };
+ int ParseSettings(const MODULE_SETTINGS & s);
+ int GetUserDelay() const { return userDelay; };
+ int GetUserTimeout() const { return userTimeout; };
+ int GetUserPort() const { return port; };
+ FREEMB GetFreeMbShowType() const { return freeMbShowType; };
+
+private:
+ int ParseIntInRange(const string & str, int min, int max, int * val);
+ int userDelay;
+ int userTimeout;
+ uint16_t port;
+ string errorStr;
+ FREEMB freeMbShowType;
+};
+//-----------------------------------------------------------------------------
+class AUTH_IA :public BASE_AUTH
+{
+public:
+ AUTH_IA();
+ virtual ~AUTH_IA();
+
+ void SetUsers(USERS * u) { users = u; };
+ void SetTariffs(TARIFFS *){};
+ void SetAdmins(ADMINS *){};
+ void SetTraffcounter(TRAFFCOUNTER *){};
+ void SetStore(BASE_STORE *){};
+ void SetStgSettings(const SETTINGS * s) { stgSettings = s; };
+ void SetSettings(const MODULE_SETTINGS & s) { settings = s; };
+ int ParseSettings();
+
+ int Start();
+ int Stop();
+ int Reload() { return 0; };
+ bool IsRunning() { return isRunningRunTimeouter || isRunningRun; };
+
+ const string & GetStrError() const { return errorStr; };
+ const string GetVersion() const { return "InetAccess authorization plugin v.1.4"; };
+ uint16_t GetStartPosition() const { return 50; };
+ uint16_t GetStopPosition() const { return 50; };
+
+ void DelUser(user_iter u);
+
+ int SendMessage(const STG_MSG & msg, uint32_t ip) const;
+
+private:
+ static void * Run(void *);
+ static void * RunTimeouter(void * d);
+ int PrepareNet();
+ int FinalizeNet();
+ int RecvData(char * buffer, int bufferSize);
+ int CheckHeader(const char * buffer, int * protoVer);
+ int PacketProcessor(char * buff, int dataLen, uint32_t sip, uint16_t sport, int protoVer, user_iter * user);
+
+ int Process_CONN_SYN_6(CONN_SYN_6 * connSyn, IA_USER * iaUser, user_iter * user, uint32_t sip);
+ int Process_CONN_SYN_7(CONN_SYN_7 * connSyn, IA_USER * iaUser, user_iter * user, uint32_t sip);
+ int Process_CONN_SYN_8(CONN_SYN_8 * connSyn, IA_USER * iaUser, user_iter * user, uint32_t sip);
+
+ int Process_CONN_ACK_6(CONN_ACK_6 * connAck, IA_USER * iaUser, user_iter * user, uint32_t sip);
+ int Process_CONN_ACK_7(CONN_ACK_7 * connAck, IA_USER * iaUser, user_iter * user, uint32_t sip);
+ int Process_CONN_ACK_8(CONN_ACK_8 * connAck, IA_USER * iaUser, user_iter * user, uint32_t sip);
+
+ int Process_ALIVE_ACK_6(ALIVE_ACK_6 * aliveAck, IA_USER * iaUser, user_iter * user, uint32_t sip);
+ int Process_ALIVE_ACK_7(ALIVE_ACK_7 * aliveAck, IA_USER * iaUser, user_iter * user, uint32_t sip);
+ int Process_ALIVE_ACK_8(ALIVE_ACK_8 * aliveAck, IA_USER * iaUser, user_iter * user, uint32_t sip);
+
+ int Process_DISCONN_SYN_6(DISCONN_SYN_6 * disconnSyn, IA_USER * iaUser, user_iter * user, uint32_t sip);
+ int Process_DISCONN_SYN_7(DISCONN_SYN_7 * disconnSyn, IA_USER * iaUser, user_iter * user, uint32_t sip);
+ int Process_DISCONN_SYN_8(DISCONN_SYN_8 * disconnSyn, IA_USER * iaUser, user_iter * user, uint32_t sip);
+
+ int Process_DISCONN_ACK_6(DISCONN_ACK_6 * disconnSyn,
+ IA_USER * iaUser,
+ user_iter * user,
+ uint32_t sip,
+ map<uint32_t, IA_USER>::iterator it);
+ int Process_DISCONN_ACK_7(DISCONN_ACK_7 * disconnSyn,
+ IA_USER * iaUser,
+ user_iter * user,
+ uint32_t sip,
+ map<uint32_t, IA_USER>::iterator it);
+ int Process_DISCONN_ACK_8(DISCONN_ACK_8 * disconnSyn,
+ IA_USER * iaUser,
+ user_iter * user,
+ uint32_t sip,
+ map<uint32_t, IA_USER>::iterator it);
+
+ int Send_CONN_SYN_ACK_6(IA_USER * iaUser, user_iter * user, uint32_t sip);
+ int Send_CONN_SYN_ACK_7(IA_USER * iaUser, user_iter * user, uint32_t sip);
+ int Send_CONN_SYN_ACK_8(IA_USER * iaUser, user_iter * user, uint32_t sip);
+
+ int Send_ALIVE_SYN_6(IA_USER * iaUser, uint32_t sip);
+ int Send_ALIVE_SYN_7(IA_USER * iaUser, uint32_t sip);
+ int Send_ALIVE_SYN_8(IA_USER * iaUser, uint32_t sip);
+
+ int Send_DISCONN_SYN_ACK_6(IA_USER * iaUser, uint32_t sip);
+ int Send_DISCONN_SYN_ACK_7(IA_USER * iaUser, uint32_t sip);
+ int Send_DISCONN_SYN_ACK_8(IA_USER * iaUser, uint32_t sip);
+
+ int Send_FIN_6(IA_USER * iaUser, uint32_t sip, map<uint32_t, IA_USER>::iterator it);
+ int Send_FIN_7(IA_USER * iaUser, uint32_t sip, map<uint32_t, IA_USER>::iterator it);
+ int Send_FIN_8(IA_USER * iaUser, uint32_t sip, map<uint32_t, IA_USER>::iterator it);
+
+ int Timeouter();
+
+ void InitEncrypt(BLOWFISH_CTX * ctx, const string & password);
+ void Decrypt(BLOWFISH_CTX * ctx, char * dst, const char * src, int len8);
+ void Encrypt(BLOWFISH_CTX * ctx, char * dst, const char * src, int len8);
+
+ int SendError(uint32_t ip, uint16_t port, int protoVer, const string & text);
+ int Send(uint32_t ip, uint16_t port, const char * buffer, int len);
+ int RealSendMessage6(const STG_MSG & msg, uint32_t ip, IA_USER & user);
+ int RealSendMessage7(const STG_MSG & msg, uint32_t ip, IA_USER & user);
+ int RealSendMessage8(const STG_MSG & msg, uint32_t ip, IA_USER & user);
+
+ bool WaitPackets(int sd) const;
+
+ BLOWFISH_CTX ctxS; //for loginS
+
+ mutable string errorStr;
+ AUTH_IA_SETTINGS iaSettings;
+ MODULE_SETTINGS settings;
+
+ bool nonstop;
+
+ bool isRunningRun;
+ bool isRunningRunTimeouter;
+
+ USERS * users;
+ const SETTINGS * stgSettings;
+
+ mutable map<uint32_t, IA_USER> ip2user;
+
+ pthread_t recvThread;
+ pthread_t timeouterThread;
+ mutable pthread_mutex_t mutex;
+
+ int listenSocket;
+
+ CONN_SYN_ACK_6 connSynAck6;
+ CONN_SYN_ACK_8 connSynAck8;
+
+ DISCONN_SYN_ACK_6 disconnSynAck6;
+ DISCONN_SYN_ACK_8 disconnSynAck8;
+
+ ALIVE_SYN_6 aliveSyn6;
+ ALIVE_SYN_8 aliveSyn8;
+ FIN_6 fin6;
+ FIN_8 fin8;
+
+ map<string, int> packetTypes;
+
+ STG_LOGGER & WriteServLog;
+
+ uint32_t enabledDirs;
+
+ class DEL_USER_NONIFIER: public NOTIFIER_BASE<user_iter>
+ {
+ public:
+ DEL_USER_NONIFIER(AUTH_IA & a) : auth(a) {};
+ virtual ~DEL_USER_NONIFIER(){};
+
+ void Notify(const user_iter & user)
+ {
+ auth.DelUser(user);
+ }
+
+ private:
+ AUTH_IA & auth;
+ } onDelUserNotifier;
+
+ class UnauthorizeUser : std::unary_function<const std::pair<uint32_t, IA_USER> &, void> {
+ public:
+ UnauthorizeUser(AUTH_IA * a) : auth(a) {};
+ void operator()(const std::pair<uint32_t, IA_USER> & p)
+ {
+ p.second.user->Unauthorize(auth);
+ }
+ private:
+ AUTH_IA * auth;
+ };
+
+};
+//-----------------------------------------------------------------------------
+
+#endif
+
+
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.4 2008/12/04 17:01:28 faust Exp $
+###############################################################################
+
+include ../../../../../Makefile.conf
+
+PROG = mod_auth_stress.so
+
+SRCS = ./stress.cpp
+
+LIBS += $(LIB_THREAD)
+
+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 : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+/*
+ $Revision: 1.5 $
+ $Date: 2009/06/19 12:50:32 $
+ $Author: faust $
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include "stress.h"
+#include "../../../user.h"
+
+class STRESS_CREATOR
+{
+private:
+ AUTH_STRESS * dc;
+
+public:
+ STRESS_CREATOR()
+ {
+ printfd(__FILE__, "constructor STRESS_CREATOR\n");
+ dc = new AUTH_STRESS();
+ };
+ ~STRESS_CREATOR()
+ {
+ printfd(__FILE__, "destructor STRESS_CREATOR\n");
+ delete dc;
+ };
+
+ BASE_PLUGIN * GetPlugin()
+ {
+ return dc;
+ };
+};
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+STRESS_CREATOR stressc;
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// ëÌÁÓÓ ÄÌÑ ÐÏÉÓËÁ ÀÚÅÒÁ × ÓÐÉÓËÅ ÎÏÔÉÆÉËÁÔÏÒÏ×
+template <typename varType>
+class IS_CONTAINS_USER: public binary_function<varType, user_iter, bool>
+{
+public:
+ bool operator()(varType notifier, user_iter user) const
+ {
+ return notifier.GetUser() == user;
+ };
+};
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+BASE_PLUGIN * GetPlugin()
+{
+//printf("BASE_CAPTURER * GetCapturer()\n");
+return stressc.GetPlugin();
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+AUTH_STRESS_SETTINGS::AUTH_STRESS_SETTINGS()
+ : averageOnlineTime(0)
+{
+}
+//-----------------------------------------------------------------------------
+int AUTH_STRESS_SETTINGS::ParseIntInRange(const string & str, int min, int max, int * val)
+{
+if (str2x(str.c_str(), *val))
+ {
+ errorStr = "Incorrect value \'" + str + "\'.";
+ return -1;
+ }
+if (*val < min || *val > max)
+ {
+ errorStr = "Value \'" + str + "\' out of range.";
+ return -1;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_STRESS_SETTINGS::ParseSettings(const MODULE_SETTINGS & s)
+{
+PARAM_VALUE pv;
+vector<PARAM_VALUE>::const_iterator pvi;
+
+pv.param = "AverageOnlineTime";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end())
+ {
+ errorStr = "Parameter \'" + pv.param + "\' not found.";
+ return -1;
+ }
+
+if (ParseIntInRange(pvi->value[0], 5, 10*3600, &averageOnlineTime))
+ {
+ errorStr = "Cannot parse parameter \'" + pv.param + "\': " + errorStr;
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_STRESS_SETTINGS::GetAverageOnlineTime() const
+{
+return averageOnlineTime;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+const string AUTH_STRESS::GetVersion() const
+{
+return "Stress authorizator v.0.1";
+}
+//-----------------------------------------------------------------------------
+AUTH_STRESS::AUTH_STRESS()
+{
+pthread_mutex_init(&mutex, NULL);
+isRunning = false;
+}
+//-----------------------------------------------------------------------------
+void AUTH_STRESS::SetUsers(USERS * u)
+{
+users = u;
+}
+//-----------------------------------------------------------------------------
+void AUTH_STRESS::SetSettings(const MODULE_SETTINGS & s)
+{
+settings = s;
+}
+//-----------------------------------------------------------------------------
+int AUTH_STRESS::ParseSettings()
+{
+int ret = stressSettings.ParseSettings(settings);
+if (ret)
+ errorStr = stressSettings.GetStrError();
+return ret;
+}
+//-----------------------------------------------------------------------------
+const string & AUTH_STRESS::GetStrError() const
+{
+return errorStr;
+}
+//-----------------------------------------------------------------------------
+int AUTH_STRESS::Start()
+{
+GetUsers();
+nonstop = true;
+
+list<user_iter>::iterator users_iter;
+
+onAddUserNotifier.SetAuthorizator(this);
+onDelUserNotifier.SetAuthorizator(this);
+users->AddNotifierUserAdd(&onAddUserNotifier);
+users->AddNotifierUserDel(&onDelUserNotifier);
+
+if (!isRunning)
+ {
+ if (pthread_create(&thread, NULL, Run, this))
+ {
+ errorStr = "Cannot create thread.";
+ return -1;
+ }
+ }
+
+users_iter = usersList.begin();
+while (users_iter != usersList.end())
+ {
+ Authorize(*users_iter);
+ users_iter++;
+ }
+
+//isRunning = true;
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_STRESS::Stop()
+{
+nonstop = false;
+if (isRunning)
+ {
+ //5 seconds to thread stops itself
+ int i;
+ for (i = 0; i < 25; i++)
+ {
+ if (!isRunning)
+ break;
+ stgUsleep(200000);
+ }
+
+ //after 5 seconds waiting thread still running. now killing it
+ if (isRunning)
+ {
+ if (pthread_kill(thread, SIGINT))
+ {
+ errorStr = "Cannot kill thread.";
+ return -1;
+ }
+ printfd(__FILE__, "AUTH_STRESS killed Run\n");
+ }
+ }
+
+users->DelNotifierUserAdd(&onAddUserNotifier);
+users->DelNotifierUserDel(&onDelUserNotifier);
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+bool AUTH_STRESS::IsRunning()
+{
+return isRunning;
+}
+//-----------------------------------------------------------------------------
+uint16_t AUTH_STRESS::GetStartPosition() const
+{
+return 70;
+}
+//-----------------------------------------------------------------------------
+uint16_t AUTH_STRESS::GetStopPosition() const
+{
+return 70;
+}
+//-----------------------------------------------------------------------------
+void AUTH_STRESS::SetUserNotifiers(user_iter u)
+{
+// ---------- IP -------------------
+CHG_BEFORE_NOTIFIER<USER_IPS> BeforeChgIPNotifier;
+CHG_AFTER_NOTIFIER<USER_IPS> AfterChgIPNotifier;
+
+BeforeChgIPNotifier.SetAuthorizator(this);
+BeforeChgIPNotifier.SetUser(u);
+BeforeChgIPNotifierList.push_front(BeforeChgIPNotifier);
+
+AfterChgIPNotifier.SetAuthorizator(this);
+AfterChgIPNotifier.SetUser(u);
+AfterChgIPNotifierList.push_front(AfterChgIPNotifier);
+
+u->property.ips.AddBeforeNotifier(&(*BeforeChgIPNotifierList.begin()));
+u->property.ips.AddAfterNotifier(&(*AfterChgIPNotifierList.begin()));
+// ---------- IP end ---------------
+}
+//-----------------------------------------------------------------------------
+void AUTH_STRESS::UnSetUserNotifiers(user_iter u)
+{
+// --- IP ---
+IS_CONTAINS_USER<CHG_BEFORE_NOTIFIER<USER_IPS> > IsContainsUserIPB;
+IS_CONTAINS_USER<CHG_AFTER_NOTIFIER<USER_IPS> > IsContainsUserIPA;
+
+list<CHG_BEFORE_NOTIFIER<USER_IPS> >::iterator ipBIter;
+list<CHG_AFTER_NOTIFIER<USER_IPS> >::iterator ipAIter;
+
+ipBIter = find_if(BeforeChgIPNotifierList.begin(),
+ BeforeChgIPNotifierList.end(),
+ bind2nd(IsContainsUserIPB, u));
+
+if (ipBIter != BeforeChgIPNotifierList.end())
+ {
+ ipBIter->GetUser()->property.ips.DelBeforeNotifier(&(*ipBIter));
+ BeforeChgIPNotifierList.erase(ipBIter);
+ }
+
+ipAIter = find_if(AfterChgIPNotifierList.begin(),
+ AfterChgIPNotifierList.end(),
+ bind2nd(IsContainsUserIPA, u));
+
+if (ipAIter != AfterChgIPNotifierList.end())
+ {
+ ipAIter->GetUser()->property.ips.DelAfterNotifier(&(*ipAIter));
+ AfterChgIPNotifierList.erase(ipAIter);
+ }
+// --- IP end ---
+}
+//-----------------------------------------------------------------------------
+void AUTH_STRESS::GetUsers()
+{
+user_iter u;
+printfd(__FILE__, "users->OpenSearch() usernum=%d\n", users->GetUserNum());
+int h = users->OpenSearch();
+if (!h)
+ {
+ printfd(__FILE__, "users->OpenSearch() error\n");
+ return;
+ }
+
+while (1)
+ {
+ if (users->SearchNext(h, &u))
+ {
+ break;
+ }
+ usersList.push_back(u);
+ SetUserNotifiers(u);
+ }
+
+users->CloseSearch(h);
+}
+//-----------------------------------------------------------------------------
+void AUTH_STRESS::Unauthorize(user_iter u) const
+{
+if (!u->IsAuthorizedBy(this))
+ return;
+
+printfd(__FILE__, "Unauthorized user %s\n", u->GetLogin().c_str());
+u->Unauthorize(this);
+}
+//-----------------------------------------------------------------------------
+void AUTH_STRESS::Authorize(user_iter u) const
+{
+USER_IPS ips = u->property.ips;
+if (ips.OnlyOneIP() && !u->IsAuthorizedBy(this))
+ {
+ if (u->Authorize(ips[0].ip, "", 0xFFffFFff, this) == 0)
+ {
+ printfd(__FILE__, "Authorized user %s\n", u->GetLogin().c_str());
+ }
+ }
+}
+//-----------------------------------------------------------------------------
+void AUTH_STRESS::AddUser(user_iter u)
+{
+//printfd(__FILE__, "User added to list %s\n", u->GetLogin().c_str());
+SetUserNotifiers(u);
+usersList.push_back(u);
+}
+//-----------------------------------------------------------------------------
+void AUTH_STRESS::DelUser(user_iter u)
+{
+Unauthorize(u);
+UnSetUserNotifiers(u);
+
+list<user_iter>::iterator users_iter;
+users_iter = usersList.begin();
+
+while (users_iter != usersList.end())
+ {
+ if (u == *users_iter)
+ {
+ usersList.erase(users_iter);
+ printfd(__FILE__, "User removed from list %s\n", u->GetLogin().c_str());
+ break;
+ }
+ users_iter++;
+ }
+}
+//-----------------------------------------------------------------------------
+int AUTH_STRESS::SendMessage(const STG_MSG & msg, uint32_t ip) const
+{
+errorStr = "Authorization modele \'AUTH_STRESS\' does not support sending messages";
+return -1;
+}
+//-----------------------------------------------------------------------------
+void * AUTH_STRESS::Run(void * d)
+{
+AUTH_STRESS * ia;
+ia = (AUTH_STRESS *)d;
+
+ia->isRunning = true;
+
+while (ia->nonstop)
+ {
+ printfd(__FILE__, "AUTH_STRESS::Run\n");
+
+ list<user_iter>::iterator users_iter;
+ users_iter = ia->usersList.begin();
+ while (users_iter != ia->usersList.end())
+ {
+ if (random() % 2*ia->stressSettings.GetAverageOnlineTime() == 1)
+ {
+ ia->Authorize(*users_iter);
+ printfd(__FILE__, "AUTH_STRESS::Authorize\n");
+ }
+ if (random() % 2*ia->stressSettings.GetAverageOnlineTime() == 2)
+ {
+ ia->Unauthorize(*users_iter);
+ printfd(__FILE__, "AUTH_STRESS::Unauthorize\n");
+ }
+
+ users_iter++;
+ }
+
+ sleep(1);
+ }
+
+ia->isRunning = false;
+return NULL;
+}
+
+//-----------------------------------------------------------------------------
+template <typename varParamType>
+void CHG_BEFORE_NOTIFIER<varParamType>::Notify(const varParamType & oldValue, const varParamType & newValue)
+{
+auth->Unauthorize(user);
+}
+//-----------------------------------------------------------------------------
+template <typename varParamType>
+void CHG_AFTER_NOTIFIER<varParamType>::Notify(const varParamType & oldValue, const varParamType & newValue)
+{
+auth->Unauthorize(user);
+}
+//-----------------------------------------------------------------------------
--- /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>
+ */
+
+/*
+ $Revision: 1.3 $
+ $Date: 2009/06/19 12:50:32 $
+ $Author: faust $
+ */
+
+
+#ifndef STRESS_H
+#define STRESS_H
+
+#include <string>
+#include <pthread.h>
+#include "base_auth.h"
+#include "notifer.h"
+#include "user_ips.h"
+#include "../../../users.h"
+
+using namespace std;
+
+extern "C" BASE_PLUGIN * GetPlugin();
+
+class AUTH_STRESS;
+//-----------------------------------------------------------------------------
+template <typename varParamType>
+class CHG_BEFORE_NOTIFIER: public PROPERTY_NOTIFIER_BASE<varParamType>
+{
+public:
+ void Notify(const varParamType & oldValue, const varParamType & newValue);
+ void SetUser(user_iter u) { user = u; }
+ user_iter GetUser() {return user; }
+ void SetAuthorizator(const AUTH_STRESS * a) { auth = a; }
+
+private:
+ user_iter user;
+ const AUTH_STRESS * auth;
+};
+//-----------------------------------------------------------------------------
+template <typename varParamType>
+class CHG_AFTER_NOTIFIER: public PROPERTY_NOTIFIER_BASE<varParamType>
+{
+public:
+ void Notify(const varParamType & oldValue, const varParamType & newValue);
+ void SetUser(user_iter u) { user = u; }
+ user_iter GetUser() {return user; }
+ void SetAuthorizator(const AUTH_STRESS * a) { auth = a; }
+
+private:
+ user_iter user;
+ const AUTH_STRESS * auth;
+};
+//-----------------------------------------------------------------------------
+class AUTH_STRESS_SETTINGS
+{
+public:
+ AUTH_STRESS_SETTINGS();
+ const string& GetStrError() const { return errorStr; }
+ int ParseSettings(const MODULE_SETTINGS & s);
+ int GetAverageOnlineTime() const;
+private:
+ int ParseIntInRange(const string & str, int min, int max, int * val);
+ int averageOnlineTime;
+ string errorStr;
+};
+//-----------------------------------------------------------------------------
+class AUTH_STRESS :public BASE_AUTH
+{
+public:
+ AUTH_STRESS();
+ virtual ~AUTH_STRESS(){};
+
+ void SetUsers(USERS * u);
+ void SetTariffs(TARIFFS * t){};
+ void SetAdmins(ADMINS * a){};
+ void SetTraffcounter(TRAFFCOUNTER * tc){};
+ void SetStore(BASE_STORE * ){};
+ void SetStgSettings(const SETTINGS *){};
+
+ int Start();
+ int Stop();
+ bool IsRunning();
+ void SetSettings(const MODULE_SETTINGS & s);
+ int ParseSettings();
+ const string & GetStrError() const;
+ const string GetVersion() const;
+ uint16_t GetStartPosition() const;
+ uint16_t GetStopPosition() const;
+
+ void AddUser(user_iter u);
+ void DelUser(user_iter u);
+
+ void Authorize(user_iter u) const;
+ void Unauthorize(user_iter u) const;
+
+ int SendMessage(const STG_MSG & msg, uint32_t ip) const;
+
+private:
+ void GetUsers();
+ void SetUserNotifiers(user_iter u);
+ void UnSetUserNotifiers(user_iter u);
+
+ bool nonstop;
+
+ static void * Run(void *);
+
+ mutable string errorStr;
+ AUTH_STRESS_SETTINGS stressSettings;
+ USERS * users;
+ list<user_iter> usersList;
+ bool isRunning;
+ MODULE_SETTINGS settings;
+
+ pthread_t thread;
+ pthread_mutex_t mutex;
+
+ list<CHG_BEFORE_NOTIFIER<USER_IPS> > BeforeChgIPNotifierList;
+ list<CHG_AFTER_NOTIFIER<USER_IPS> > AfterChgIPNotifierList;
+
+ class ADD_USER_NONIFIER: public NOTIFIER_BASE<user_iter>
+ {
+ public:
+ ADD_USER_NONIFIER(){};
+ virtual ~ADD_USER_NONIFIER(){};
+
+ void SetAuthorizator(AUTH_STRESS * a) { auth = a; }
+ void Notify(const user_iter & user)
+ {
+ auth->AddUser(user);
+ }
+
+ private:
+ AUTH_STRESS * auth;
+ } onAddUserNotifier;
+
+ class DEL_USER_NONIFIER: public NOTIFIER_BASE<user_iter>
+ {
+ public:
+ DEL_USER_NONIFIER(){};
+ virtual ~DEL_USER_NONIFIER(){};
+
+ void SetAuthorizator(AUTH_STRESS * a) { auth = a; }
+ void Notify(const user_iter & user)
+ {
+ auth->DelUser(user);
+ }
+
+ private:
+ AUTH_STRESS * auth;
+ } onDelUserNotifier;
+
+};
+//-----------------------------------------------------------------------------
+
+#endif
+
+
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.10 2008/12/04 17:03:25 faust Exp $
+###############################################################################
+
+include ../../../../../Makefile.conf
+
+PROG = mod_cap_debug.so
+
+SRCS = ./debug_cap.cpp \
+ ./checksum.c \
+ ./icmp.c \
+ ./ip.c \
+ ./misc.c \
+ ./packet.c \
+ ./socket.c \
+ ./tcp.c \
+ ./udp.c
+
+STGLIBS = -lstg_common
+
+LIBS += $(LIB_THREAD)
+
+include ../../Makefile.in
+
--- /dev/null
+/*$Id: checksum.c,v 1.1 2005/12/12 18:14:22 nobunaga Exp $
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+unsigned short
+in_cksum(unsigned short *addr, int len)
+{
+ int nleft = len;
+ int sum = 0;
+ unsigned short *w = addr;
+ unsigned short answer = 0;
+
+ /*
+ * Our algorithm is simple, using a 32 bit accumulator (sum), we add
+ * sequential 16 bit words to it, and at the end, fold back all the
+ * carry bits from the top 16 bits into the lower 16 bits.
+ */
+ while (nleft > 1) {
+ sum += *w++;
+ nleft -= 2;
+ }
+
+ /* mop up an odd byte, if necessary */
+ if (nleft == 1) {
+ *(unsigned char *)(&answer) = *(unsigned char *)w ;
+ sum += answer;
+ }
+
+ /* add back carry outs from top 16 bits to low 16 bits */
+ sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
+ sum += (sum >> 16); /* add carry */
+ answer = ~sum; /* truncate to 16 bits */
+ return(answer);
+}
--- /dev/null
+/* $Id: checksum.h,v 1.1 2005/12/12 18:14:22 nobunaga Exp $
+
+Copyright (C) 2002 Marc Kirchner <kirchner@stud.fh-heilbronn.de>
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+unsigned short in_cksum(unsigned short *addr, int len);
--- /dev/null
+/* $Id: constants.h,v 1.1 2005/12/12 18:14:22 nobunaga Exp $
+
+Copyright (C) 2002 Marc Kirchner <kirchner@stud.fh-heilbronn.de>
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+/*
+* socket types
+*/
+#define PKT_RAW SOCK_RAW
+#define PKT_STREAM SOCK_STREAM
+#define PKT_DGRAM SOCK_DGRAM
+
+/*
+* Link Layer
+*/
+#define PKT_LINK_ARP 0x01
+#define PKT_LINK_RARP 0x02
+
+/*
+* Network Layer
+*/
+#define PKT_NET_IP 0x01
+#define PKT_NET_ICMP 0x02
+#define PKT_NET_IGMP 0x04
+
+/*
+* Transport layer
+*/
+#define PKT_TRANS_TCP 0x01
+#define PKT_TRANS_UDP 0x02
+
+/* --- [ IP ] ------------------------ */
+/* IP options */
+#define PKT_IP_OPT_EOL 0 /* end of option list */
+#define PKT_IP_OPT_END PKT_IP_OPT_EOL
+#define PKT_IP_OPT_NOP 1 /* no operation */
+#define PKT_IP_OPT_NOOP PKT_IP_OPT_NOP
+
+#define PKT_IP_OPT_RR 7 /* record packet route */
+#define PKT_IP_OPT_TS 68 /* timestamp */
+#define PKT_IP_OPT_TIMESTAMP PKT_IP_OPT_TS
+#define PKT_IP_OPT_SECURITY 130 /* provide s,c,h,tcc */
+#define PKT_IP_OPT_SEC PKT_IP_OPT_SECURITY
+#define PKT_IP_OPT_LSRR 131 /* loose source route */
+#define PKT_IP_OPT_SATID 136 /* satnet id */
+#define PKT_IP_OPT_SID PKT_IP_OPT_SATID
+#define PKT_IP_OPT_SSRR 137 /* strict source route */
+#define PKT_IP_OPT_RA 148 /* router alert */
+
+/* flag bits for ipt_flg */
+#define PKT_IP_OPT_TS_TSONLY 0 /* timestamps only */
+#define PKT_IP_OPT_TS_TSANDADDR 1 /* timestamps and addresses */
+#define PKT_IP_OPT_TS_PRESPEC 3 /* specified modules only */
+
+/* --- [ TCP ] ------------------------ */
+/* tcp flags */
+#ifndef __FAVOUR_BSD
+#define TH_FIN 0x01
+#define TH_SYN 0x02
+#define TH_RST 0x04
+#define TH_PUSH 0x08
+#define TH_ACK 0x10
+#define TH_URG 0x20
+#endif
+/* additional flags */
+#define TH_XMAS 0x40
+#define TH_YMAS 0x80
+
+/* tcp options */
+#define PKT_TCP_OPT_END 0x00
+#define PKT_TCP_OPT_NOP 0x01
+#define PKT_TCP_OPT_MSS 0x02
+#define PKT_TCP_OPT_WSF 0x03 /*window scale factor*/
+#define PKT_TCP_OPT_SACK_PERM 0x04
+#define PKT_TCP_OPT_SACK 0x05
+#define PKT_TCP_OPT_TIME 0x08 /* timestamp option */
+
+/* tcp option lenghts */
+#define PKT_TCP_OPT_END_LEN 0x01
+#define PKT_TCP_OPT_NOP_LEN 0x01
+#define PKT_TCP_OPT_MSS_LEN 0x04
+#define PKT_TCP_OPT_WSF_LEN 0x03 /*window scale factor*/
+#define PKT_TCP_OPT_SACK_PERM_LEN 0x02
+#define PKT_TCP_OPT_SACK_LEN 0x01
+#define PKT_TCP_OPT_TIME_LEN 0x0a /* timestamp option */
+
+/* return values and errors */
+#define PKTOK 0
+#define EPKTRANGE -64
+#define EERRNO -63 /* errno has been set */
+#define EPKTINVALPTR -62
+#define EPKTUNKNOWNTYPE -61
--- /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: 18.09.2002
+*/
+
+/*
+* Author : Boris Mikhailenko <stg34@stg.dp.ua>
+*/
+
+/*
+$Revision: 1.21 $
+$Date: 2009/03/19 20:03:35 $
+$Author: faust $
+*/
+
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "debug_cap.h"
+#include "../../../traffcounter.h"
+#include "libpal.h"
+
+//-----------------------------------------------------------------------------
+void WriteStat(uint32_t u, uint32_t d)
+{
+FILE * f;
+f = fopen("/tmp/cap.stat", "at");
+fprintf(f, "up %5.2f Mbit, down %5.2f Mbit, sum %5.2f Mbit\n",
+ u / (1000000*8.0),
+ d / (1000000*8.0),
+ (u + d) / (1000000*8.0));
+fclose(f);
+}
+//-----------------------------------------------------------------------------
+
+class CAP_DEBUG_CREATOR
+{
+private:
+ DEBUG_CAP * dc;
+
+public:
+ CAP_DEBUG_CREATOR()
+ : dc(new DEBUG_CAP())
+ {
+ };
+ ~CAP_DEBUG_CREATOR()
+ {
+ delete dc;
+ };
+
+ DEBUG_CAP * GetCapturer()
+ {
+ return dc;
+ };
+};
+//-----------------------------------------------------------------------------
+RAW_PACKET MakeTCPPacket(const char * src,
+ const char * dst,
+ uint16_t sport,
+ uint16_t dport,
+ uint16_t len);
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+CAP_DEBUG_CREATOR cdc;
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+BASE_PLUGIN * GetPlugin()
+{
+return cdc.GetCapturer();
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+const string DEBUG_CAP::GetVersion() const
+{
+return "Debug_cap v.0.01a";
+}
+//-----------------------------------------------------------------------------
+DEBUG_CAP::DEBUG_CAP()
+{
+isRunning = false;
+nonstop = false;
+}
+//-----------------------------------------------------------------------------
+void DEBUG_CAP::SetTraffcounter(TRAFFCOUNTER * tc)
+{
+traffCnt = tc;
+}
+//-----------------------------------------------------------------------------
+const string & DEBUG_CAP::GetStrError() const
+{
+return errorStr;
+}
+//-----------------------------------------------------------------------------
+int DEBUG_CAP::Start()
+{
+if (isRunning)
+ return 0;
+
+printfd(__FILE__, "DEBUG_CAP::Start()\n");
+
+nonstop = true;
+
+if (pthread_create(&thread, NULL, Run1, this) == 0)
+ {
+ return 0;
+ }
+
+errorStr = "Cannot create thread.";
+return -1;
+}
+//-----------------------------------------------------------------------------
+int DEBUG_CAP::Stop()
+{
+if (!isRunning)
+ return 0;
+
+nonstop = false;
+
+//5 seconds to thread stops itself
+int i;
+for (i = 0; i < 25; i++)
+ {
+ if (!isRunning)
+ break;
+
+ stgUsleep(200000);
+ //printf(".");
+ }
+
+/*if (i)
+ printf("\n");*/
+
+//after 5 seconds waiting thread still running. now killing it
+if (isRunning)
+ {
+ //TODO pthread_cancel()
+ if (pthread_kill(thread, SIGINT))
+ {
+ errorStr = "Cannot kill thread.";
+ return -1;
+ }
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+bool DEBUG_CAP::IsRunning()
+{
+return nonstop;
+}
+//-----------------------------------------------------------------------------
+void * DEBUG_CAP::Run1(void * data)
+{
+printfd(__FILE__, "=====================| pid: %d |===================== \n", getpid());
+
+DEBUG_CAP * dc = (DEBUG_CAP *)data;
+dc->isRunning = true;
+
+RAW_PACKET rp;
+rp = MakeTCPPacket("192.168.1.1", "192.168.1.21", 255, 255, 200);
+int a = 0;
+sleep(3);
+
+struct tm * tm;
+time_t t;
+uint32_t u = 0;
+uint32_t d = 0;
+
+//2 upload : 3 download
+
+int usize;
+int dsize;
+
+t = stgTime;
+tm = localtime(&t);
+int min = tm->tm_min;
+int sec = tm->tm_sec;
+
+char cliIP[20];
+char srvIP[20];
+char trashIP1[20];
+char trashIP2[20];
+
+while (dc->nonstop)
+ {
+ for (int i = 8; i <= 252; i++)
+ {
+
+ usize = random()%100 + 100;
+ dsize = random()%500 + 900;
+
+ for (int j = 2; j < 11; j++)
+ {
+ sprintf(cliIP, "192.168.%d.%d", j, i);
+ sprintf(srvIP, "10.1.%d.%d", random()%8, 1);
+
+ rp = MakeTCPPacket(srvIP, cliIP, 80, random()%2 + 2000, dsize);
+ d += dsize;
+ dc->traffCnt->Process(rp);
+
+ rp = MakeTCPPacket(cliIP, srvIP, random()%2 + 2000, 80, usize);
+ u += usize;
+ dc->traffCnt->Process(rp);
+ }
+ }
+
+ usleep(100000);
+ t = stgTime;
+
+ if (min != localtime(&t)->tm_min)
+ {
+ min = localtime(&t)->tm_min;
+ WriteStat(u, d);
+ u = d = 0;
+ }
+
+ a++;
+
+ }
+
+dc->isRunning = false;
+return NULL;
+}
+//-----------------------------------------------------------------------------
+void * DEBUG_CAP::Run2(void * data)
+{
+printfd(__FILE__, "=====================| pid: %d |===================== \n", getpid());
+
+DEBUG_CAP * dc = (DEBUG_CAP *)data;
+dc->isRunning = true;
+
+RAW_PACKET rp;
+rp = MakeTCPPacket("192.168.1.1", "192.168.1.21", 255, 255, 200);
+int a = 0;
+sleep(3);
+
+struct tm * tm;
+time_t t;
+uint32_t u = 0;
+uint32_t d = 0;
+
+//2 upload : 3 download
+
+int usize = 200;
+int dsize = 1500;
+
+t = stgTime;
+tm = localtime(&t);
+int min = tm->tm_min;
+
+char cliIP[20];
+char srvIP[20];
+
+while (dc->nonstop)
+ {
+ for (int i = 101; i <= 150; i++)
+ {
+ sprintf(cliIP, "192.168.1.%d", i);
+ for (int dp = 0; dp < 1; dp++)
+ {
+ //sprintf(srvIP, "10.1.%d.%d", i, 10 + dp);
+ sprintf(srvIP, "10.1.%d.%d", i, 10 + dp);
+
+ rp = MakeTCPPacket(srvIP, cliIP, 80, 10000 + i + dp, dsize);
+ d += dsize;
+ dc->traffCnt->Process(rp);
+
+ rp = MakeTCPPacket(srvIP, cliIP, 80, 10000 + i + dp, dsize);
+ d += dsize;
+ dc->traffCnt->Process(rp);
+
+ rp = MakeTCPPacket(srvIP, cliIP, 80, 10000 + i + dp, dsize);
+ dc->traffCnt->Process(rp);
+ d += dsize;
+
+
+ rp = MakeTCPPacket(cliIP, srvIP, 10000 + i + dp, 80, usize);
+ u += usize;
+ dc->traffCnt->Process(rp);
+
+ rp = MakeTCPPacket(cliIP, srvIP, 10000 + i + dp, 80, usize);
+ u += usize;
+ dc->traffCnt->Process(rp);
+ }
+ }
+
+ //usleep(20000);
+ t = stgTime;
+
+ if (min != localtime(&t)->tm_min)
+ {
+ min = localtime(&t)->tm_min;
+ WriteStat(u, d);
+ u = d = 0;
+ }
+
+ a++;
+
+ }
+
+dc->isRunning = false;
+return NULL;
+}
+//-----------------------------------------------------------------------------
+void * DEBUG_CAP::Run3(void * data)
+{
+printfd(__FILE__, "=====================| pid: %d |===================== \n", getpid());
+
+DEBUG_CAP * dc = (DEBUG_CAP *)data;
+dc->isRunning = true;
+
+RAW_PACKET rp;
+rp = MakeTCPPacket("192.168.1.1", "192.168.1.21", 255, 255, 200);
+int a = 0;
+sleep(3);
+
+struct tm * tm;
+time_t t;
+uint32_t u = 0;
+uint32_t d = 0;
+
+//2 upload : 3 download
+
+int usize = 200;
+int dsize = 1500;
+
+t = stgTime;
+tm = localtime(&t);
+
+char cliIP[20];
+char srvIP1[20];
+char srvIP2[20];
+char srvIP3[20];
+
+int firstTime = true;
+
+while (dc->nonstop)
+ {
+ if (firstTime)
+ {
+ sprintf(srvIP1, "10.1.%d.%d", random() % 14 + 153, random() % 11 + 35);
+
+ sprintf(srvIP2, "%d.%d.%d.%d",
+ random() % 20 + 81,
+ random() % 28 + 153,
+ random() % 28 + 37,
+ random() % 28 + 13);
+
+ sprintf(srvIP3, "%d.%d.%d.%d",
+ random() % 20 + 81,
+ random() % 28 + 153,
+ random() % 28 + 37,
+ random() % 28 + 13);
+
+ printfd(__FILE__, "firstTime=false\n");
+ firstTime = false;
+ }
+
+ int rnd = random() % 400;
+ if (rnd < 5)
+ {
+ sprintf(srvIP1, "10.1.%d.%d", random() % 14 + 153, random() % 11 + 35);
+ printfd(__FILE__, "srvIP1=%s\n", srvIP1);
+ }
+ if (rnd == 9)
+ {
+ sprintf(srvIP2, "%d.%d.%d.%d",
+ random() % 20 + 81,
+ random() % 28 + 153,
+ random() % 28 + 37,
+ random() % 28 + 13);
+ printfd(__FILE__, "srvIP2=%s\n", srvIP2);
+ }
+ if (rnd == 5)
+ {
+ sprintf(srvIP2, "%d.%d.%d.%d",
+ random() % 20 + 81,
+ random() % 28 + 153,
+ random() % 28 + 37,
+ random() % 28 + 13);
+ printfd(__FILE__, "srvIP3=%s\n", srvIP3);
+ }
+
+ for (int i = 2; i < 52; i++)
+ {
+ sprintf(cliIP, "192.168.1.%d", i);
+ for (int dp = 0; dp < 1; dp++)
+ {
+ usize = 50 + random() % 100;
+ dsize = 1000 + random() % 400;
+
+ rp = MakeTCPPacket(srvIP1, cliIP, 80, 10000 + i + dp, dsize);
+ dc->traffCnt->Process(rp);
+
+ rp = MakeTCPPacket(srvIP2, cliIP, 80, 10000 + i + dp, dsize);
+ dc->traffCnt->Process(rp);
+
+ rp = MakeTCPPacket(srvIP3, cliIP, 80, 10000 + i + dp, dsize);
+ dc->traffCnt->Process(rp);
+
+
+ rp = MakeTCPPacket(cliIP, srvIP1, 10000 + i + dp, 80, usize);
+ dc->traffCnt->Process(rp);
+
+ rp = MakeTCPPacket(cliIP, srvIP2, 10000 + i + dp, 80, usize);
+ dc->traffCnt->Process(rp);
+
+ rp = MakeTCPPacket(cliIP, srvIP3, 10000 + i + dp, 80, usize);
+ dc->traffCnt->Process(rp);
+ }
+ }
+
+ usleep(300000);
+ /*t = stgTime;
+
+ if (min != localtime(&t)->tm_min)
+ {
+ min = localtime(&t)->tm_min;
+ WriteStat(u, d);
+ u = d = 0;
+ }*/
+
+ a++;
+
+ }
+
+dc->isRunning = false;
+return NULL;
+}
+//-----------------------------------------------------------------------------
+uint16_t DEBUG_CAP::GetStartPosition() const
+{
+return 0;
+}
+//-----------------------------------------------------------------------------
+uint16_t DEBUG_CAP::GetStopPosition() const
+{
+return 0;
+}
+//-----------------------------------------------------------------------------
+RAW_PACKET MakeTCPPacket(const char * src,
+ const char * dst,
+ uint16_t sport,
+ uint16_t dport,
+ uint16_t len)
+{
+struct packet pkt;
+if (pkt_init(&pkt, 0, 100))
+ {
+ printfd(__FILE__, "pkt_init error!\n");
+ }
+
+in_addr_t sip = inet_addr(src);
+in_addr_t dip = inet_addr(dst);
+
+pkt_ip_header(&pkt,
+ 5, //header len
+ 4,
+ 0,
+ len, //total len
+ 0,
+ 0,
+ 64, //ttl
+ 6, //TCP
+ 0,
+ *(uint32_t*)&sip,
+ *(uint32_t*)&dip);
+
+pkt_move_actptr(&pkt, 20);
+
+pkt_tcp_header(&pkt,
+ sport,
+ dport,
+ 1, // seq,
+ 1, // ackseq,
+ 5, // headerlen,
+ 0, // reserved,
+ 0, // flags,
+ 0, // window,
+ 0, // checksum,
+ 0); // urgent
+
+RAW_PACKET rp;
+memcpy(&rp, pkt.pkt, sizeof(rp));
+
+if (pkt_free(&pkt))
+ {
+ printfd(__FILE__, "pkt_free error!\n");
+ }
+rp.dataLen = -1;
+strcpy(rp.iface, "eth0");
+return rp;
+}
+//-----------------------------------------------------------------------------
+
+
--- /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: 18.09.2002
+*/
+
+/*
+* Author : Boris Mikhailenko <stg34@stg.dp.ua>
+*/
+
+/*
+$Revision: 1.12 $
+$Date: 2009/06/23 11:32:27 $
+$Author: faust $
+*/
+
+#include <string>
+#include <pthread.h>
+
+#include "os_int.h"
+#include "base_plugin.h"
+#include "base_settings.h"
+
+using namespace std;
+extern "C" BASE_PLUGIN * GetPlugin();
+
+//-----------------------------------------------------------------------------
+struct iphdr_eth
+{
+ uint8_t ihl:4,
+ version:4;
+ uint8_t tos;
+ uint16_t tot_len;
+ uint16_t id;
+ uint16_t frag_off;
+ uint8_t ttl;
+ uint8_t protocol;
+ uint16_t check;
+ uint32_t saddr;
+ uint32_t daddr;
+ int32_t len;
+ char iface[10];
+};
+//-----------------------------------------------------------------------------
+class CAP_SETTINGS//: public BASE_SETTINGS
+{
+public:
+ const string& GetStrError() const { static string s; return s; }
+ int ParseSettings(const MODULE_SETTINGS & s) { return 0; };
+};
+//-----------------------------------------------------------------------------
+class DEBUG_CAP :public BASE_PLUGIN
+{
+public:
+ DEBUG_CAP();
+ virtual ~DEBUG_CAP(){};
+
+ void SetUsers(USERS * u){};
+ void SetTariffs(TARIFFS * t){};
+ void SetAdmins(ADMINS * a){};
+ void SetTraffcounter(TRAFFCOUNTER * tc);
+ void SetStore(BASE_STORE *){};
+ void SetStgSettings(const SETTINGS *){};
+
+ int Start();
+ int Stop();
+ int Reload() { return 0; };
+ int ParseSettings() { return 0; };
+ void SetSettings(const MODULE_SETTINGS & s){};
+ bool IsRunning();
+ const string & GetStrError() const;
+ const string GetVersion() const;
+ uint16_t GetStartPosition() const;
+ uint16_t GetStopPosition() const;
+private:
+ static void * Run1(void *);
+ static void * Run2(void *);
+ static void * Run3(void *);
+ mutable string errorStr;
+ CAP_SETTINGS capSettings;
+ pthread_t thread;
+ bool nonstop;
+ bool isRunning;
+
+ TRAFFCOUNTER * traffCnt;
+};
+//-----------------------------------------------------------------------------
+
--- /dev/null
+/* $Id: icmp.c,v 1.1 2005/12/12 18:14:22 nobunaga Exp $
+
+Copyright (C) 2002 Marc Kirchner <kirchner@stud.fh-heilbronn.de>
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "libpal.h"
+
+int
+pkt_icmp_header(struct packet *pkt, unsigned char type, unsigned char code, unsigned short int checksum)
+{
+
+ struct icmp *icmp;
+ if (pkt) {
+ icmp = (struct icmp *) pkt->pkt_ptr;
+ icmp->icmp_type = type;
+ icmp->icmp_code = code;
+ icmp->icmp_cksum = htons(checksum);
+ return 0;
+ } else
+ return EPKTINVALPTR;
+}
+
+int pkt_icmp_addr_mask(struct packet *pkt, unsigned short int id, unsigned short int seqno, unsigned int mask, char *cmask)
+{
+ struct icmp *icmp;
+ struct in_addr inetaddr;
+
+ if (pkt) {
+ icmp = (struct icmp *)pkt->pkt_ptr;
+ } else
+ return EPKTINVALPTR;
+ icmp->icmp_id = htons(id);
+ icmp->icmp_seq = htons(seqno);
+ if (!cmask) {
+ icmp->icmp_mask = htons(mask);
+ } else {
+ if (inet_aton(cmask, &inetaddr) != 0) {
+ icmp->icmp_mask = inetaddr.s_addr;
+ } else
+ return EERRNO;
+ }
+ return 0;
+}
+
+int
+pkt_icmp_cksum(struct packet *pkt, unsigned int len)
+{
+ struct icmp *icmp;
+
+ if (!pkt)
+ return EPKTINVALPTR;
+
+ icmp = (struct icmp *) pkt->pkt_ptr;
+ icmp->icmp_cksum = 0;
+ icmp->icmp_cksum = in_cksum((unsigned short *)icmp, len);
+ return 0;
+}
+
+int
+pkt_icmp_dest_unreach(struct packet *pkt, unsigned int unused)
+{
+ struct icmp *icmp;
+
+ if (pkt) {
+ icmp = (struct icmp *)pkt->pkt_ptr;
+ } else
+ return EPKTINVALPTR;
+ icmp->icmp_void = htons(unused);
+ return 0;
+}
+
+int
+pkt_icmp_source_quench(struct packet *pkt, unsigned int unused)
+{
+ struct icmp *icmp;
+
+ if (pkt) {
+ icmp = (struct icmp *)pkt->pkt_ptr;
+ } else
+ return EPKTINVALPTR;
+ icmp->icmp_void = htons(unused);
+ return 0;
+}
+
+int
+pkt_icmp_redirect(struct packet *pkt, unsigned int routerip, char *crouterip)
+{
+ struct icmp *icmp;
+ struct in_addr inetaddr;
+
+ if (pkt) {
+ icmp = (struct icmp *)pkt->pkt_ptr;
+ } else {
+ return EPKTINVALPTR;
+ }
+ if (crouterip) {
+ if (inet_aton(crouterip, &inetaddr) != 0) {
+ icmp->icmp_gwaddr = inetaddr;
+ } else
+ return EERRNO;
+ } else {
+ inetaddr.s_addr = htons(routerip);
+ icmp->icmp_gwaddr = inetaddr;
+ }
+ return 0;
+}
+
+int
+pkt_icmp_echo(struct packet *pkt, unsigned short int id, unsigned short int seqno, void *data, size_t data_len)
+{
+ struct icmp *icmp;
+
+ if (pkt) {
+ icmp = (struct icmp *) pkt->pkt_ptr;
+ } else
+ return EPKTINVALPTR;
+ icmp->icmp_id = htons(id);
+ icmp->icmp_seq = htons(seqno);
+ if (data) {
+ memcpy(icmp->icmp_data, data, data_len);
+ }
+ return 0;
+}
+
+int
+pkt_icmp_timestamp(struct packet *pkt, unsigned short int id, unsigned short int seqno, unsigned int ts_otime, unsigned int ts_rtime, unsigned int ts_ttime)
+{
+ struct icmp *icmp;
+
+ if (pkt)
+ icmp = (struct icmp *) pkt->pkt_ptr;
+ else
+ return EPKTINVALPTR;
+ icmp->icmp_id = htons(id);
+ icmp->icmp_seq = htons(seqno);
+ icmp->icmp_otime = htons(ts_otime);
+ icmp->icmp_rtime = htons(ts_rtime);
+ icmp->icmp_ttime = htons(ts_ttime);
+ return 0;
+}
--- /dev/null
+/* $Id: ip.c,v 1.1 2005/12/12 18:14:22 nobunaga Exp $
+
+Copyright (C) 2002 Marc Kirchner <kirchner@stud.fh-heilbronn.de>
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "libpal.h"
+
+int
+pkt_ip_header(struct packet *pkt,
+ unsigned int iphdr_len,
+ unsigned int version,
+ unsigned char tos,
+ unsigned short int total_len,
+ unsigned short int id,
+ unsigned short int frag_off,
+ unsigned char ttl,
+ unsigned char protocol,
+ unsigned short int cksum,
+ unsigned int saddr,
+ unsigned int daddr)
+{
+ struct ip *ip;
+
+ if (!pkt)
+ return EPKTINVALPTR;
+
+ ip = (struct ip *) pkt->pkt_ptr;
+
+ ip->ip_hl = iphdr_len;
+ ip->ip_v = version;
+ ip->ip_tos = tos;
+ ip->ip_len = htons(total_len);
+ ip->ip_id = htons(id);
+ ip->ip_off = htons(frag_off);
+ ip->ip_ttl = ttl;
+ ip->ip_p = protocol;
+ ip->ip_src.s_addr = saddr;
+ ip->ip_dst.s_addr = daddr;
+
+ return 0;
+}
+
+int
+pkt_ip_option_header(struct packet *pkt, unsigned char type, unsigned char len, unsigned char ptr, unsigned char oflw_flg, void *optval, size_t optlen)
+{
+ unsigned char *vp;
+
+ if (!pkt)
+ return EPKTINVALPTR;
+
+ vp = pkt->pkt_ptr;
+ *vp = type;
+ switch (type) {
+ case PKT_IP_OPT_END:
+ break;
+ case PKT_IP_OPT_NOP:
+ break;
+ case PKT_IP_OPT_SEC:
+ if ((pkt->pkt_pos + 2 + optlen) <= pkt->pkt_size) {
+ *(vp+1) = len;
+ memcpy((void*)(vp+2), optval, optlen);
+ } else {
+ return EPKTRANGE;
+ }
+ break;
+ case PKT_IP_OPT_RR:
+ case PKT_IP_OPT_LSRR:
+ case PKT_IP_OPT_SSRR:
+ case PKT_IP_OPT_SID:
+ if ((pkt->pkt_pos + 3 + optlen) <= pkt->pkt_size) {
+ *(vp+1) = len;
+ *(vp+2) = ptr;
+ memcpy((void*)(vp+3), optval, optlen);
+ } else {
+ return EPKTRANGE;
+ }
+ break;
+ case PKT_IP_OPT_TS:
+ if ((pkt->pkt_pos + 4 + optlen) <= pkt->pkt_size) {
+ *(vp+1) = len;
+ *(vp+2) = ptr;
+ *(vp+3) = oflw_flg;
+ memcpy((void*)(vp+4), optval, optlen);
+ } else {
+ return EPKTRANGE;
+ }
+ break;
+ default:
+ return EPKTUNKNOWNTYPE;
+ }
+ return PKTOK;
+}
+
+int
+pkt_ip_cksum(struct packet *pkt)
+{
+ /*
+ * checksum should be calculated by kernel
+ * when we are using SOCK_RAW access.
+ */
+ struct ip *ip;
+
+ if (!pkt)
+ return EPKTINVALPTR;
+
+ ip = (struct ip *) pkt->pkt_ptr;
+ ip->ip_sum = 0;
+ ip->ip_sum = in_cksum((unsigned short *)ip, sizeof(struct ip));
+ return 0;
+}
--- /dev/null
+/* $Id: libpal.h,v 1.1 2005/12/12 18:14:22 nobunaga Exp $
+
+Copyright (C) 2002 Marc Kirchner <kirchner@stud.fh-heilbronn.de>
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef _LIBPAL_H_
+#define _LIBPAL_H_
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "checksum.h"
+#include "constants.h"
+
+/*
+* generic packet structure
+*
+* we maintain a so called "active ptr" inside the packet. Most operations
+* on the packet will take place at the position the pointer points at.
+* The pointer should never be moved directly, instead the functions
+* pkt_set_actpr() and pkt_move_actptr() are provided.
+* Using this approach we can perform bounds checking and make sure our
+* library functions won't segfault.
+* pkt_type is not really being used at the moment. I don't know if it
+* ever will be. It might just be left out one day, so keep your fingers
+* off. Use pkt_init() to set it. And dont even think of messing with the
+* packet payload pointer pkt. You do NOT want to do that. Use the provided
+* library functions.
+* To be clear: don't do _anything_ with this struct. Just pass it as a
+* parameter, be happy and your programs will (hopefully) work.
+*/
+struct packet {
+ unsigned long pkt_type;
+ unsigned char *pkt;
+ unsigned int pkt_size;
+ unsigned char *pkt_ptr; /* active ptr inside packet */
+ unsigned int pkt_pos; /* pkt_ptr position, starting at 0 */
+};
+
+/*
+* our socket structure
+*
+* same as above. Use the provided library fuctions to change its values.
+* Do not do it on your own. Live and let die. You have been warned.
+*/
+struct pkt_socket {
+ int rawfd;
+ struct sockaddr_in *sckad;
+ /*struct sockaddr_ll *sckll;*/
+ socklen_t sckad_len;
+};
+
+/* memory management */
+int pkt_init(struct packet *pkt, unsigned long type, unsigned int size);
+int pkt_free(struct packet *pkt);
+
+/* pointer movement */
+int pkt_set_actptr(struct packet *pkt, unsigned int bytepos);
+int pkt_move_actptr(struct packet *pkt, int relmov);
+
+/* raw data */
+int pkt_add_systimestamp(struct packet *pkt);
+int pkt_add_data(struct packet *pkt, char *data, size_t data_len);
+int pkt_resize(struct packet *pkt, unsigned int newsize);
+
+/* socket operations */
+int pkt_socket_open(struct pkt_socket *sck, int type);
+int pkt_socket_close(struct pkt_socket *sck);
+int pkt_socket_prepare(struct pkt_socket *sck, char *daddr);
+int pkt_socket_setopt(struct pkt_socket *sck, int level, int optname, void *optval, socklen_t optlen);
+
+/* sending */
+int pkt_send(struct packet *pkt, struct pkt_socket *sck);
+
+/* IP */
+int pkt_ip_header(struct packet *pkt, unsigned int iphdr_len, unsigned int version, unsigned char tos, unsigned short int total_len, unsigned short int id, unsigned short int frag_off /* 3bit flag, 13bit offset */, unsigned char ttl, unsigned char protocol, unsigned short int cksum, unsigned int saddr, unsigned int daddr);
+int pkt_ip_cksum(struct packet *pkt);
+int pkt_ip_option_header(struct packet *pkt, unsigned char type, unsigned char len, unsigned char ptr, unsigned char oflw_flg, void *optval, size_t optlen);
+
+/* TCP */
+int pkt_tcp_header(struct packet *pkt, unsigned short int sport, unsigned short int dport, unsigned int seq, unsigned int ackseq, unsigned char headerlen, unsigned char reserved, unsigned char flags, unsigned short window, unsigned short int checksum, unsigned short int urgent);
+int pkt_tcp_cksum(struct packet *pkt, char *saddr, char *daddr, unsigned int tcp_pkt_size);
+int pkt_tcp_option(struct packet *pkt, unsigned char kind, unsigned char len, void *optval, size_t optlen);
+
+/* UDP */
+int pkt_udp_header(struct packet *pkt, unsigned short int sport, unsigned short int dport, unsigned short int udp_total_len, unsigned short int checksum);
+int pkt_udp_cksum(struct packet *pkt, char *saddr, char *daddr, unsigned int udp_total_len);
+
+/* ICMP */
+int pkt_icmp_header(struct packet *pkt, unsigned char type, unsigned char code, unsigned short int checksum);
+int pkt_icmp_cksum(struct packet *pkt, unsigned int len);
+int pkt_icmp_addr_mask(struct packet *pkt, unsigned short int id, unsigned short int seqno, unsigned int mask, char *cmask);
+int pkt_icmp_dest_unreach(struct packet *pkt, unsigned int unused);
+int pkt_icmp_source_quench(struct packet *pkt, unsigned int unused);
+int pkt_icmp_redirect(struct packet *pkt, unsigned int routerip, char *crouterip);
+int pkt_icmp_echo(struct packet *pkt, unsigned short int id, unsigned short int seqno, void *data, size_t data_len);
+int pkt_icmp_timestamp(struct packet *pkt, unsigned short int id, unsigned short int seqno, unsigned int ts_otime, unsigned int ts_rtime, unsigned int ts_ttime);
+
+/* functions that might be useful and might be added some day ...
+int pkt_shift_data(struct packet *pkt, unsigned int from, unsigned int to, unsigned int len);
+int pkt_tcp_change_seqno(int rel_seq, int rel_ackseq);
+int pkt_tcp_set_seqno(unsigned int seq, unsigned int ackseq);
+int pkt_ip_option(struct packet *pkt, unsigned char code, unsigned char len, unsigned char ptr);
+int pkt_ip_option_addval(struct *pkt, unsigned char posptr, unsigned int optval);
+*/
+
+#endif
--- /dev/null
+/* $Id: misc.c,v 1.1 2005/12/12 18:14:22 nobunaga Exp $
+
+Copyright (C) 2002 Marc Kirchner <kirchner@stud.fh-heilbronn.de>
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "libpal.h"
+
+/*
+<++doc++>
+@name int pkt_add_systimestamp(struct packet *pkt)
+@desc Adds a system timestamp (struct timeval) at the position where pkt->pkt_ptr points to.
+@param pkt packet into which a timestamp with the current system time will be added.
+<--doc-->
+*/
+int
+pkt_add_systimestamp(struct packet *pkt)
+{
+ if (!pkt)
+ return EPKTINVALPTR;
+ if (pkt->pkt_size < (pkt->pkt_pos + sizeof(struct timeval)))
+ return EPKTRANGE;
+ if (gettimeofday((struct timeval *)pkt->pkt_ptr, NULL) == 0)
+ return 0;
+ else
+ return EERRNO;
+}
+
--- /dev/null
+/* $Id: packet.c,v 1.1 2005/12/12 18:14:22 nobunaga Exp $
+
+Copyright (C) 2002 Marc Kirchner <kirchner@stud.fh-heilbronn.de>
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "libpal.h"
+
+/*
+<++doc++>
+@name int pkt_init(struct packet *pkt, unsigned long type, unsigned int size)
+@desc Allocates memory for a new packet and initializes its internal variables
+@param pkt pointer to the new packet
+@param type type of the packet. Its setting is currently ignored, but this is likely to change. Possible values are e.g. PKT_NET_IP|PKT_TRANS_TCP. See packet.h for other values
+@param size overall size if the packet not including ethernet headers or trailers.
+<--doc-->
+*/
+int
+pkt_init(struct packet *pkt, unsigned long type, unsigned int size)
+{
+ if ((pkt->pkt = (unsigned char *) malloc(size)) == NULL) {
+ /* no mem, we assume errno will be set */
+ return -1;
+ } else {
+ /* clear mem out */
+ memset(pkt->pkt, 0, size);
+ /* init vars */
+ pkt->pkt_type = type;
+ pkt->pkt_size = size;
+ /* set active ptr to beginning of mem */
+ pkt->pkt_ptr = pkt->pkt;
+ pkt->pkt_pos = 0;
+ return 0;
+ }
+}
+
+/*
+<++doc++>
+@name int pkt_free(struct packet *pkt)
+@desc Used to destroy a packet and to free used memory
+@param pkt the packet to destroy
+<--doc-->
+*/
+int
+pkt_free(struct packet *pkt)
+{
+ if (pkt) {
+ free(pkt->pkt);
+ pkt->pkt=NULL;
+ return 0;
+ }
+ return EPKTINVALPTR;
+}
+
+/*
+<++doc++>
+@name int pkt_set_actptr(struct packet *pkt, unsigned int bytepos)
+@desc This function sets the active pointer position inside the packet.
+@param pkt the packet whose active ptr is to be set
+@param bytepos the byte position where to set the active ptr to, starting from 0
+<--doc-->
+*/
+
+int
+pkt_set_actptr(struct packet *pkt, unsigned int bytepos)
+{
+ if (!pkt)
+ return EPKTINVALPTR;
+ if (bytepos > pkt->pkt_size) {
+ return EPKTRANGE;
+ } else {
+ pkt->pkt_ptr = pkt->pkt + bytepos;
+ return PKTOK;
+ }
+}
+
+/*
+<++doc++>
+@name int pkt_move_actptr(struct packet *pkt, int relmov)
+@desc This function moves the active pointer inside the packet.
+@param pkt the packet whose active ptr is to be moved
+@param relmov number of bytes the active ptr shall be moved. To move it backward, negative values may be used.
+<--doc-->
+*/
+int
+pkt_move_actptr(struct packet *pkt, int relmov)
+{
+ if (!pkt)
+ return EPKTINVALPTR;
+ if ((pkt->pkt_pos + relmov > pkt->pkt_size) ||
+ (pkt->pkt_pos + relmov < 0)) {
+ return EPKTRANGE;
+ } else {
+ pkt->pkt_ptr += relmov;
+ return PKTOK;
+ }
+}
+
+/*
+<++doc++>
+@name int pkt_add_data(struct packet *pkt, char *data, size_t data_len)
+@desc Adds supplied data at the current active ptr position of the given packet.This basically is a memcpy() wrapper function.
+@param pkt data will be written into this packet
+@param data a pointer to the data that shall be copied into the packet
+@param data_len the amount of data (in bytes) that will be copied
+<--doc-->
+*/
+int
+pkt_add_data(struct packet *pkt, char *data, size_t data_len)
+{
+ if (!pkt || !data)
+ return EPKTINVALPTR;
+ if (pkt->pkt_size >= (pkt->pkt_pos + data_len)) {
+ memcpy(pkt->pkt_ptr, data, data_len);
+ return 0;
+ } else
+ return EPKTRANGE;
+}
+
+/*
+<++doc++>
+@name int pkt_resize(struct packet *pkt, unsigned int newsize)
+@desc The given packet will be resized to newsize
+@param pkt the packet to resize
+@param newsize the new size of the packet
+<--doc-->
+*/
+int
+pkt_resize(struct packet *pkt, unsigned int newsize)
+{
+ unsigned char *newpkt;
+
+ if (!pkt)
+ return EPKTINVALPTR;
+
+ if ((newpkt = (unsigned char *) malloc(newsize)) != NULL) {
+ memset(newpkt, 0, newsize);
+ memcpy(newpkt, pkt->pkt, (pkt->pkt_size < newsize ? pkt->pkt_size : newsize));
+ pkt->pkt_size = newsize;
+ pkt->pkt_ptr = newpkt;
+ pkt->pkt_pos = 0;
+ /* free old mem */
+ free (pkt->pkt);
+ pkt->pkt = newpkt;
+ return 0;
+ } else
+ return EERRNO;
+}
--- /dev/null
+/* $Id: socket.c,v 1.1 2005/12/12 18:14:22 nobunaga Exp $
+
+Copyright (C) 2002 Marc Kirchner <kirchner@stud.fh-heilbronn.de>
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "libpal.h"
+
+/*
+<++doc++>
+@name int pkt_socket_open(struct pkt_socket *sck, int type)
+@desc Opens a packet socket. This is necessary to be able to send any packages.
+@param sck pointer to a pkt_socket structure
+@param type The type of the socket. Possible values are PKT_RAW (to open a raw socket. IP, TCP/UDP and application header have to be forged before sending) , PKT_STREAM, PKT_DGRAM. STREAM and DGRAM are supported by this function, but other function do not care.
+<--doc-->
+*/
+int
+pkt_socket_open(struct pkt_socket *sck, int type)
+{
+ int proto;
+ int iphdrincl = 1;
+ int ret = 0;
+
+ if (!sck)
+ return EPKTINVALPTR;
+
+ /* get mem for sockaddr structure */
+ if ((sck->sckad = (struct sockaddr_in *) malloc (sizeof(struct sockaddr_in))) == NULL) {
+ return -1;
+ }
+ sck->sckad_len = sizeof(struct sockaddr_in);
+ memset(sck->sckad, 0, sck->sckad_len);
+
+ /* except for raw sockets, proto is set to 0 */
+ /* (Stevens, UNP 2nd ed., 1998) */
+ switch (type) {
+ case PKT_RAW:
+ proto = IPPROTO_RAW;
+ break;
+ default:
+ proto = 0;
+ break;
+ }
+ if ((sck->rawfd = socket(AF_INET, type, proto)) == -1) {
+ return -1;
+ }
+ if (type == PKT_RAW) {
+ if ((ret = setsockopt(sck->rawfd, IPPROTO_IP, IP_HDRINCL, (const void *) &iphdrincl, sizeof(iphdrincl))) < 0) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+
+/*
+<++doc++>
+@name int pkt_socket_close(struct pkt_socket *sck)
+@desc Closes a packet socket and frees used memory.
+@param sck pointer to a pkt_socket structure
+<--doc-->
+*/
+int
+pkt_socket_close(struct pkt_socket *sck)
+{
+ if (!sck)
+ return EPKTINVALPTR;
+ close(sck->rawfd);
+ free(sck->sckad);
+ sck->sckad=NULL;
+ return 0;
+}
+
+/*
+<++doc++>
+@name int pkt_socket_prepare(struct pkt_socket *sck, char *daddr)
+@desc this function is necessary to enable the kernel to determine the correct outgoing interface
+@param sck pointer to a pkt_socket structure
+@param daddr dotted-decimal destination IP address
+<--doc-->
+*/
+int
+pkt_socket_prepare(struct pkt_socket *sck, char *daddr)
+{
+ /*
+ * this is necessary for the kernel to determine outgoing
+ * interface.
+ */
+
+ int ret = 0;
+
+ if (!sck || !daddr)
+ return EPKTINVALPTR;
+
+ /* set up sockaddr struct */
+ memset(sck->sckad, 0, sck->sckad_len);
+ if ((ret = inet_pton(AF_INET, daddr, &(sck->sckad->sin_addr))) == 0) {
+ return -1;
+ }
+ sck->sckad->sin_family = AF_INET;
+
+ /*
+ * i dont think we need to set the dest port...
+ */
+ return 0;
+}
+
+/*
+<++doc++>
+@name int pkt_socket_setopt(struct pkt_socket *sck, int level, int optname, void *optval, socklen_t optlen)
+@desc this is basically a wrapper function for setsockopt(2)
+@param sck pointer to a pkt_socket structure
+@param level level the socket option will apply to (should be SOL_SOCKET)
+@param optname option name, see sys/socket.h for values
+@param optval new option value (for boolean options: 0=false)
+@param optlen option value size (this is a value-result parameter!)
+<--doc-->
+*/
+int
+pkt_socket_setopt(struct pkt_socket *sck, int level,
+ int optname, void *optval, socklen_t optlen)
+{
+ if (!sck)
+ return EPKTINVALPTR;
+ return (setsockopt(sck->rawfd, level, optname, optval, optlen));
+}
+
+
+/*
+<++doc++>
+@name int pkt_send(struct packet *pkt, struct pkt_socket *sck)
+@desc sends the packet pkt unsing the socket sck
+@param pkt pointer to a packet structure
+@param sck pointer to a pkt_socket structure
+<--doc-->
+*/
+int
+pkt_send(struct packet *pkt, struct pkt_socket *sck)
+{
+ int ret = 0;
+
+ if (!pkt || !sck)
+ return EPKTINVALPTR;
+
+ /* no sendto-flags support */
+ if ((ret = sendto(sck->rawfd, pkt->pkt, pkt->pkt_size, 0, (struct sockaddr *) sck->sckad, sck->sckad_len)) == -1) {
+ return -1;
+ }
+ return 0;
+}
--- /dev/null
+/* $Id: tcp.c,v 1.2 2009/06/19 12:50:47 faust Exp $
+
+Copyright (C) 2002 Marc Kirchner <kirchner@stud.fh-heilbronn.de>
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "libpal.h"
+#include "types.h" /* internal types */
+
+int
+pkt_tcp_header(struct packet *pkt,
+ unsigned short int sport,
+ unsigned short int dport,
+ unsigned int seq,
+ unsigned int ackseq,
+ unsigned char headerlen,
+ unsigned char reserved,
+ unsigned char flags,
+ unsigned short window,
+ unsigned short int checksum,
+ unsigned short int urgent)
+{
+ struct tcphdr *tcp;
+
+ if (!pkt)
+ return EPKTINVALPTR;
+
+ tcp = (struct tcphdr *) pkt->pkt_ptr;
+ tcp->source = htons(sport);
+ tcp->dest = htons(dport);
+ tcp->seq = htonl(seq);
+ tcp->ack_seq = htonl(ackseq);
+ tcp->window = htons(window);
+ tcp->urg_ptr = htons(urgent);
+
+ tcp->doff = headerlen;
+ tcp->res1 = reserved;
+ if (flags) {
+ tcp->fin = ((flags & TH_FIN) != 0);
+ tcp->syn = ((flags & TH_SYN) != 0);
+ tcp->rst = ((flags & TH_RST) != 0);
+ tcp->psh = ((flags & TH_RST) != 0);
+ tcp->ack = ((flags & TH_ACK) != 0);
+ tcp->urg = ((flags & TH_URG) != 0);
+# if __BYTE_ORDER == __LITTLE_ENDIAN
+ tcp->res2 = (flags & (TH_XMAS | TH_YMAS)) >> 6;
+# elif __BYTE_ORDER == __BIG_ENDIAN
+ tcp->res2 = (flags & (TH_XMAS | TH_YMAS));
+# else
+# error "Adjust your <bits/endian.h> defines"
+# endif
+ } else {
+ tcp->fin = 0;
+ tcp->syn = 0;
+ tcp->rst = 0;
+ tcp->psh = 0;
+ tcp->ack = 0;
+ tcp->urg = 0;
+ tcp->res2 = 0;
+ }
+ tcp->check = htons(checksum);
+ return 0;
+}
+
+int
+pkt_tcp_cksum(struct packet *pkt, char *saddr, char *daddr,
+ unsigned int tcp_pkt_size)
+{
+ char *tosum;
+ struct pseudohdr *psh;
+ struct tcphdr *tcp;
+ struct in_addr addr;
+
+ if (!pkt || !saddr || !daddr)
+ return EPKTINVALPTR;
+
+ if ((tcp_pkt_size + pkt->pkt_pos) > pkt->pkt_size -1)
+ return EPKTRANGE;
+
+ if ((tosum = (char *) malloc(tcp_pkt_size+sizeof(struct pseudohdr))) != NULL) {
+ memset(tosum, 0, tcp_pkt_size+sizeof(struct pseudohdr));
+ psh = (struct pseudohdr *) tosum;
+ tcp = (struct tcphdr *) pkt->pkt_ptr;
+
+ tcp->check = 0;
+
+ if (inet_pton(AF_INET, saddr, &addr) < 0)
+ return EERRNO;
+ psh->saddr = addr.s_addr;
+ if (inet_pton(AF_INET, daddr, &addr) < 0)
+ return EERRNO;
+ psh->daddr = addr.s_addr;
+ psh->zero = 0x00;
+ psh->protocol = IPPROTO_TCP;
+ psh->length = htons(tcp_pkt_size);
+
+ memcpy(tosum + sizeof(struct pseudohdr), tcp, tcp_pkt_size);
+ tcp->check = in_cksum((unsigned short *)tosum, tcp_pkt_size + sizeof(struct pseudohdr));
+ free(tosum);
+ return 0;
+ } else
+ return EERRNO;
+}
+
+int
+pkt_tcp_option(struct packet *pkt, unsigned char kind,
+ unsigned char len, void *optval, size_t optlen)
+{
+ void *vp;
+ unsigned short int mss;
+
+ if (!pkt)
+ return EPKTINVALPTR;
+
+ if ((pkt->pkt_size) < (pkt->pkt_pos+2+optlen))
+ return EPKTRANGE;
+
+ vp = (void *)pkt->pkt_ptr;
+
+ memcpy(vp, &kind, 1);
+ char * p;
+ p = (char*)vp;
+ p++;
+ vp = p;
+ //vp++;
+ memcpy(vp, &len, 1);
+ //vp++;
+ p = (char*)vp;
+ p++;
+ vp = p;
+ if (kind == PKT_TCP_OPT_MSS) {
+ mss = htons(*(unsigned short int *)optval);
+ memcpy(vp, &mss, optlen);
+ } else if (kind == PKT_TCP_OPT_TIME) {
+ unsigned int time = htonl(*(unsigned int *)optval);
+ memcpy(vp, &time, optlen);
+ } else {
+ memcpy(vp, optval, optlen);
+ }
+ return 0;
+}
--- /dev/null
+/* $Id: types.h,v 1.1 2005/12/12 18:14:22 nobunaga Exp $
+
+Copyright (C) 2002 Marc Kirchner <kirchner@stud.fh-heilbronn.de>
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef _LIBPAL_TYPES_H_
+#define _LIBPAL_TYPES_H_
+
+/*
+* these are types users wont need
+*/
+
+/* Stevens' pseudo header */
+struct pseudohdr {
+ u_int32_t saddr;
+ u_int32_t daddr;
+ u_int8_t zero;
+ u_int8_t protocol;
+ u_int16_t length;
+};
+#endif
--- /dev/null
+/* $Id: udp.c,v 1.1 2005/12/12 18:14:22 nobunaga Exp $
+
+Copyright (C) 2002 Marc Kirchner <kirchner@stud.fh-heilbronn.de>
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "libpal.h"
+#include "types.h"
+
+int
+pkt_udp_header(struct packet *pkt, unsigned short int sport, unsigned short int dport, unsigned short int udp_total_len, unsigned short int checksum)
+{
+ struct udphdr *udp;
+
+ if (!pkt)
+ return EPKTINVALPTR;
+ if (pkt->pkt_size >= (pkt->pkt_pos + sizeof(struct udphdr))) {
+ udp = (struct udphdr *) pkt->pkt_ptr;
+ udp->source = htons(sport);
+ udp->dest = htons(dport);
+ udp->len = htons(udp_total_len);
+ udp->check = htons(checksum);
+ return 0;
+ } else
+ return EPKTRANGE;
+}
+
+int
+pkt_udp_cksum(struct packet *pkt, char *saddr, char *daddr,
+ unsigned int udp_total_len)
+{
+ char *tosum;
+ struct pseudohdr *psh;
+ struct udphdr *udp;
+ unsigned short int check=0;
+ struct in_addr addr;
+
+ if (!pkt || !saddr || !daddr)
+ return EPKTINVALPTR;
+
+ if ((udp_total_len + pkt->pkt_pos) > pkt->pkt_size -1)
+ return EPKTRANGE;
+
+ if ((tosum = (char *) malloc(udp_total_len+sizeof(struct pseudohdr))) != NULL) {
+ memset(tosum, 0, udp_total_len+sizeof(struct pseudohdr));
+ psh = (struct pseudohdr *) tosum;
+ udp = (struct udphdr *) pkt->pkt_ptr;
+
+ udp->check = 0;
+
+ if (inet_pton(AF_INET, saddr, &addr) < 0)
+ return EERRNO;
+ psh->saddr = addr.s_addr;
+ if (inet_pton(AF_INET, daddr, &addr) < 0)
+ return EERRNO;
+ psh->daddr = addr.s_addr;
+ psh->zero = 0x00;
+ psh->protocol = IPPROTO_UDP;
+ psh->length = htons(udp_total_len);
+
+ memcpy(tosum + sizeof(struct pseudohdr), udp, udp_total_len);
+ check = in_cksum((unsigned short *)tosum, udp_total_len + sizeof(struct pseudohdr));
+ /* _no_ call to htons(), because tosum is in network byte order */
+ udp->check = check == 0 ? 0xffff : check;
+ free(tosum);
+ return 0;
+ } else
+ return EERRNO;
+}
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.2 2008/12/04 17:04:41 faust Exp $
+###############################################################################
+
+include ../../../../../Makefile.conf
+
+PROG = mod_cap_nf.so
+
+SRCS = ./cap_nf.cpp
+
+LIBS += $(LIB_THREAD)
+STGLIBS = -lstg_common
+
+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
+ */
+
+/*
+Date: 16.05.2008
+*/
+
+/*
+* Author : Maxim Mamontov <faust@stg.dp.ua>
+*/
+
+/*
+$Revision: 1.11 $
+$Date: 2010/09/10 06:41:06 $
+$Author: faust $
+*/
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+
+#include <csignal>
+#include <cerrno>
+#include <cstring>
+
+#include "common.h"
+#include "cap_nf.h"
+#include "raw_ip_packet.h"
+
+#include "../../../traffcounter.h"
+
+class CAP_NF_CREATOR
+{
+public:
+ CAP_NF_CREATOR()
+ : nf(new NF_CAP())
+ {
+ };
+
+ ~CAP_NF_CREATOR()
+ {
+ delete nf;
+ };
+
+ NF_CAP * GetCapturer() { return nf; };
+private:
+ NF_CAP * nf;
+} cnc;
+
+BASE_PLUGIN * GetPlugin()
+{
+return cnc.GetCapturer();
+}
+
+NF_CAP::NF_CAP()
+ : traffCnt(NULL),
+ tidTCP(0),
+ tidUDP(0),
+ runningTCP(false),
+ runningUDP(false),
+ stoppedTCP(true),
+ stoppedUDP(true),
+ portT(0),
+ portU(0),
+ sockTCP(-1),
+ sockUDP(-1)
+{
+}
+
+NF_CAP::~NF_CAP()
+{
+}
+
+int NF_CAP::ParseSettings()
+{
+vector<PARAM_VALUE>::iterator it;
+for (it = settings.moduleParams.begin(); it != settings.moduleParams.end(); ++it)
+ {
+ if (it->param == "TCPPort")
+ {
+ if (str2x(it->value[0], portT))
+ {
+ errorStr = "Invalid TCPPort value";
+ printfd(__FILE__, "Error: Invalid TCPPort value\n");
+ return -1;
+ }
+ continue;
+ }
+ if (it->param == "UDPPort")
+ {
+ if (str2x(it->value[0], portU))
+ {
+ errorStr = "Invalid UDPPort value";
+ printfd(__FILE__, "Error: Invalid UDPPort value\n");
+ return -1;
+ }
+ continue;
+ }
+ printfd(__FILE__, "'%s' is not a valid module param\n", it->param.c_str());
+ }
+return 0;
+}
+
+int NF_CAP::Start()
+{
+if (portU > 0)
+ {
+ if (OpenUDP())
+ {
+ return -1;
+ }
+ runningUDP = true;
+ if (pthread_create(&tidUDP, NULL, RunUDP, this))
+ {
+ runningUDP = false;
+ CloseUDP();
+ errorStr = "Cannot create UDP thread";
+ printfd(__FILE__, "Error: Cannot create UDP thread\n");
+ return -1;
+ }
+ }
+if (portT > 0)
+ {
+ if (OpenTCP())
+ {
+ return -1;
+ }
+ runningTCP = true;
+ if (pthread_create(&tidTCP, NULL, RunTCP, this))
+ {
+ runningTCP = false;
+ CloseTCP();
+ errorStr = "Cannot create TCP thread";
+ printfd(__FILE__, "Error: Cannot create TCP thread\n");
+ return -1;
+ }
+ }
+return 0;
+}
+
+int NF_CAP::Stop()
+{
+runningTCP = runningUDP = false;
+if (portU && !stoppedUDP)
+ {
+ CloseUDP();
+ for (int i = 0; i < 25 && !stoppedUDP; ++i)
+ {
+ usleep(200000);
+ }
+ if (stoppedUDP)
+ {
+ pthread_join(tidUDP, NULL);
+ }
+ else
+ {
+ if (pthread_kill(tidUDP, SIGUSR1))
+ {
+ errorStr = "Error sending signal to UDP thread";
+ printfd(__FILE__, "Error: Error sending signal to UDP thread\n");
+ return -1;
+ }
+ printfd(__FILE__, "UDP thread NOT stopped\n");
+ }
+ }
+if (portT && !stoppedTCP)
+ {
+ CloseTCP();
+ for (int i = 0; i < 25 && !stoppedTCP; ++i)
+ {
+ usleep(200000);
+ }
+ if (stoppedTCP)
+ {
+ pthread_join(tidTCP, NULL);
+ }
+ else
+ {
+ if (pthread_kill(tidTCP, SIGUSR1))
+ {
+ errorStr = "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");
+ }
+ }
+return 0;
+}
+
+bool NF_CAP::OpenUDP()
+{
+struct sockaddr_in sin;
+sockUDP = socket(PF_INET, SOCK_DGRAM, 0);
+if (sockUDP <= 0)
+ {
+ errorStr = "Error opening UDP socket";
+ printfd(__FILE__, "Error: Error opening UDP socket\n");
+ return true;
+ }
+sin.sin_family = AF_INET;
+sin.sin_port = htons(portU);
+sin.sin_addr.s_addr = inet_addr("0.0.0.0");
+if (bind(sockUDP, (struct sockaddr *)&sin, sizeof(sin)))
+ {
+ errorStr = "Error binding UDP socket";
+ printfd(__FILE__, "Error: Error binding UDP socket\n");
+ return true;
+ }
+return false;
+}
+
+bool NF_CAP::OpenTCP()
+{
+struct sockaddr_in sin;
+sockTCP = socket(PF_INET, SOCK_STREAM, 0);
+if (sockTCP <= 0)
+ {
+ errorStr = "Error opening TCP socket";
+ printfd(__FILE__, "Error: Error opening TCP socket\n");
+ return true;
+ }
+sin.sin_family = AF_INET;
+sin.sin_port = htons(portT);
+sin.sin_addr.s_addr = inet_addr("0.0.0.0");
+if (bind(sockTCP, (struct sockaddr *)&sin, sizeof(sin)))
+ {
+ errorStr = "Error binding TCP socket";
+ printfd(__FILE__, "Error: Error binding TCP socket\n");
+ return true;
+ }
+if (listen(sockTCP, 1))
+ {
+ errorStr = "Error listening on TCP socket";
+ printfd(__FILE__, "Error: Error listening TCP socket\n");
+ return true;
+ }
+return false;
+}
+
+void * NF_CAP::RunUDP(void * c)
+{
+NF_CAP * cap = static_cast<NF_CAP *>(c);
+uint8_t buf[BUF_SIZE];
+int res;
+struct sockaddr_in sin;
+socklen_t slen;
+cap->stoppedUDP = false;
+while (cap->runningUDP)
+ {
+ if (!cap->WaitPackets(cap->sockUDP))
+ {
+ continue;
+ }
+
+ // Data
+ slen = sizeof(sin);
+ res = recvfrom(cap->sockUDP, buf, BUF_SIZE, 0, reinterpret_cast<struct sockaddr *>(&sin), &slen);
+ if (!cap->runningUDP)
+ break;
+
+ if (res == 0) // EOF
+ {
+ continue;
+ }
+
+
+ // Wrong logic!
+ // Need to check actual data length and wait all data to receive
+ if (res < 24)
+ {
+ if (errno != EINTR)
+ {
+ cap->errorStr = "Invalid data received";
+ printfd(__FILE__, "Error: Invalid data received through UDP\n");
+ }
+ continue;
+ }
+
+ cap->ParseBuffer(buf, res);
+ }
+cap->stoppedUDP = true;
+return NULL;
+}
+
+void * NF_CAP::RunTCP(void * c)
+{
+NF_CAP * cap = static_cast<NF_CAP *>(c);
+uint8_t buf[BUF_SIZE];
+int res;
+int sd;
+struct sockaddr_in sin;
+socklen_t slen;
+cap->stoppedTCP = false;
+while (cap->runningTCP)
+ {
+ if (!cap->WaitPackets(cap->sockTCP))
+ {
+ continue;
+ }
+
+ // Data
+ slen = sizeof(sin);
+ sd = accept(cap->sockTCP, reinterpret_cast<struct sockaddr *>(&sin), &slen);
+ if (!cap->runningTCP)
+ break;
+
+ if (sd <= 0)
+ {
+ if (errno != EINTR)
+ {
+ cap->errorStr = "Error accepting connection";
+ printfd(__FILE__, "Error: Error accepting connection\n");
+ }
+ continue;
+ }
+
+ if (!cap->WaitPackets(sd))
+ {
+ close(sd);
+ continue;
+ }
+
+ res = recv(sd, buf, BUF_SIZE, MSG_WAITALL);
+ close(sd);
+
+ if (!cap->runningTCP)
+ break;
+
+ if (res == 0) // EOF
+ {
+ continue;
+ }
+
+ // Wrong logic!
+ // Need to check actual data length and wait all data to receive
+ if (res < 24)
+ {
+ if (errno != EINTR)
+ {
+ cap->errorStr = "Invalid data received";
+ printfd(__FILE__, "Error: Invalid data received through TCP\n");
+ }
+ continue;
+ }
+
+ cap->ParseBuffer(buf, res);
+ }
+cap->stoppedTCP = true;
+return NULL;
+}
+
+void NF_CAP::ParseBuffer(uint8_t * buf, int size)
+{
+RAW_PACKET ip;
+NF_HEADER * hdr = reinterpret_cast<NF_HEADER *>(buf);
+if (htons(hdr->version) != 5)
+ {
+ return;
+ }
+
+int packets = htons(hdr->count);
+
+if (packets < 0 || packets > 30)
+ {
+ return;
+ }
+
+if (24 + 48 * packets != size)
+ {
+ // See 'wrong logic' upper
+ return;
+ }
+
+for (int i = 0; i < packets; ++i)
+ {
+ NF_DATA * data = reinterpret_cast<NF_DATA *>(buf + 24 + i * 48);
+
+ /*ip.pckt[0] = 4 << 4;
+ ip.pckt[0] |= 5;
+ ip.pckt[9] = data->proto;
+ ip.dataLen = ntohl(data->octets);
+ *(uint32_t *)(ip.pckt + 12) = data->srcAddr;
+ *(uint32_t *)(ip.pckt + 16) = data->dstAddr;
+ *(uint16_t *)(ip.pckt + 20) = data->srcPort;
+ *(uint16_t *)(ip.pckt + 22) = data->dstPort;*/
+ ip.ipHeader.ip_v = 4;
+ ip.ipHeader.ip_hl = 5;
+ ip.ipHeader.ip_p = data->proto;
+ ip.dataLen = ntohl(data->octets);
+ ip.ipHeader.ip_src.s_addr = data->srcAddr;
+ ip.ipHeader.ip_dst.s_addr = data->dstAddr;
+ ip.sPort = data->srcPort;
+ ip.dPort = data->dstPort;
+
+ traffCnt->Process(ip);
+ }
+}
+
+bool NF_CAP::WaitPackets(int sd) const
+{
+fd_set rfds;
+FD_ZERO(&rfds);
+FD_SET(sd, &rfds);
+
+struct timeval tv;
+tv.tv_sec = 0;
+tv.tv_usec = 500000;
+
+int res = select(sd + 1, &rfds, NULL, NULL, &tv);
+if (res == -1) // Error
+ {
+ if (errno != EINTR)
+ {
+ printfd(__FILE__, "Error on select: '%s'\n", strerror(errno));
+ }
+ return false;
+ }
+
+if (res == 0) // Timeout
+ {
+ return false;
+ }
+
+return true;
+}
--- /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: 16.05.2008
+*/
+
+/*
+* Author : Maxim Mamontov <faust@stg.dp.ua>
+*/
+
+/*
+$Revision: 1.5 $
+$Date: 2009/12/13 12:56:07 $
+$Author: faust $
+*/
+#ifndef __CAP_NF_H__
+#define __CAP_NF_H__
+
+#include <string>
+#include <pthread.h>
+
+#include "os_int.h"
+#include "base_plugin.h"
+
+#define VERSION "CAP_NF v. 0.4"
+#define START_POS 0
+#define STOP_POS 0
+
+struct NF_HEADER
+{
+ uint16_t version; // Protocol version
+ uint16_t count; // Flows count
+ uint32_t uptime; // System uptime
+ uint32_t timestamp; // UNIX timestamp
+ uint32_t nsecs; // Residual nanoseconds
+ uint32_t flowSeq; // Sequence counter
+ uint8_t eType; // Engine type
+ uint8_t eID; // Engine ID
+ uint16_t sInterval; // Sampling mode and interval
+} __attribute__ ((packed));
+
+struct NF_DATA
+{
+ uint32_t srcAddr; // Flow source address
+ uint32_t dstAddr; // Flow destination address
+ uint32_t nextHop; // IP addres on next hop router
+ uint16_t inSNMP; // SNMP index of input iface
+ uint16_t outSNMP; // SNMP index of output iface
+ uint32_t packets; // Packets in flow
+ uint32_t octets; // Total number of bytes in flow
+ uint32_t timeStart; // Uptime on first packet in flow
+ uint32_t timeFinish;// Uptime on last packet in flow
+ uint16_t srcPort; // Flow source port
+ uint16_t dstPort; // Flow destination port
+ uint8_t pad1; // 1-byte padding
+ uint8_t TCPFlags; // Cumulative OR of TCP flags
+ uint8_t proto; // IP protocol type (tcp, udp, etc.)
+ uint8_t tos; // IP Type of Service (ToS)
+ uint16_t srcAS; // Source BGP autonomous system number
+ uint16_t dstAS; // Destination BGP autonomus system number
+ uint8_t srcMask; // Source address mask in "slash" notation
+ uint8_t dstMask; // Destination address mask in "slash" notation
+ uint16_t pad2; // 2-byte padding
+} __attribute__ ((packed));
+
+#define BUF_SIZE (sizeof(NF_HEADER) + 30 * sizeof(NF_DATA))
+
+class NF_CAP : public BASE_PLUGIN
+{
+public:
+ NF_CAP();
+ ~NF_CAP();
+
+ void SetUsers(USERS *) {};
+ void SetTariffs(TARIFFS *) {};
+ void SetAdmins(ADMINS *) {};
+ void SetTraffcounter(TRAFFCOUNTER * tc) { traffCnt = tc; };
+ void SetStore(BASE_STORE *) {};
+ void SetStgSettings(const SETTINGS *) {};
+ void SetSettings(const MODULE_SETTINGS & s) { settings = s; };
+ int ParseSettings();
+
+ int Start();
+ int Stop();
+ int Reload() { return 0; };
+ bool IsRunning() { return runningTCP || runningUDP; };
+ const string & GetStrError() const { return errorStr; };
+ const string GetVersion() const { return VERSION; };
+ uint16_t GetStartPosition() const { return START_POS; };
+ uint16_t GetStopPosition() const { return STOP_POS; };
+
+private:
+ TRAFFCOUNTER * traffCnt;
+ MODULE_SETTINGS settings;
+ pthread_t tidTCP;
+ pthread_t tidUDP;
+ bool runningTCP;
+ bool runningUDP;
+ bool stoppedTCP;
+ bool stoppedUDP;
+ uint16_t portT;
+ uint16_t portU;
+ int sockTCP;
+ int sockUDP;
+ mutable std::string errorStr;
+
+ static void * RunUDP(void *);
+ static void * RunTCP(void *);
+ void ParseBuffer(uint8_t *, int);
+
+ bool OpenTCP();
+ bool OpenUDP();
+ void CloseTCP() { close(sockTCP); };
+ void CloseUDP() { close(sockUDP); };
+
+ bool WaitPackets(int sd) const;
+};
+
+extern "C" BASE_PLUGIN * GetPlugin();
+
+#endif
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.4 2008/12/04 17:05:21 faust Exp $
+###############################################################################
+
+include ../../../../../Makefile.conf
+
+PROG = mod_cap_divert.so
+
+SRCS = ./divert_cap.cpp
+
+STGLIBS = -lstg_common
+
+LIBS += $(LIB_THREAD)
+
+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 : Boris Mikhailenko <stg34@stg.dp.ua>
+*/
+
+/*
+$Revision: 1.13 $
+$Date: 2010/09/10 06:43:03 $
+*/
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <string.h>
+
+#include <sys/uio.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "divert_cap.h"
+
+#define BUFF_LEN (16384) /* max mtu -> lo=16436 TODO why?*/
+
+//-----------------------------------------------------------------------------
+struct DIVERT_DATA
+{
+int sock;
+short int port;
+unsigned char buffer[BUFF_LEN];
+char iface[10];
+};
+//-----------------------------------------------------------------------------
+pollfd pollddiv;
+DIVERT_DATA cddiv; //capture data
+//-----------------------------------------------------------------------------
+class DIVERT_CAP_CREATOR
+{
+private:
+ DIVERT_CAP * divc;
+
+public:
+ DIVERT_CAP_CREATOR()
+ : divc(new DIVERT_CAP())
+ {
+ };
+ ~DIVERT_CAP_CREATOR()
+ {
+ delete divc;
+ };
+
+ DIVERT_CAP * GetCapturer()
+ {
+ return divc;
+ };
+};
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+DIVERT_CAP_CREATOR dcc;
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+BASE_PLUGIN * GetPlugin()
+{
+return dcc.GetCapturer();
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+const string DIVERT_CAP::GetVersion() const
+{
+return "Divert_cap v.1.0";
+}
+//-----------------------------------------------------------------------------
+DIVERT_CAP::DIVERT_CAP()
+{
+isRunning = false;
+nonstop = false;
+}
+//-----------------------------------------------------------------------------
+void DIVERT_CAP::SetTraffcounter(TRAFFCOUNTER * tc)
+{
+traffCnt = tc;
+}
+//-----------------------------------------------------------------------------
+const string & DIVERT_CAP::GetStrError() const
+{
+return errorStr;
+}
+//-----------------------------------------------------------------------------
+int DIVERT_CAP::Start()
+{
+if (isRunning)
+ return 0;
+
+if (DivertCapOpen() < 0)
+ {
+ errorStr = "Cannot open socket!";
+ printfd(__FILE__, "Cannot open socket\n");
+ return -1;
+ }
+
+nonstop = true;
+
+if (pthread_create(&thread, NULL, Run, this) == 0)
+ {
+ return 0;
+ }
+
+errorStr = "Cannot create thread.";
+printfd(__FILE__, "Cannot create thread\n");
+return -1;
+}
+//-----------------------------------------------------------------------------
+int DIVERT_CAP::Stop()
+{
+if (!isRunning)
+ return 0;
+
+DivertCapClose();
+
+nonstop = false;
+
+//5 seconds to thread stops itself
+int i;
+for (i = 0; i < 25; i++)
+ {
+ if (!isRunning)
+ break;
+
+ usleep(200000);
+ }
+
+//after 5 seconds waiting thread still running. now killing it
+if (isRunning)
+ {
+ if (pthread_kill(thread, SIGINT))
+ {
+ errorStr = "Cannot kill thread.";
+ printfd(__FILE__, "Cannot kill thread\n");
+ return -1;
+ }
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+bool DIVERT_CAP::IsRunning()
+{
+return isRunning;
+}
+//-----------------------------------------------------------------------------
+void * DIVERT_CAP::Run(void * d)
+{
+DIVERT_CAP * dc = (DIVERT_CAP *)d;
+dc->isRunning = true;
+
+/*struct ETH_IP
+{
+uint16_t ethHdr[8];
+RAW_PACKET rp;
+char padding[4];
+char padding1[8];
+};
+
+ETH_IP * ethIP;
+
+char ethip[sizeof(ETH_IP)];
+
+//memset(ðIP, 0, sizeof(ethIP));
+memset(ðip, 0, sizeof(ETH_IP));
+
+ethIP = (ETH_IP *)ðip;
+ethIP->rp.dataLen = -1;
+*/
+//char * iface = NULL;
+char buffer[64];
+while (dc->nonstop)
+ {
+ RAW_PACKET rp;
+ dc->DivertCapRead(buffer, 64, NULL);
+
+ //printf("%x %x %x %x \n", buffer[0], buffer[4], buffer[8], buffer[12]);
+ //printf("%x %x %x %x \n", buffer[16], buffer[20], buffer[24], buffer[28]);
+ //printf("%x %x %x %x \n", buffer[32], buffer[36], buffer[40], buffer[44]);
+
+ if (buffer[12] != 0x8)
+ continue;
+
+ memcpy(rp.pckt, &buffer[14], pcktSize);
+
+ //dc->traffCnt->Process(*((RAW_PACKET*)( &buffer[14] ))); // - too dirty!
+ dc->traffCnt->Process(rp);
+ }
+
+dc->isRunning = false;
+return NULL;
+}
+//-----------------------------------------------------------------------------
+uint16_t DIVERT_CAP::GetStartPosition() const
+{
+return 10;
+}
+//-----------------------------------------------------------------------------
+uint16_t DIVERT_CAP::GetStopPosition() const
+{
+return 10;
+}
+//-----------------------------------------------------------------------------
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
+//-----------------------------------------------------------------------------
+int DIVERT_CAP::DivertCapOpen()
+{
+memset(&pollddiv, 0, sizeof(pollddiv));
+memset(&cddiv, 0, sizeof(DIVERT_DATA));
+
+strcpy(cddiv.iface, "foo");
+cddiv.port = port;
+
+DivertCapOpen(0);
+pollddiv.events = POLLIN;
+pollddiv.fd = cddiv.sock;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int DIVERT_CAP::DivertCapOpen(int)
+{
+int ret;
+cddiv.sock = socket(PF_INET, SOCK_RAW, IPPROTO_DIVERT);
+if (cddiv.sock < 0)
+ {
+ errorStr = "Create divert socket error.";
+ printfd(__FILE__, "Cannot create divert socket\n");
+ return -1;
+ }
+
+struct sockaddr_in divAddr;
+
+memset(&divAddr, 0, sizeof(divAddr));
+
+divAddr.sin_family = AF_INET;
+divAddr.sin_port = htons(cddiv.port);
+divAddr.sin_addr.s_addr = INADDR_ANY;
+
+ret = bind(cddiv.sock, (struct sockaddr *)&divAddr, sizeof(divAddr));
+
+if (ret < 0)
+ {
+ errorStr = "Bind divert socket error.";
+ printfd(__FILE__, "Cannot bind divert socket\n");
+ return -1;
+ }
+
+return cddiv.sock;
+}
+//-----------------------------------------------------------------------------
+int DIVERT_CAP::DivertCapRead(char * b, int blen, char ** iface)
+{
+poll(&pollddiv, 1, -1);
+
+if (pollddiv.revents & POLLIN)
+ {
+ DivertCapRead(b, blen, iface, 0);
+ pollddiv.revents = 0;
+ return 0;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int DIVERT_CAP::DivertCapRead(char * b, int blen, char ** iface, int)
+{
+static char buf[BUFF_LEN];
+static struct sockaddr_in divertaddr;
+static int bytes;
+static socklen_t divertaddrSize = sizeof(divertaddr);
+
+if ((bytes = recvfrom (cddiv.sock, buf, BUFF_LEN,
+ 0, (struct sockaddr*) &divertaddr, &divertaddrSize)) > 50)
+ {
+ memcpy(b + 14, buf, blen - 14);
+ b[12] = 0x8;
+
+ if (iface)
+ *iface = cddiv.iface;
+
+ sendto(cddiv.sock, buf, bytes, 0, (struct sockaddr*)&divertaddr, divertaddrSize);
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int DIVERT_CAP::DivertCapClose()
+{
+close(cddiv.sock);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int DIVERT_CAP::ParseSettings()
+{
+int p;
+PARAM_VALUE pv;
+vector<PARAM_VALUE>::const_iterator pvi;
+
+pv.param = "Port";
+pvi = find(settings.moduleParams.begin(), settings.moduleParams.end(), pv);
+if (pvi == settings.moduleParams.end())
+ {
+ port = 15701;
+ return 0;
+ }
+
+if (ParseIntInRange(pvi->value[0], 1, 65535, &p))
+ {
+ errorStr = "Cannot parse parameter \'Port\': " + errorStr;
+ printfd(__FILE__, "Cannot parse parameter 'Port'\n");
+ return -1;
+ }
+
+port = p;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int DIVERT_CAP::ParseIntInRange(const string & str, int min, int max, int * val)
+{
+if (str2x(str.c_str(), *val))
+ {
+ errorStr = "Incorrect value \'" + str + "\'.";
+ return -1;
+ }
+if (*val < min || *val > max)
+ {
+ errorStr = "Value \'" + str + "\' out of range.";
+ return -1;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+void DIVERT_CAP::SetSettings(const MODULE_SETTINGS & s)
+{
+settings = s;
+}
+//-----------------------------------------------------------------------------
+
--- /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@stg.dp.ua>
+*/
+
+/*
+$Revision: 1.6 $
+$Date: 2009/06/23 11:32:27 $
+*/
+
+#ifndef DIVERT_CAP_H
+#define DIVERT_CAP_H
+
+#include <string>
+#include <pthread.h>
+
+#include "base_plugin.h"
+#include "base_settings.h"
+#include "../../../traffcounter.h"
+
+using namespace std;
+
+extern "C" BASE_PLUGIN * GetPlugin();
+
+//-----------------------------------------------------------------------------
+class DIVERT_CAP :public BASE_PLUGIN
+{
+public:
+ DIVERT_CAP();
+ virtual ~DIVERT_CAP(){};
+
+ void SetUsers(USERS *){};
+ void SetTariffs(TARIFFS *){};
+ void SetAdmins(ADMINS *){};
+ void SetTraffcounter(TRAFFCOUNTER * tc);
+ void SetStore(BASE_STORE *){};
+ void SetStgSettings(const SETTINGS *){};
+
+ int Start();
+ int Stop();
+ int Reload() { return 0; };
+ bool IsRunning();
+
+ void SetSettings(const MODULE_SETTINGS & s);
+ int ParseSettings();
+ const string & GetStrError() const;
+ const string GetVersion() const;
+ uint16_t GetStartPosition() const;
+ uint16_t GetStopPosition() const;
+
+private:
+ static void * Run(void *);
+
+ int DivertCapOpen();
+ int DivertCapOpen(int n);
+ int DivertCapRead(char * buffer, int blen, char ** iface);
+ int DivertCapRead(char * buffer, int blen, char ** iface, int n);
+ int DivertCapClose();
+
+ int ParseIntInRange(const string & str, int min, int max, int * val);
+
+ MODULE_SETTINGS settings;
+
+ int port;
+
+ mutable string errorStr;
+
+ pthread_t thread;
+
+ bool nonstop;
+ bool isRunning;
+
+ //int capSock;
+
+ TRAFFCOUNTER * traffCnt;
+};
+//-----------------------------------------------------------------------------
+
+
+#endif
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.7 2008/12/04 17:06:56 faust Exp $
+###############################################################################
+
+include ../../../../../Makefile.conf
+
+PROG = mod_cap_bpf.so
+
+SRCS = ./ether_cap.cpp
+
+STGLIBS = -lstg_common
+
+LIBS += $(LIB_THREAD)
+
+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
+ */
+
+/*
+Date: 18.09.2002
+*/
+
+/*
+* Author : Boris Mikhailenko <stg34@stg.dp.ua>
+*/
+
+/*
+$Revision: 1.19 $
+$Date: 2009/03/24 11:20:15 $
+$Author: faust $
+*/
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+
+#include <net/bpf.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+
+#include <string>
+#include <vector>
+
+#include "ether_cap.h"
+#include "common.h"
+#include "raw_ip_packet.h"
+
+using namespace std;
+
+//#define CAP_DEBUG 1
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+class BPF_CAP_CREATOR
+{
+private:
+ BPF_CAP * bpfc;
+
+public:
+ BPF_CAP_CREATOR()
+ : bpfc(new BPF_CAP())
+ {
+ };
+ ~BPF_CAP_CREATOR()
+ {
+ delete bpfc;
+ };
+
+ BPF_CAP * GetCapturer()
+ {
+ return bpfc;
+ };
+};
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+BPF_CAP_CREATOR bcc;
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+BASE_PLUGIN * GetPlugin()
+{
+return bcc.GetCapturer();
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+int BPF_CAP_SETTINGS::ParseSettings(const MODULE_SETTINGS & s)
+{
+//char sep[]= ", \t\n\r";
+//char *s;
+string ifaces;
+//char * str;
+//char *p;
+
+iface.erase(iface.begin(), iface.end());
+
+//PARAM_VALUE pv;
+//pv.param = "WorkDir";
+//vector<PARAM_VALUE>::const_iterator pvi;
+
+if (s.moduleParams.empty())
+ {
+ errorStr = "Parameter \'iface\' not found.";
+ printfd(__FILE__, "Parameter 'iface' not found\n");
+ return -1;
+ }
+
+for (unsigned i = 0; i < s.moduleParams.size(); i++)
+ {
+ if (s.moduleParams[i].param != "iface")
+ {
+ errorStr = "Parameter \'" + s.moduleParams[i].param + "\' unrecognized.";
+ printfd(__FILE__, "Invalid parameter: '%s'\n", s.moduleParams[i].param.c_str());
+ return -1;
+ }
+ for (unsigned j = 0; j < s.moduleParams[i].value.size(); j++)
+ {
+ iface.push_back(s.moduleParams[i].value[j]);
+ }
+ }
+
+/*if (cf.ReadString("Iface", &ifaces, "NoIface") < 0)
+ {
+ errorStr = "Cannot read parameter \'Iface\' from " + cf.GetFileName();
+ return -1;
+ }
+
+str = new char[ifaces.size() + 1];
+strcpy(str, ifaces.c_str());
+p = str;
+
+while((s = strtok(p, sep)))
+ {
+ printfd(__FILE__, "iface[] = %s\n", s);
+ p = NULL;
+ iface.push_back(s);
+ //strncpy(iface[i++], s, DEV_NAME_LEN);
+ //devNum++;
+ }
+
+delete[] str;
+if (!ifaces.size())
+ {
+ errorStr = "Error read parameter \'Iface\' from " + cf.GetFileName();
+ return -1;
+ }*/
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+string BPF_CAP_SETTINGS::GetIface(unsigned int num)
+{
+if (num >= iface.size())
+ {
+ return "";
+ }
+return iface[num];
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+const string BPF_CAP::GetVersion() const
+{
+return "bpf_cap v.1.0";
+}
+//-----------------------------------------------------------------------------
+BPF_CAP::BPF_CAP()
+{
+isRunning = false;
+nonstop = false;
+}
+//-----------------------------------------------------------------------------
+void BPF_CAP::SetSettings(const MODULE_SETTINGS & s)
+{
+settings = s;
+}
+//-----------------------------------------------------------------------------
+int BPF_CAP::ParseSettings()
+{
+int ret = capSettings.ParseSettings(settings);
+if (ret)
+ {
+ errorStr = capSettings.GetStrError();
+ return ret;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+void BPF_CAP::SetTraffcounter(TRAFFCOUNTER * tc)
+{
+traffCnt = tc;
+}
+//-----------------------------------------------------------------------------
+const string & BPF_CAP::GetStrError() const
+{
+return errorStr;
+}
+//-----------------------------------------------------------------------------
+int BPF_CAP::Start()
+{
+if (isRunning)
+ return 0;
+
+if (BPFCapOpen() < 0)
+ {
+ //errorStr = "Cannot open bpf device!";
+ return -1;
+ }
+
+nonstop = true;
+
+if (pthread_create(&thread, NULL, Run, this) == 0)
+ {
+ return 0;
+ }
+
+errorStr = "Cannot create thread.";
+printfd(__FILE__, "Cannot create thread\n");
+return -1;
+}
+//-----------------------------------------------------------------------------
+int BPF_CAP::Stop()
+{
+if (!isRunning)
+ return 0;
+
+BPFCapClose();
+
+nonstop = false;
+
+//5 seconds to thread stops itself
+int i;
+for (i = 0; i < 25; i++)
+ {
+ if (!isRunning)
+ break;
+
+ usleep(200000);
+ }
+
+//after 5 seconds waiting thread still running. now killing it
+if (isRunning)
+ {
+ //TODO pthread_cancel()
+ if (pthread_kill(thread, SIGINT))
+ {
+ errorStr = "Cannot kill thread.";
+ printfd(__FILE__, "Cannot kill thread\n");
+ return -1;
+ }
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+bool BPF_CAP::IsRunning()
+{
+return isRunning;
+}
+//-----------------------------------------------------------------------------
+void * BPF_CAP::Run(void * d)
+{
+BPF_CAP * dc = (BPF_CAP *)d;
+dc->isRunning = true;
+
+uint8_t hdr[96]; //68 + 14 + 4(size) + 9(SYS_IFACE) + 1(align to 4) = 96
+
+RAW_PACKET * rpp = (RAW_PACKET *)&hdr[14];
+memset(hdr, 0, sizeof(hdr));
+
+rpp->dataLen = -1;
+char * iface;
+
+while (dc->nonstop)
+ {
+ dc->BPFCapRead((char*)&hdr, 68 + 14, &iface);
+
+ if (!(hdr[12] == 0x8 && hdr[13] == 0x0))
+ {
+ continue;
+ }
+
+ dc->traffCnt->Process(*rpp);
+ }
+
+dc->isRunning = false;
+return NULL;
+}
+//-----------------------------------------------------------------------------
+uint16_t BPF_CAP::GetStartPosition() const
+{
+return 0;
+}
+//-----------------------------------------------------------------------------
+uint16_t BPF_CAP::GetStopPosition() const
+{
+return 0;
+}
+//-----------------------------------------------------------------------------
+int BPF_CAP::BPFCapOpen()
+{
+//for (int i = 0; i < settings->devNum; i++)
+int i = 0;
+BPF_DATA bd;
+pollfd pd;
+
+while ((bd.iface = capSettings.GetIface(i)) != "")
+ {
+ bpfData.push_back(bd);
+ if (BPFCapOpen(&bpfData[i]) < 0)
+ {
+ return -1;
+ }
+
+ pd.events = POLLIN;
+ pd.fd = bpfData[i].fd;
+ polld.push_back(pd);
+ i++;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+//int BPF_CAP::BPFCapOpen(string ifaceToOpen)
+int BPF_CAP::BPFCapOpen(BPF_DATA * bd)
+{
+char devbpf[20];
+int i = 0;
+int l = BUFF_LEN;
+int im = 1;
+struct ifreq ifr;
+
+do {
+ sprintf(devbpf, "/dev/bpf%d", i);
+ i++;
+ bd->fd = open(devbpf, O_RDONLY);
+ //cd[n].fd = open(devbpf, O_RDONLY);
+ } while(bd->fd < 0 && errno == EBUSY);
+ //while(cd[n].fd < 0 && errno == EBUSY);
+
+//if (cd[n].fd < 0)
+if (bd->fd < 0)
+ {
+ errorStr = "Can't capture packets. Open bpf device for " + bd->iface + " error.";
+ printfd(__FILE__, "Cannot open BPF device\n");
+ return -1;
+ }
+
+//strncpy(ifr.ifr_name, settings->iface[n], sizeof(ifr.ifr_name));
+strncpy(ifr.ifr_name, bd->iface.c_str(), sizeof(ifr.ifr_name));
+
+//if (ioctl(cd[n].fd, BIOCSBLEN, (caddr_t)&l) < 0)
+if (ioctl(bd->fd, BIOCSBLEN, (caddr_t)&l) < 0)
+ {
+ errorStr = bd->iface + " BIOCSBLEN " + string(strerror(errno));
+ printfd(__FILE__, "ioctl failed: '%s'\n", errorStr.c_str());
+ return -1;
+ }
+
+//if (ioctl(cd[n].fd, BIOCSETIF, (caddr_t)&ifr) < 0 )
+if (ioctl(bd->fd, BIOCSETIF, (caddr_t)&ifr) < 0)
+ {
+ errorStr = bd->iface + " BIOCSETIF " + string(strerror(errno));
+ printfd(__FILE__, "ioctl failed: '%s'\n", errorStr.c_str());
+ return -1;
+ }
+
+//if (ioctl(cd[n].fd, BIOCIMMEDIATE, &im) < 0 )
+if (ioctl(bd->fd, BIOCIMMEDIATE, &im) < 0)
+ {
+ errorStr = bd->iface + " BIOCIMMEDIATE " + string(strerror(errno));
+ printfd(__FILE__, "ioctl failed: '%s'\n", errorStr.c_str());
+ return -1;
+ }
+
+return bd->fd;
+//return 0;
+}
+//-----------------------------------------------------------------------------
+int BPF_CAP::BPFCapClose()
+{
+for (unsigned int i = 0; i < bpfData.size(); i++)
+ close(bpfData[i].fd);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int BPF_CAP::BPFCapRead(char * buffer, int blen, char ** capIface)
+{
+poll(&polld[0], polld.size(), -1);
+
+for (unsigned int i = 0; i < polld.size(); i++)
+ {
+ if (polld[i].revents & POLLIN)
+ {
+ BPFCapRead(buffer, blen, capIface, &bpfData[i]);
+ polld[i].revents = 0;
+ return 0;
+ }
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int BPF_CAP::BPFCapRead(char * buffer, int blen, char **, BPF_DATA * bd)
+{
+if (bd->canRead)
+ {
+ bd->r = read(bd->fd, bd->buffer, BUFF_LEN);
+ if (bd->r < 0)
+ {
+ //printfd(__FILE__, " error read\n");
+ usleep(20000);
+ }
+
+ bd->p = bd->buffer;
+ bd->bh = (struct bpf_hdr*)bd->p;
+ bd->canRead = 0;
+ }
+
+if(bd->r > bd->sum)
+ {
+ memcpy(buffer, (char*)(bd->p) + bd->bh->bh_hdrlen, blen);
+ //strncpy(iface, settings->iface[n], 9);
+ //*iface = settings->iface[n];
+
+ bd->sum += BPF_WORDALIGN(bd->bh->bh_hdrlen + bd->bh->bh_caplen);
+ bd->p = bd->p + BPF_WORDALIGN(bd->bh->bh_hdrlen + bd->bh->bh_caplen);
+ bd->bh = (struct bpf_hdr*)bd->p;
+ }
+
+if(bd->r <= bd->sum)
+ {
+ bd->canRead = 1;
+ bd->sum = 0;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
--- /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
+ */
+
+ /*
+ $Revision: 1.11 $
+ $Date: 2009/06/23 11:32:27 $
+ $Author: faust $
+ */
+
+/*
+* Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+*/
+
+#ifndef ETHER_CAP_H
+#define ETHER_CAP_H
+
+#include <string>
+#include <vector>
+#include <pthread.h>
+
+#ifdef FREE_BSD5
+#include <inttypes.h>
+#endif
+
+#ifdef FREE_BSD
+#include <sys/inttypes.h>
+#endif
+
+#include "base_plugin.h"
+#include "base_settings.h"
+#include "../../../traffcounter.h"
+
+using namespace std;
+
+extern "C" BASE_PLUGIN * GetPlugin();
+
+#define BUFF_LEN (128)
+
+//-----------------------------------------------------------------------------
+struct BPF_DATA
+{
+ BPF_DATA()
+ {
+ fd = 0;
+ p = NULL;
+ r = 0;
+ sum = 0;
+ memset(buffer, 0, BUFF_LEN);
+ bh = NULL;
+ canRead = 1;
+ iface = "";
+ //memset(&polld, 0, sizeof(pollfd));
+ };
+
+ BPF_DATA(const BPF_DATA & bd)
+ {
+ fd = bd.fd;
+ p = bd.p;
+ r = bd.r;
+ sum = bd.sum;
+ memcpy(buffer, bd.buffer, BUFF_LEN);
+ bh = bd.bh;
+ canRead = bd.canRead;
+ iface = bd.iface;
+ //memcpy(&polld, &bd.polld, sizeof(pollfd));
+ };
+
+int fd;
+uint8_t * p;
+int r;
+int sum;
+uint8_t buffer[BUFF_LEN];
+struct bpf_hdr * bh;
+int canRead;
+string iface;
+//pollfd polld;
+};
+//-----------------------------------------------------------------------------
+class BPF_CAP_SETTINGS
+{
+public:
+ virtual ~BPF_CAP_SETTINGS(){};
+ const string& GetStrError() const { return errorStr; }
+ int ParseSettings(const MODULE_SETTINGS & s);
+ string GetIface(unsigned int num);
+
+private:
+ vector<string> iface;
+ mutable string errorStr;
+};
+//-----------------------------------------------------------------------------
+class BPF_CAP :public BASE_PLUGIN
+{
+public:
+ BPF_CAP();
+ virtual ~BPF_CAP(){};
+
+ void SetUsers(USERS *){};
+ void SetTariffs(TARIFFS *){};
+ void SetAdmins(ADMINS *){};
+ void SetTraffcounter(TRAFFCOUNTER * tc);
+ void SetStore(BASE_STORE *){};
+ void SetStgSettings(const SETTINGS *){};
+
+ int Start();
+ int Stop();
+ int Reload() { return 0; };
+ bool IsRunning();
+
+ void SetSettings(const MODULE_SETTINGS & s);
+ int ParseSettings();
+
+ const string & GetStrError() const;
+ const string GetVersion() const;
+ uint16_t GetStartPosition() const;
+ uint16_t GetStopPosition() const;
+
+private:
+ static void * Run(void *);
+ int BPFCapOpen();
+ //int BPFCapOpen(int n);
+ int BPFCapOpen(BPF_DATA * bd);
+ int BPFCapClose();
+ int BPFCapRead(char * buffer, int blen, char ** iface);
+ int BPFCapRead(char * buffer, int blen, char ** iface, BPF_DATA * bd);
+
+ BPF_CAP_SETTINGS capSettings;
+
+ mutable string errorStr;
+
+ vector<BPF_DATA> bpfData;
+ vector<pollfd> polld;
+
+ pthread_t thread;
+ bool nonstop;
+ bool isRunning;
+ int capSock;
+ MODULE_SETTINGS settings;
+
+ TRAFFCOUNTER * traffCnt;
+};
+//-----------------------------------------------------------------------------
+
+#endif //ETHER_CAP_H
+
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.9 2008/12/04 17:07:37 faust Exp $
+###############################################################################
+
+include ../../../../../Makefile.conf
+
+PROG = mod_cap_ether.so
+
+SRCS = ./ether_cap.cpp
+
+LIBS += $(LIB_THREAD)
+STGLIBS = -lstg_common
+
+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
+ */
+
+/*
+Date: 18.09.2002
+*/
+
+/*
+* Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+*/
+
+/*
+$Revision: 1.23 $
+$Date: 2009/12/13 13:45:13 $
+*/
+
+
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <linux/if_ether.h>
+#include <linux/if_packet.h>
+#include <signal.h>
+
+#include <sys/ioctl.h>
+#include <net/if.h>
+
+#include "ether_cap.h"
+#include "common.h"
+#include "raw_ip_packet.h"
+
+//#define CAP_DEBUG 1
+
+
+//-----------------------------------------------------------------------------
+class ETHER_CAP_CREATOR
+{
+private:
+ ETHER_CAP * ec;
+
+public:
+ ETHER_CAP_CREATOR()
+ : ec(new ETHER_CAP())
+ {
+ };
+ ~ETHER_CAP_CREATOR()
+ {
+ delete ec;
+ };
+
+ ETHER_CAP * GetCapturer()
+ {
+ return ec;
+ };
+};
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+ETHER_CAP_CREATOR ecc;
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+BASE_PLUGIN * GetPlugin()
+{
+return ecc.GetCapturer();
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+const string ETHER_CAP::GetVersion() const
+{
+return "Ether_cap v.1.2";
+}
+//-----------------------------------------------------------------------------
+ETHER_CAP::ETHER_CAP()
+{
+isRunning = false;
+nonstop = false;
+}
+//-----------------------------------------------------------------------------
+void ETHER_CAP::SetTraffcounter(TRAFFCOUNTER * tc)
+{
+traffCnt = tc;
+}
+//-----------------------------------------------------------------------------
+const string & ETHER_CAP::GetStrError() const
+{
+return errorStr;
+}
+//-----------------------------------------------------------------------------
+int ETHER_CAP::Start()
+{
+if (isRunning)
+ return 0;
+
+if (EthCapOpen() < 0)
+ {
+ errorStr = "Cannot open socket!";
+ printfd(__FILE__, "Cannot open socket\n");
+ return -1;
+ }
+
+nonstop = true;
+
+if (pthread_create(&thread, NULL, Run, this) == 0)
+ {
+ return 0;
+ }
+
+errorStr = "Cannot create thread.";
+printfd(__FILE__, "Cannot create thread\n");
+return -1;
+}
+//-----------------------------------------------------------------------------
+int ETHER_CAP::Stop()
+{
+if (!isRunning)
+ return 0;
+
+nonstop = false;
+
+//5 seconds to thread stops itself
+for (int i = 0; i < 25 && isRunning; i++)
+ {
+ usleep(200000);
+ }
+//after 5 seconds waiting thread still running. now killing it
+if (isRunning)
+ {
+ if (pthread_kill(thread, SIGUSR1))
+ {
+ errorStr = "Cannot kill thread.";
+ return -1;
+ }
+ for (int i = 0; i < 25 && isRunning; ++i)
+ usleep(200000);
+ if (isRunning)
+ {
+ errorStr = "ETHER_CAP not stopped.";
+ printfd(__FILE__, "Cannot stop thread\n");
+ return -1;
+ }
+ else
+ {
+ pthread_join(thread, NULL);
+ }
+ }
+
+EthCapClose();
+return 0;
+}
+//-----------------------------------------------------------------------------
+bool ETHER_CAP::IsRunning()
+{
+return isRunning;
+}
+//-----------------------------------------------------------------------------
+void * ETHER_CAP::Run(void * d)
+{
+ETHER_CAP * dc = (ETHER_CAP *)d;
+dc->isRunning = true;
+
+struct ETH_IP
+{
+uint16_t ethHdr[8];
+RAW_PACKET rp;
+char padding[4];
+char padding1[8];
+};
+
+ETH_IP * ethIP;
+
+char ethip[sizeof(ETH_IP)];
+
+memset(ðip, 0, sizeof(ETH_IP));
+
+ethIP = (ETH_IP *)ðip;
+ethIP->rp.dataLen = -1;
+
+char * iface = NULL;
+
+while (dc->nonstop)
+ {
+ if (dc->EthCapRead(ðip, 68 + 14, &iface))
+ {
+ continue;
+ }
+
+ if (ethIP->ethHdr[7] != 0x8)
+ continue;
+
+ dc->traffCnt->Process(ethIP->rp);
+ }
+
+dc->isRunning = false;
+return NULL;
+}
+//-----------------------------------------------------------------------------
+uint16_t ETHER_CAP::GetStartPosition() const
+{
+return 10;
+}
+//-----------------------------------------------------------------------------
+uint16_t ETHER_CAP::GetStopPosition() const
+{
+return 10;
+}
+//-----------------------------------------------------------------------------
+int ETHER_CAP::EthCapOpen()
+{
+capSock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+return capSock;
+}
+//-----------------------------------------------------------------------------
+int ETHER_CAP::EthCapClose()
+{
+close(capSock);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int ETHER_CAP::EthCapRead(void * buffer, int blen, char **)
+{
+struct sockaddr_ll addr;
+int addrLen, res;
+
+if (!WaitPackets(capSock))
+ {
+ return ENODATA;
+ }
+
+addrLen = sizeof(addr);
+
+res = recvfrom(capSock, ((char*)buffer) + 2, blen, 0, (struct sockaddr *)&addr, (socklen_t*)&addrLen);
+
+if (-1 == res)
+ {
+ if (errno != EINTR)
+ {
+ printfd(__FILE__, "Error on recvfrom: '%s'\n", strerror(errno));
+ }
+ return ENODATA;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+bool ETHER_CAP::WaitPackets(int sd) const
+{
+fd_set rfds;
+FD_ZERO(&rfds);
+FD_SET(sd, &rfds);
+
+struct timeval tv;
+tv.tv_sec = 0;
+tv.tv_usec = 500000;
+
+int res = select(sd + 1, &rfds, NULL, NULL, &tv);
+if (res == -1) // Error
+ {
+ if (errno != EINTR)
+ {
+ printfd(__FILE__, "Error on select: '%s'\n", strerror(errno));
+ }
+ return false;
+ }
+
+if (res == 0) // Timeout
+ {
+ return false;
+ }
+
+return true;
+}
--- /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
+ */
+
+ /*
+ $Revision: 1.12 $
+ $Date: 2009/12/13 13:45:13 $
+ */
+
+/*
+* Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+*/
+
+#ifndef ETHER_CAP_H
+#define ETHER_CAP_H
+
+#include <string>
+#include <pthread.h>
+
+#include "base_plugin.h"
+#include "base_settings.h"
+#include "../../../traffcounter.h"
+
+using namespace std;
+
+extern "C" BASE_PLUGIN * GetPlugin();
+
+//-----------------------------------------------------------------------------
+class ETHER_CAP_SETTINGS
+{
+public:
+ const string& GetStrError() const { static string s; return s; }
+ int ParseSettings(const MODULE_SETTINGS &) { return 0; }
+};
+//-----------------------------------------------------------------------------
+class ETHER_CAP :public BASE_PLUGIN
+{
+public:
+ ETHER_CAP();
+ virtual ~ETHER_CAP(){};
+
+ void SetUsers(USERS *){};
+ void SetTariffs(TARIFFS *){};
+ void SetAdmins(ADMINS *){};
+ void SetTraffcounter(TRAFFCOUNTER * tc);
+ void SetStore(BASE_STORE *){};
+ void SetStgSettings(const SETTINGS *){};
+
+ int Start();
+ int Stop();
+ int Reload() { return 0; };
+ bool IsRunning();
+
+ void SetSettings(const MODULE_SETTINGS &){};
+ int ParseSettings(){ return 0; };
+ const string & GetStrError() const;
+ const string GetVersion() const;
+ uint16_t GetStartPosition() const;
+ uint16_t GetStopPosition() const;
+
+private:
+ static void * Run(void *);
+ int EthCapOpen();
+ int EthCapClose();
+ int EthCapRead(void * buffer, int blen, char ** iface);
+ bool WaitPackets(int sd) const;
+
+ ETHER_CAP_SETTINGS capSettings;
+
+ mutable string errorStr;
+
+ pthread_t thread;
+ bool nonstop;
+ bool isRunning;
+ int capSock;
+
+ TRAFFCOUNTER * traffCnt;
+};
+//-----------------------------------------------------------------------------
+
+#endif //ETHER_CAP_H
+
--- /dev/null
+#include <signal.h>
+#include <netinet/in.h>
+#include <linux/netfilter.h>
+
+#include "ipq_cap.h"
+#include "raw_ip_packet.h"
+#include "libipq.h"
+
+class IPQ_CAP_CREATOR
+{
+private:
+ IPQ_CAP * ic;
+
+public:
+ IPQ_CAP_CREATOR()
+ {
+ printf("constructor IPQ_CAP_CREATOR\n");
+ ic = new IPQ_CAP();
+ };
+ ~IPQ_CAP_CREATOR()
+ {
+ printf("destructor IPQ_CAP_CREATOR\n");
+ if (ic)
+ delete ic;
+ };
+
+ BASE_PLUGIN * GetCapturer()
+ {
+ return ic;
+ };
+};
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+IPQ_CAP_CREATOR icc;
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+BASE_PLUGIN * GetPlugin()
+{
+return icc.GetCapturer();
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+const string IPQ_CAP::GetVersion() const
+{
+return "ipq_cap v.1.1";
+}
+//-----------------------------------------------------------------------------
+IPQ_CAP::IPQ_CAP()
+{
+isRunning = false;
+nonstop = false;
+}
+//-----------------------------------------------------------------------------
+void IPQ_CAP::SetTraffcounter(TRAFFCOUNTER * tc)
+{
+traffCnt = tc;
+}
+//-----------------------------------------------------------------------------
+const string & IPQ_CAP::GetStrError() const
+{
+return errorStr;
+}
+//-----------------------------------------------------------------------------
+int IPQ_CAP::Start()
+{
+if (isRunning)
+ return 0;
+printfd(__FILE__, "IPQ_CAP::Start()\n");
+if (IPQCapOpen() < 0)
+ {
+ errorStr = "Cannot open socket!";
+ return -1;
+ }
+nonstop = true;
+if (pthread_create(&thread, NULL, Run, this) == 0)
+ {
+ return 0;
+ }
+errorStr = "Cannot create thread.";
+return -1;
+}
+//-----------------------------------------------------------------------------
+int IPQ_CAP::Stop()
+{
+if (!isRunning)
+ return 0;
+IPQCapClose();
+nonstop = false;
+//5 seconds to thread stops itself
+for (int i = 0; i < 25; i++)
+ {
+ if (!isRunning)
+ break;
+ usleep(200000);
+ }
+//after 5 seconds waiting thread still running. now killing it
+if (isRunning)
+ {
+ if (pthread_kill(thread, SIGINT))
+ {
+ errorStr = "Cannot kill thread.";
+ return -1;
+ }
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+bool IPQ_CAP::IsRunning()
+{
+return isRunning;
+}
+//-----------------------------------------------------------------------------
+void * IPQ_CAP::Run(void * d)
+{
+RAW_PACKET raw_packet;
+int status;
+
+sleep(2);
+IPQ_CAP * dc = (IPQ_CAP *)d;
+dc->isRunning = true;
+memset(&raw_packet, 0, sizeof(raw_packet));
+raw_packet.dataLen = -1;
+while (dc->nonstop)
+ {
+ status=dc->IPQCapRead(&raw_packet, 68);
+ if(status==-1||status==-2)
+ continue;
+ dc->traffCnt->Process(raw_packet);
+ }
+dc->isRunning = false;
+return NULL;
+}
+//-----------------------------------------------------------------------------
+uint16_t IPQ_CAP::GetStartPosition() const
+{
+return 0;
+}
+//-----------------------------------------------------------------------------
+uint16_t IPQ_CAP::GetStopPosition() const
+{
+return 0;
+}
+//-----------------------------------------------------------------------------
+int IPQ_CAP::IPQCapOpen()
+{
+int status;
+
+ipq_h = ipq_create_handle(0, PF_INET);
+if (ipq_h == NULL)
+ {
+ ipq_destroy_handle(ipq_h);
+ errorStr = "Cannot create ipq handle!";
+ return -1;
+ }
+status = ipq_set_mode(ipq_h, IPQ_COPY_PACKET, PAYLOAD_LEN);
+if (status < 0)
+ {
+ ipq_destroy_handle(ipq_h);
+ errorStr = "Cannot set IPQ_COPY_PACKET mode!";
+ return -1;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int IPQ_CAP::IPQCapClose()
+{
+ipq_destroy_handle(ipq_h);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int IPQ_CAP::IPQCapRead(void * buffer, int blen)
+{
+int status;
+static ipq_packet_msg_t *m;
+
+memset(buf, 0, BUFSIZE);
+status = ipq_read(ipq_h, buf, BUFSIZE, 0);
+if (status < 0)
+ return -1;
+if (ipq_message_type(buf) != IPQM_PACKET)
+ return -2;
+m = ipq_get_packet(buf);
+memcpy(buffer, m->payload, blen);
+ipq_set_verdict(ipq_h, m->packet_id, NF_ACCEPT, 0, NULL);
+return 0;
+}
+//-----------------------------------------------------------------------------
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.6 2008/12/04 17:08:56 faust Exp $
+###############################################################################
+
+include ../../../../../Makefile.conf
+
+PROG = mod_cap_ipq.so
+
+SRCS = ./ipq_cap.cpp \
+ ./libipq.c
+
+LIBS += $(LIB_THREAD)
+STGLIBS = -lstg_common
+
+include ../../Makefile.in
+
--- /dev/null
+#include <signal.h>
+#include <cerrno>
+#include <netinet/in.h>
+#include <linux/netfilter.h>
+
+#include "ipq_cap.h"
+#include "raw_ip_packet.h"
+
+extern "C"
+ {
+ #include "libipq.h"
+ }
+
+class IPQ_CAP_CREATOR
+{
+private:
+ IPQ_CAP * ic;
+
+public:
+ IPQ_CAP_CREATOR()
+ : ic(new IPQ_CAP())
+ {
+ };
+ ~IPQ_CAP_CREATOR()
+ {
+ delete ic;
+ };
+
+ IPQ_CAP * GetCapturer()
+ {
+ return ic;
+ };
+};
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+IPQ_CAP_CREATOR icc;
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+BASE_PLUGIN * GetPlugin()
+{
+return icc.GetCapturer();
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+const string IPQ_CAP::GetVersion() const
+{
+return "ipq_cap v.1.2";
+}
+//-----------------------------------------------------------------------------
+IPQ_CAP::IPQ_CAP()
+{
+isRunning = false;
+nonstop = false;
+}
+//-----------------------------------------------------------------------------
+void IPQ_CAP::SetTraffcounter(TRAFFCOUNTER * tc)
+{
+traffCnt = tc;
+}
+//-----------------------------------------------------------------------------
+const string & IPQ_CAP::GetStrError() const
+{
+return errorStr;
+}
+//-----------------------------------------------------------------------------
+int IPQ_CAP::Start()
+{
+if (isRunning)
+ return 0;
+if (IPQCapOpen() < 0)
+ {
+ errorStr = "Cannot open socket!";
+ printfd(__FILE__, "Cannot open socket\n");
+ return -1;
+ }
+nonstop = true;
+if (pthread_create(&thread, NULL, Run, this) == 0)
+ {
+ return 0;
+ }
+errorStr = "Cannot create thread.";
+printfd(__FILE__, "Cannot create thread\n");
+return -1;
+}
+//-----------------------------------------------------------------------------
+int IPQ_CAP::Stop()
+{
+if (!isRunning)
+ return 0;
+nonstop = false;
+//5 seconds to thread stops itself
+for (int i = 0; i < 25; i++)
+ {
+ if (!isRunning)
+ break;
+ usleep(200000);
+ }
+//after 5 seconds waiting thread still running. now killing it
+if (isRunning)
+ {
+ if (pthread_kill(thread, SIGINT))
+ {
+ errorStr = "Cannot kill thread.";
+ return -1;
+ }
+ for (int i = 0; i < 25 && isRunning; ++i)
+ {
+ usleep(200000);
+ }
+ if (isRunning)
+ {
+ printfd(__FILE__, "Thread not stopped\n");
+ }
+ else
+ {
+ pthread_join(thread, NULL);
+ }
+ }
+IPQCapClose();
+return 0;
+}
+//-----------------------------------------------------------------------------
+bool IPQ_CAP::IsRunning()
+{
+return isRunning;
+}
+//-----------------------------------------------------------------------------
+void * IPQ_CAP::Run(void * d)
+{
+RAW_PACKET raw_packet;
+int status;
+
+IPQ_CAP * dc = (IPQ_CAP *)d;
+dc->isRunning = true;
+memset(&raw_packet, 0, sizeof(raw_packet));
+raw_packet.dataLen = -1;
+while (dc->nonstop)
+ {
+ status = dc->IPQCapRead(&raw_packet, 68);
+ if (status == -1 ||
+ status == -2 ||
+ status == -3 ||
+ status == -4)
+ continue;
+ dc->traffCnt->Process(raw_packet);
+ }
+dc->isRunning = false;
+return NULL;
+}
+//-----------------------------------------------------------------------------
+uint16_t IPQ_CAP::GetStartPosition() const
+{
+return 0;
+}
+//-----------------------------------------------------------------------------
+uint16_t IPQ_CAP::GetStopPosition() const
+{
+return 0;
+}
+//-----------------------------------------------------------------------------
+int IPQ_CAP::IPQCapOpen()
+{
+int status;
+
+ipq_h = ipq_create_handle(0, PF_INET);
+if (ipq_h == NULL)
+ {
+ ipq_destroy_handle(ipq_h);
+ errorStr = "Cannot create ipq handle!";
+ return -1;
+ }
+status = ipq_set_mode(ipq_h, IPQ_COPY_PACKET, PAYLOAD_LEN);
+if (status < 0)
+ {
+ ipq_destroy_handle(ipq_h);
+ errorStr = "Cannot set IPQ_COPY_PACKET mode!";
+ return -1;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int IPQ_CAP::IPQCapClose()
+{
+ipq_destroy_handle(ipq_h);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int IPQ_CAP::IPQCapRead(void * buffer, int blen)
+{
+int status;
+static ipq_packet_msg_t *m;
+
+memset(buf, 0, BUFSIZE);
+status = ipq_read(ipq_h, buf, BUFSIZE, 1);
+if (status == 0)
+ return -4;
+if (errno == EINTR)
+ return -3;
+if (status < 0)
+ return -1;
+if (ipq_message_type(buf) != IPQM_PACKET)
+ return -2;
+m = ipq_get_packet(buf);
+memcpy(buffer, m->payload, blen);
+ipq_set_verdict(ipq_h, m->packet_id, NF_ACCEPT, 0, NULL);
+return 0;
+}
+//-----------------------------------------------------------------------------
--- /dev/null
+#include <string>
+
+#include "base_plugin.h"
+#include "base_settings.h"
+#include "../../../traffcounter.h"
+
+#define BUFSIZE (256)
+#define PAYLOAD_LEN (96)
+
+using namespace std;
+
+extern "C" BASE_PLUGIN * GetPlugin();
+
+//-----------------------------------------------------------------------------
+class IPQ_CAP :public BASE_PLUGIN
+{
+public:
+ IPQ_CAP();
+ virtual ~IPQ_CAP(){};
+
+ void SetUsers(USERS *){};
+ void SetTariffs(TARIFFS *){};
+ void SetAdmins(ADMINS *){};
+ void SetTraffcounter(TRAFFCOUNTER * tc);
+ void SetStore(BASE_STORE *){};
+ void SetStgSettings(const SETTINGS *){};
+
+ int Start();
+ int Stop();
+ int Reload() { return 0; };
+ bool IsRunning();
+
+ void SetSettings(const MODULE_SETTINGS &){};
+ int ParseSettings(){ return 0; };
+ const string & GetStrError() const;
+ const string GetVersion() const;
+ uint16_t GetStartPosition() const;
+ uint16_t GetStopPosition() const;
+
+private:
+ static void * Run(void *);
+ int IPQCapOpen();
+ int IPQCapClose();
+ int IPQCapRead(void * buffer, int blen);
+
+ struct ipq_handle *ipq_h;
+ mutable string errorStr;
+
+ pthread_t thread;
+ bool nonstop;
+ bool isRunning;
+ int capSock;
+
+ TRAFFCOUNTER * traffCnt;
+ unsigned char buf[BUFSIZE];
+};
--- /dev/null
+/*
+ * libipq.c
+ *
+ * IPQ userspace library.
+ *
+ * Please note that this library is still developmental, and there may
+ * be some API changes.
+ *
+ * Author: James Morris <jmorris@intercode.com.au>
+ *
+ * 07-11-2001 Modified by Fernando Anton to add support for IPv6.
+ *
+ * Copyright (c) 2000-2001 Netfilter Core Team
+ *
+ * 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.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+#include "libipq.h"
+
+/****************************************************************************
+ *
+ * Private interface
+ *
+ ****************************************************************************/
+
+enum
+ {
+ IPQ_ERR_NONE = 0,
+ IPQ_ERR_IMPL,
+ IPQ_ERR_HANDLE,
+ IPQ_ERR_SOCKET,
+ IPQ_ERR_BIND,
+ IPQ_ERR_BUFFER,
+ IPQ_ERR_RECV,
+ IPQ_ERR_NLEOF,
+ IPQ_ERR_ADDRLEN,
+ IPQ_ERR_STRUNC,
+ IPQ_ERR_RTRUNC,
+ IPQ_ERR_NLRECV,
+ IPQ_ERR_SEND,
+ IPQ_ERR_SUPP,
+ IPQ_ERR_RECVBUF,
+ IPQ_ERR_TIMEOUT,
+ IPQ_ERR_PROTOCOL
+ };
+#define IPQ_MAXERR IPQ_ERR_PROTOCOL
+
+/*struct ipq_errmap_t
+ {
+ int errcode;
+ char *message;
+ } ipq_errmap[] = {
+ { IPQ_ERR_NONE, "Unknown error"},
+ { IPQ_ERR_IMPL, "Implementation error"},
+ { IPQ_ERR_HANDLE, "Unable to create netlink handle"},
+ { IPQ_ERR_SOCKET, "Unable to create netlink socket"},
+ { IPQ_ERR_BIND, "Unable to bind netlink socket"},
+ { IPQ_ERR_BUFFER, "Unable to allocate buffer"},
+ { IPQ_ERR_RECV, "Failed to receive netlink message"},
+ { IPQ_ERR_NLEOF, "Received EOF on netlink socket"},
+ { IPQ_ERR_ADDRLEN, "Invalid peer address length"},
+ { IPQ_ERR_STRUNC, "Sent message truncated"},
+ { IPQ_ERR_RTRUNC, "Received message truncated"},
+ { IPQ_ERR_NLRECV, "Received error from netlink"},
+ { IPQ_ERR_SEND, "Failed to send netlink message"},
+ { IPQ_ERR_SUPP, "Operation not supported"},
+ { IPQ_ERR_RECVBUF, "Receive buffer size invalid"},
+ { IPQ_ERR_TIMEOUT, "Timeout"},
+ { IPQ_ERR_PROTOCOL, "Invalid protocol specified"}
+};*/
+
+static int ipq_errno = IPQ_ERR_NONE;
+
+static ssize_t ipq_netlink_sendto(const struct ipq_handle *h,
+ const void *msg, size_t len);
+
+static ssize_t ipq_netlink_recvfrom(const struct ipq_handle *h,
+ unsigned char *buf, size_t len,
+ int timeout);
+
+static ssize_t ipq_netlink_sendmsg(const struct ipq_handle *h,
+ const struct msghdr *msg,
+ unsigned int flags);
+
+//static char *ipq_strerror(int errcode);
+//-----------------------------------------------------------------------------
+static ssize_t ipq_netlink_sendto(const struct ipq_handle *h,
+ const void *msg, size_t len)
+{
+ int status = sendto(h->fd, msg, len, 0,
+ (struct sockaddr *)&h->peer, sizeof(h->peer));
+ if (status < 0)
+ ipq_errno = IPQ_ERR_SEND;
+ return status;
+}
+//-----------------------------------------------------------------------------
+static ssize_t ipq_netlink_sendmsg(const struct ipq_handle *h,
+ const struct msghdr *msg,
+ unsigned int flags)
+{
+ int status = sendmsg(h->fd, msg, flags);
+ if (status < 0)
+ ipq_errno = IPQ_ERR_SEND;
+ return status;
+}
+//-----------------------------------------------------------------------------
+static ssize_t ipq_netlink_recvfrom(const struct ipq_handle *h,
+ unsigned char *buf, size_t len,
+ int timeout)
+{
+ socklen_t addrlen;
+ int status;
+ struct nlmsghdr *nlh;
+
+ if (len < sizeof(struct nlmsgerr))
+ {
+ ipq_errno = IPQ_ERR_RECVBUF;
+ return -1;
+ }
+ addrlen = sizeof(h->peer);
+
+ if (timeout != 0)
+ {
+ int ret;
+ struct timeval tv;
+ fd_set read_fds;
+
+ if (timeout < 0)
+ {
+ /* non-block non-timeout */
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ }
+ else
+ {
+ tv.tv_sec = timeout / 1000000;
+ tv.tv_usec = timeout % 1000000;
+ }
+
+ FD_ZERO(&read_fds);
+ FD_SET(h->fd, &read_fds);
+ ret = select(h->fd+1, &read_fds, NULL, NULL, &tv);
+ if (ret < 0)
+ {
+ if (errno == EINTR)
+ {
+ return 0;
+ }
+ else
+ {
+ ipq_errno = IPQ_ERR_RECV;
+ return -1;
+ }
+ }
+ if (!FD_ISSET(h->fd, &read_fds))
+ {
+ ipq_errno = IPQ_ERR_TIMEOUT;
+ return 0;
+ }
+ }
+ status = recvfrom(h->fd, buf, len, 0,
+ (struct sockaddr *)&h->peer, &addrlen);
+ if (status < 0)
+ {
+ ipq_errno = IPQ_ERR_RECV;
+ return status;
+ }
+ if (addrlen != sizeof(h->peer))
+ {
+ ipq_errno = IPQ_ERR_RECV;
+ return -1;
+ }
+ if (h->peer.nl_pid != 0)
+ {
+ ipq_errno = IPQ_ERR_RECV;
+ return -1;
+ }
+ if (status == 0)
+ {
+ ipq_errno = IPQ_ERR_NLEOF;
+ return -1;
+ }
+ nlh = (struct nlmsghdr *)buf;
+ if (nlh->nlmsg_flags & MSG_TRUNC || (int)nlh->nlmsg_len > status)
+ {
+ ipq_errno = IPQ_ERR_RTRUNC;
+ return -1;
+ }
+ return status;
+}
+//-----------------------------------------------------------------------------
+/*static char *ipq_strerror(int errcode)
+{
+ if (errcode < 0 || errcode > IPQ_MAXERR)
+ errcode = IPQ_ERR_IMPL;
+ return ipq_errmap[errcode].message;
+}*/
+
+/****************************************************************************
+ *
+ * Public interface
+ *
+ ****************************************************************************/
+
+/*
+ * Create and initialise an ipq handle.
+ */
+struct ipq_handle *ipq_create_handle(u_int32_t __attribute__((unused)) flags, u_int32_t protocol)
+ {
+ int status;
+ struct ipq_handle *h;
+
+ h = (struct ipq_handle *)malloc(sizeof(struct ipq_handle));
+ if (h == NULL)
+ {
+ ipq_errno = IPQ_ERR_HANDLE;
+ return NULL;
+ }
+
+ memset(h, 0, sizeof(struct ipq_handle));
+
+ if (protocol == PF_INET)
+ h->fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_FIREWALL);
+ else if (protocol == PF_INET6)
+ h->fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_IP6_FW);
+ else
+ {
+ ipq_errno = IPQ_ERR_PROTOCOL;
+ free(h);
+ return NULL;
+ }
+
+ if (h->fd == -1)
+ {
+ ipq_errno = IPQ_ERR_SOCKET;
+ close(h->fd);
+ free(h);
+ return NULL;
+ }
+ memset(&h->local, 0, sizeof(struct sockaddr_nl));
+ h->local.nl_family = AF_NETLINK;
+ h->local.nl_pid = getpid();
+ h->local.nl_groups = 0;
+ status = bind(h->fd, (struct sockaddr *)&h->local, sizeof(h->local));
+ if (status == -1)
+ {
+ ipq_errno = IPQ_ERR_BIND;
+ close(h->fd);
+ free(h);
+ return NULL;
+ }
+ memset(&h->peer, 0, sizeof(struct sockaddr_nl));
+ h->peer.nl_family = AF_NETLINK;
+ h->peer.nl_pid = 0;
+ h->peer.nl_groups = 0;
+ return h;
+ }
+//-----------------------------------------------------------------------------
+/*
+ * No error condition is checked here at this stage, but it may happen
+ * if/when reliable messaging is implemented.
+ */
+int ipq_destroy_handle(struct ipq_handle *h)
+{
+ if (h)
+ {
+ close(h->fd);
+ free(h);
+ }
+ return 0;
+}
+//-----------------------------------------------------------------------------
+int ipq_set_mode(const struct ipq_handle *h,
+ u_int8_t mode, size_t range)
+{
+ #define FAKE_ARRAY_SIZE 16
+ struct
+ {
+ struct nlmsghdr nlh;
+ ipq_peer_msg_t pm;
+ char s[FAKE_ARRAY_SIZE];
+ } req;
+
+ memset(&req, 0, sizeof(req));
+ req.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(req)-FAKE_ARRAY_SIZE);
+ req.nlh.nlmsg_flags = NLM_F_REQUEST;
+ req.nlh.nlmsg_type = IPQM_MODE;
+ req.nlh.nlmsg_pid = h->local.nl_pid;
+ req.pm.msg.mode.value = mode;
+ req.pm.msg.mode.range = range;
+ return ipq_netlink_sendto(h, (void *)&req, req.nlh.nlmsg_len);
+ //return ipq_netlink_sendto(h, (void *)&req, sizeof(req));
+}
+//-----------------------------------------------------------------------------
+/*
+ * timeout is in microseconds (1 second is 1000000 (1 million) microseconds)
+ *
+ */
+ssize_t ipq_read(const struct ipq_handle *h,
+ unsigned char *buf, size_t len, int timeout)
+{
+ return ipq_netlink_recvfrom(h, buf, len, timeout);
+}
+//-----------------------------------------------------------------------------
+int ipq_message_type(const unsigned char *buf)
+{
+ return((struct nlmsghdr*)buf)->nlmsg_type;
+}
+//-----------------------------------------------------------------------------
+int ipq_get_msgerr(const unsigned char *buf)
+{
+ struct nlmsghdr *h = (struct nlmsghdr *)buf;
+ struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h);
+ return -err->error;
+}
+//-----------------------------------------------------------------------------
+ipq_packet_msg_t *ipq_get_packet(const unsigned char *buf)
+{
+ return(ipq_packet_msg_t *)(NLMSG_DATA((struct nlmsghdr *)(buf)));
+}
+//-----------------------------------------------------------------------------
+int ipq_set_verdict(const struct ipq_handle *h,
+ ipq_id_t id,
+ unsigned int verdict,
+ size_t data_len,
+ unsigned char *buf)
+{
+ unsigned char nvecs;
+ size_t tlen;
+ struct nlmsghdr nlh;
+ ipq_peer_msg_t pm;
+ struct iovec iov[3];
+ struct msghdr msg;
+
+ memset(&nlh, 0, sizeof(nlh));
+ nlh.nlmsg_flags = NLM_F_REQUEST;
+ nlh.nlmsg_type = IPQM_VERDICT;
+ nlh.nlmsg_pid = h->local.nl_pid;
+ memset(&pm, 0, sizeof(pm));
+ pm.msg.verdict.value = verdict;
+ pm.msg.verdict.id = id;
+ pm.msg.verdict.data_len = data_len;
+ iov[0].iov_base = &nlh;
+ iov[0].iov_len = sizeof(nlh);
+ iov[1].iov_base = ±
+ iov[1].iov_len = sizeof(pm);
+ tlen = sizeof(nlh) + sizeof(pm);
+ nvecs = 2;
+ if (data_len && buf)
+ {
+ iov[2].iov_base = buf;
+ iov[2].iov_len = data_len;
+ tlen += data_len;
+ nvecs++;
+ }
+ msg.msg_name = (void *)&h->peer;
+ msg.msg_namelen = sizeof(h->peer);
+ msg.msg_iov = iov;
+ msg.msg_iovlen = nvecs;
+ msg.msg_control = NULL;
+ msg.msg_controllen = 0;
+ msg.msg_flags = 0;
+ nlh.nlmsg_len = tlen;
+ return ipq_netlink_sendmsg(h, &msg, 0);
+}
+//-----------------------------------------------------------------------------
+/* Not implemented yet */
+int ipq_ctl(const struct ipq_handle __attribute__((unused)) * handle, int __attribute__((unused)) request, ...)
+{
+ return 1;
+}
+//-----------------------------------------------------------------------------
+/*char *ipq_errstr(void)
+{
+ return ipq_strerror(ipq_errno);
+}*/
+//-----------------------------------------------------------------------------
+/*void ipq_perror(const char *s)
+{
+ if (s)
+ fputs(s, stderr);
+ else
+ fputs("ERROR", stderr);
+ if (ipq_errno)
+ fprintf(stderr, ": %s", ipq_errstr());
+ if (errno)
+ fprintf(stderr, ": %s", strerror(errno));
+ fputc('\n', stderr);
+}*/
+//-----------------------------------------------------------------------------
+
+
--- /dev/null
+/*
+ * libipq.h
+ *
+ * IPQ library for userspace.
+ *
+ * Author: James Morris <jmorris@intercode.com.au>
+ *
+ * Copyright (c) 2000-2001 Netfilter Core Team
+ *
+ * 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.
+ *
+ */
+
+#ifndef _LIBIPQ_H
+#define _LIBIPQ_H
+
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <asm/types.h>
+#include <linux/netlink.h>
+
+#ifdef KERNEL_64_USERSPACE_32
+#include "ip_queue_64.h"
+typedef u_int64_t ipq_id_t;
+#else
+#include <linux/netfilter_ipv4/ip_queue.h>
+typedef unsigned long ipq_id_t;
+#endif
+
+#ifdef DEBUG_LIBIPQ
+#include <stdio.h>
+#define LDEBUG(x...) fprintf(stderr, ## x)
+#else
+#define LDEBUG(x...)
+#endif /* DEBUG_LIBIPQ */
+
+/* FIXME: glibc sucks */
+#ifndef MSG_TRUNC
+#define MSG_TRUNC 0x20
+#endif
+
+struct ipq_handle
+{
+ int fd;
+ u_int8_t blocking;
+ struct sockaddr_nl local;
+ struct sockaddr_nl peer;
+};
+
+struct ipq_handle *ipq_create_handle(u_int32_t flags, u_int32_t protocol);
+
+int ipq_destroy_handle(struct ipq_handle *h);
+
+ssize_t ipq_read(const struct ipq_handle *h,
+ unsigned char *buf, size_t len, int timeout);
+
+int ipq_set_mode(const struct ipq_handle *h, u_int8_t mode, size_t len);
+
+ipq_packet_msg_t *ipq_get_packet(const unsigned char *buf);
+
+int ipq_message_type(const unsigned char *buf);
+
+int ipq_get_msgerr(const unsigned char *buf);
+
+int ipq_set_verdict(const struct ipq_handle *h,
+ ipq_id_t id,
+ unsigned int verdict,
+ size_t data_len,
+ unsigned char *buf);
+
+int ipq_ctl(const struct ipq_handle *h, int request, ...);
+
+/*char *ipq_errstr(void);
+void ipq_perror(const char *s);*/
+
+#endif /* _LIBIPQ_H */
+
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.10 2009/08/03 10:25:40 faust Exp $
+###############################################################################
+
+include ../../../../../Makefile.conf
+
+PROG = mod_conf_rpc.so
+
+SRCS = ./rpcconfig.cpp \
+ ./user_helper.cpp \
+ ./tariff_helper.cpp \
+ ./info_methods.cpp \
+ ./users_methods.cpp \
+ ./tariffs_methods.cpp \
+ ./admins_methods.cpp \
+ ./messages_methods.cpp
+
+XMLRPC_C_LIBS = $(shell xmlrpc-c-config c++2 abyss-server --libs)
+
+LIBS += $(XMLRPC_C_LIBS) \
+ $(LIB_THREAD)
+
+ifneq ($(OS),linux)
+LIBS += -liconv
+endif
+
+STGLIBS = -lstg_common -lstg_logger
+
+include ../../Makefile.in
+
--- /dev/null
+#include "admins_methods.h"
+
+#include "rpcconfig.h"
+
+//------------------------------------------------------------------------------
+
+void METHOD_ADMIN_GET::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string login = paramList.getString(1);
+paramList.verifyEnd(2);
+
+std::map<std::string, xmlrpc_c::value> structVal;
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ structVal["result"] = xmlrpc_c::value_boolean(false);
+ *retvalPtr = xmlrpc_c::value_struct(structVal);
+ return;
+ }
+
+ADMIN admin;
+
+if (admins->FindAdmin(login, &admin))
+ {
+ structVal["result"] = xmlrpc_c::value_boolean(false);
+ *retvalPtr = xmlrpc_c::value_struct(structVal);
+ return;
+ }
+
+structVal["result"] = xmlrpc_c::value_boolean(true);
+structVal["login"] = xmlrpc_c::value_string(admin.GetLogin());
+structVal["password"] = xmlrpc_c::value_string(admin.GetPassword());
+
+const PRIV * priv = admin.GetPriv();
+
+structVal["user_stat"] = xmlrpc_c::value_boolean(priv->userStat);
+structVal["user_conf"] = xmlrpc_c::value_boolean(priv->userConf);
+structVal["user_cash"] = xmlrpc_c::value_boolean(priv->userCash);
+structVal["user_passwd"] = xmlrpc_c::value_boolean(priv->userPasswd);
+structVal["user_add_del"] = xmlrpc_c::value_boolean(priv->userAddDel);
+structVal["admin_chg"] = xmlrpc_c::value_boolean(priv->adminChg);
+structVal["tariff_chg"] = xmlrpc_c::value_boolean(priv->tariffChg);
+
+*retvalPtr = xmlrpc_c::value_struct(structVal);
+}
+
+//------------------------------------------------------------------------------
+
+void METHOD_ADMIN_ADD::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string login = paramList.getString(1);
+paramList.verifyEnd(2);
+
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ printfd(__FILE__, "METHOD_ADMIN_ADD::execute(): 'Not logged or cookie timeout'\n");
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+ADMIN admin;
+
+if (admins->FindAdmin(adminInfo.admin, &admin))
+ {
+ printfd(__FILE__, "METHOD_ADMIN_ADD::execute(): 'Invalid admin (logged)'\n");
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+if (admins->Add(login, admin))
+ {
+ printfd(__FILE__, "METHOD_ADMIN_ADD::execute(): 'Failed to add admin'\n");
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+*retvalPtr = xmlrpc_c::value_boolean(true);
+}
+
+//------------------------------------------------------------------------------
+
+void METHOD_ADMIN_DEL::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string login = paramList.getString(1);
+paramList.verifyEnd(2);
+
+std::map<std::string, xmlrpc_c::value> structVal;
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+ADMIN admin;
+
+if (admins->FindAdmin(adminInfo.admin, &admin))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+if (admins->Del(login, admin))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+*retvalPtr = xmlrpc_c::value_boolean(true);
+}
+
+//------------------------------------------------------------------------------
+
+void METHOD_ADMIN_CHG::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string login = paramList.getString(1);
+xmlrpc_c::value_struct info(paramList.getStruct(2));
+paramList.verifyEnd(3);
+
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+ADMIN loggedAdmin;
+
+if (admins->FindAdmin(adminInfo.admin, &loggedAdmin))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+ADMIN admin;
+
+if (admins->FindAdmin(login, &admin))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+ADMIN_CONF conf;
+
+conf.priv = *admin.GetPriv();
+conf.password = admin.GetPassword();
+conf.login = login;
+
+std::map<std::string, xmlrpc_c::value> structVal(
+ static_cast<std::map<std::string, xmlrpc_c::value> >(xmlrpc_c::value_struct(info))
+ );
+
+std::map<std::string, xmlrpc_c::value>::iterator it;
+
+if ((it = structVal.find("password")) != structVal.end())
+ {
+ conf.password = xmlrpc_c::value_string(it->second);
+ }
+
+if ((it = structVal.find("user_stat")) != structVal.end())
+ {
+ conf.priv.userStat = xmlrpc_c::value_boolean(it->second);
+ }
+
+if ((it = structVal.find("user_conf")) != structVal.end())
+ {
+ conf.priv.userConf = xmlrpc_c::value_boolean(it->second);
+ }
+
+if ((it = structVal.find("user_cash")) != structVal.end())
+ {
+ conf.priv.userCash = xmlrpc_c::value_boolean(it->second);
+ }
+
+if ((it = structVal.find("user_passwd")) != structVal.end())
+ {
+ conf.priv.userPasswd = xmlrpc_c::value_boolean(it->second);
+ }
+
+if ((it = structVal.find("user_add_del")) != structVal.end())
+ {
+ conf.priv.userAddDel = xmlrpc_c::value_boolean(it->second);
+ }
+
+if ((it = structVal.find("admin_chg")) != structVal.end())
+ {
+ conf.priv.adminChg = xmlrpc_c::value_boolean(it->second);
+ }
+
+if ((it = structVal.find("tariff_chg")) != structVal.end())
+ {
+ conf.priv.tariffChg = xmlrpc_c::value_boolean(it->second);
+ }
+
+if (admins->Change(conf, loggedAdmin))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ }
+
+*retvalPtr = xmlrpc_c::value_boolean(true);
+}
+
+//------------------------------------------------------------------------------
+
+void METHOD_ADMINS_GET::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+paramList.verifyEnd(1);
+
+std::map<std::string, xmlrpc_c::value> structVal;
+std::vector<xmlrpc_c::value> retval;
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ structVal["result"] = xmlrpc_c::value_boolean(false);
+ *retvalPtr = xmlrpc_c::value_struct(structVal);
+ return;
+ }
+
+ADMIN_CONF ac;
+int h = admins->OpenSearch();
+
+while (admins->SearchNext(h, &ac) == 0)
+ {
+ std::map<std::string, xmlrpc_c::value> structVal;
+ structVal["result"] = xmlrpc_c::value_boolean(true);
+ structVal["login"] = xmlrpc_c::value_string(ac.login);
+ structVal["password"] = xmlrpc_c::value_string(ac.password);
+ structVal["user_stat"] = xmlrpc_c::value_boolean(ac.priv.userStat);
+ structVal["user_conf"] = xmlrpc_c::value_boolean(ac.priv.userConf);
+ structVal["user_cash"] = xmlrpc_c::value_boolean(ac.priv.userCash);
+ structVal["user_passwd"] = xmlrpc_c::value_boolean(ac.priv.userPasswd);
+ structVal["user_add_del"] = xmlrpc_c::value_boolean(ac.priv.userAddDel);
+ structVal["admin_chg"] = xmlrpc_c::value_boolean(ac.priv.adminChg);
+ structVal["tariff_chg"] = xmlrpc_c::value_boolean(ac.priv.tariffChg);
+
+ retval.push_back(xmlrpc_c::value_struct(structVal));
+ }
+
+*retvalPtr = xmlrpc_c::value_array(retval);
+}
--- /dev/null
+#ifndef __ADMINS_METHODS_H__
+#define __ADMINS_METHODS_H__
+
+#include <xmlrpc-c/base.hpp>
+#include <xmlrpc-c/registry.hpp>
+
+#include "../../../admins.h"
+#include "../../../admin.h"
+
+class RPC_CONFIG;
+
+class METHOD_ADMIN_GET : public xmlrpc_c::method {
+public:
+ METHOD_ADMIN_GET(RPC_CONFIG * c,
+ ADMINS * a)
+ : config(c),
+ admins(a)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr);
+private:
+ RPC_CONFIG * config;
+ ADMINS * admins;
+};
+
+class METHOD_ADMIN_ADD : public xmlrpc_c::method {
+public:
+ METHOD_ADMIN_ADD(RPC_CONFIG * c,
+ ADMINS * a)
+ : config(c),
+ admins(a)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr);
+private:
+ RPC_CONFIG * config;
+ ADMINS * admins;
+};
+
+class METHOD_ADMIN_DEL : public xmlrpc_c::method {
+public:
+ METHOD_ADMIN_DEL(RPC_CONFIG * c,
+ ADMINS * a)
+ : config(c),
+ admins(a)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr);
+private:
+ RPC_CONFIG * config;
+ ADMINS * admins;
+};
+
+class METHOD_ADMIN_CHG : public xmlrpc_c::method {
+public:
+ METHOD_ADMIN_CHG(RPC_CONFIG * c,
+ ADMINS * a)
+ : config(c),
+ admins(a)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr);
+private:
+ RPC_CONFIG * config;
+ ADMINS * admins;
+};
+
+class METHOD_ADMINS_GET : public xmlrpc_c::method {
+public:
+ METHOD_ADMINS_GET(RPC_CONFIG * c,
+ ADMINS * a)
+ : config(c),
+ admins(a)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr);
+private:
+ RPC_CONFIG * config;
+ ADMINS * admins;
+};
+
+#endif
--- /dev/null
+rpcconfig.o: rpcconfig.cpp rpcconfig.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_plugin.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_settings.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/noncopyable.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_store.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_stat.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/resetable.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_traff.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_const.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_locker.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_ips.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/common.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/corp_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/service_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/admin_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/admin_conf.inc.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/tariff_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_message.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_settings.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/admin_conf.h \
+ ../../../admin.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_logger.h \
+ ../../../admins.h ../../../admin.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_locker.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/noncopyable.h \
+ ../../../users.h ../../../settings.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/dotconfpp.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/mempool.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/common.h \
+ ../../../user.h ../../../tariff.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/tariff_conf.h \
+ ../../../curr_ip.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_const.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_stat.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_ips.h \
+ ../../../user_property.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/notifer.h \
+ ../../../script_executer.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_auth.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_plugin.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_message.h \
+ ../../../tariffs.h ../../../actions.h ../../../actions.inl.h \
+ ../../../eventloop.h ../../../tariffs.h ../../../traffcounter.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/raw_ip_packet.h \
+ ../../../users.h ../../../settings.h info_methods.h users_methods.h \
+ ../../../user.h tariffs_methods.h admins_methods.h messages_methods.h Makefile ../../../../../Makefile.conf
+ $(CC) -c $< -g3 -W -Wall -I/usr/local/include -DARCH_LE -fPIC -I /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include -DDEBUG -DLINUX
+user_helper.o: user_helper.cpp user_helper.h ../../../users.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ ../../../settings.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/dotconfpp.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/mempool.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/common.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_const.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_settings.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_logger.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/noncopyable.h \
+ ../../../user.h ../../../tariff.h ../../../admin.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/admin_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/admin_conf.inc.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/tariff_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/resetable.h \
+ ../../../curr_ip.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_const.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_stat.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_traff.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_locker.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_ips.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/common.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_ips.h \
+ ../../../user_property.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_store.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_stat.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/corp_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/service_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/admin_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/tariff_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_settings.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_message.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/notifer.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_locker.h \
+ ../../../script_executer.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_auth.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_plugin.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_message.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/noncopyable.h \
+ ../../../tariffs.h ../../../actions.h ../../../actions.inl.h \
+ ../../../eventloop.h ../../../admin.h utils.h Makefile ../../../../../Makefile.conf
+ $(CC) -c $< -g3 -W -Wall -I/usr/local/include -DARCH_LE -fPIC -I /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include -DDEBUG -DLINUX
+tariff_helper.o: tariff_helper.cpp tariff_helper.h ../../../tariff.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/common.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_const.h \
+ ../../../admin.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/admin_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/admin_conf.inc.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_logger.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/noncopyable.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/tariff_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/resetable.h Makefile ../../../../../Makefile.conf
+ $(CC) -c $< -g3 -W -Wall -I/usr/local/include -DARCH_LE -fPIC -I /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include -DDEBUG -DLINUX
+info_methods.o: info_methods.cpp info_methods.h ../../../users.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ ../../../settings.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/dotconfpp.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/mempool.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/common.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_const.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_settings.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_logger.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/noncopyable.h \
+ ../../../user.h ../../../tariff.h ../../../admin.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/admin_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/admin_conf.inc.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/tariff_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/resetable.h \
+ ../../../curr_ip.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_const.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_stat.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_traff.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_locker.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_ips.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/common.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_ips.h \
+ ../../../user_property.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_store.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_stat.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/corp_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/service_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/admin_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/tariff_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_settings.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_message.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/notifer.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_locker.h \
+ ../../../script_executer.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_auth.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_plugin.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_message.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/noncopyable.h \
+ ../../../tariffs.h ../../../actions.h ../../../actions.inl.h \
+ ../../../eventloop.h ../../../tariffs.h ../../../settings.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/version.h \
+ rpcconfig.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_plugin.h \
+ ../../../admin.h ../../../admins.h ../../../traffcounter.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/raw_ip_packet.h \
+ ../../../users.h Makefile ../../../../../Makefile.conf
+ $(CC) -c $< -g3 -W -Wall -I/usr/local/include -DARCH_LE -fPIC -I /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include -DDEBUG -DLINUX
+users_methods.o: users_methods.cpp users_methods.h ../../../users.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ ../../../settings.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/dotconfpp.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/mempool.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/common.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_const.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_settings.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_logger.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/noncopyable.h \
+ ../../../user.h ../../../tariff.h ../../../admin.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/admin_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/admin_conf.inc.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/tariff_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/resetable.h \
+ ../../../curr_ip.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_const.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_stat.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_traff.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_locker.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_ips.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/common.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_ips.h \
+ ../../../user_property.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_store.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_stat.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/corp_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/service_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/admin_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/tariff_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_settings.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_message.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/notifer.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_locker.h \
+ ../../../script_executer.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_auth.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_plugin.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_message.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/noncopyable.h \
+ ../../../tariffs.h ../../../actions.h ../../../actions.inl.h \
+ ../../../eventloop.h ../../../user.h rpcconfig.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_plugin.h \
+ ../../../admin.h ../../../admins.h ../../../tariffs.h \
+ ../../../traffcounter.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/raw_ip_packet.h \
+ ../../../users.h ../../../settings.h user_helper.h utils.h Makefile ../../../../../Makefile.conf
+ $(CC) -c $< -g3 -W -Wall -I/usr/local/include -DARCH_LE -fPIC -I /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include -DDEBUG -DLINUX
+tariffs_methods.o: tariffs_methods.cpp rpcconfig.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_plugin.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_settings.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/noncopyable.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_store.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_stat.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/resetable.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_traff.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_const.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_locker.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_ips.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/common.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/corp_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/service_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/admin_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/admin_conf.inc.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/tariff_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_message.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_settings.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/admin_conf.h \
+ ../../../admin.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_logger.h \
+ ../../../admins.h ../../../admin.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_locker.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/noncopyable.h \
+ ../../../users.h ../../../settings.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/dotconfpp.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/mempool.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/common.h \
+ ../../../user.h ../../../tariff.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/tariff_conf.h \
+ ../../../curr_ip.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_const.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_stat.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_ips.h \
+ ../../../user_property.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/notifer.h \
+ ../../../script_executer.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_auth.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_plugin.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_message.h \
+ ../../../tariffs.h ../../../actions.h ../../../actions.inl.h \
+ ../../../eventloop.h ../../../tariffs.h ../../../traffcounter.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/raw_ip_packet.h \
+ ../../../users.h ../../../settings.h tariffs_methods.h tariff_helper.h \
+ ../../../tariff.h Makefile ../../../../../Makefile.conf
+ $(CC) -c $< -g3 -W -Wall -I/usr/local/include -DARCH_LE -fPIC -I /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include -DDEBUG -DLINUX
+admins_methods.o: admins_methods.cpp admins_methods.h ../../../admins.h \
+ ../../../admin.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/admin_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/admin_conf.inc.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_logger.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/noncopyable.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_locker.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_store.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_stat.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/resetable.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_traff.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_const.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_locker.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_ips.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/common.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/corp_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/service_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/admin_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/tariff_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_settings.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_message.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/noncopyable.h \
+ ../../../admin.h rpcconfig.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_plugin.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_settings.h \
+ ../../../users.h ../../../settings.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/dotconfpp.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/mempool.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/common.h \
+ ../../../user.h ../../../tariff.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/tariff_conf.h \
+ ../../../curr_ip.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_const.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_stat.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_ips.h \
+ ../../../user_property.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/notifer.h \
+ ../../../script_executer.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_auth.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_plugin.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_message.h \
+ ../../../tariffs.h ../../../actions.h ../../../actions.inl.h \
+ ../../../eventloop.h ../../../tariffs.h ../../../traffcounter.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/raw_ip_packet.h \
+ ../../../users.h ../../../settings.h Makefile ../../../../../Makefile.conf
+ $(CC) -c $< -g3 -W -Wall -I/usr/local/include -DARCH_LE -fPIC -I /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include -DDEBUG -DLINUX
+messages_methods.o: messages_methods.cpp messages_methods.h \
+ ../../../users.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ ../../../settings.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/dotconfpp.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/mempool.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/common.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_const.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_settings.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_logger.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/noncopyable.h \
+ ../../../user.h ../../../tariff.h ../../../admin.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/admin_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/admin_conf.inc.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/tariff_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/resetable.h \
+ ../../../curr_ip.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_const.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_stat.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_traff.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_locker.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_ips.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/common.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_ips.h \
+ ../../../user_property.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_store.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_stat.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/user_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/corp_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/service_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/admin_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/tariff_conf.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_settings.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_message.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/notifer.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_locker.h \
+ ../../../script_executer.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_auth.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_plugin.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_message.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/noncopyable.h \
+ ../../../tariffs.h ../../../actions.h ../../../actions.inl.h \
+ ../../../eventloop.h rpcconfig.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/base_plugin.h \
+ ../../../admin.h ../../../admins.h ../../../tariffs.h \
+ ../../../traffcounter.h \
+ /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include/raw_ip_packet.h \
+ ../../../users.h ../../../settings.h utils.h Makefile ../../../../../Makefile.conf
+ $(CC) -c $< -g3 -W -Wall -I/usr/local/include -DARCH_LE -fPIC -I /home/faust/Projects/STG/stg-2.5/projects/stargazer/../../include -DDEBUG -DLINUX
--- /dev/null
+#include "info_methods.h"
+
+#include <sys/utsname.h>
+#include "version.h"
+#include "rpcconfig.h"
+
+void METHOD_INFO::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+paramList.verifyEnd(0);
+std::map<std::string, xmlrpc_c::value> structVal;
+
+std::string un;
+struct utsname utsn;
+
+uname(&utsn);
+un[0] = 0;
+
+un += utsn.sysname;
+un += " ";
+un += utsn.release;
+un += " ";
+un += utsn.machine;
+un += " ";
+un += utsn.nodename;
+
+structVal["version"] = xmlrpc_c::value_string(SERVER_VERSION);
+structVal["tariff_num"] = xmlrpc_c::value_int(tariffs->GetTariffsNum());
+structVal["tariff"] = xmlrpc_c::value_int(2);
+structVal["users_num"] = xmlrpc_c::value_int(users->GetUserNum());
+structVal["uname"] = xmlrpc_c::value_string(un);
+structVal["dir_num"] = xmlrpc_c::value_int(DIR_NUM);
+structVal["day_fee"] = xmlrpc_c::value_int(settings->GetDayFee());
+
+std::vector<xmlrpc_c::value> dirnameVal;
+
+for (int i = 0; i< DIR_NUM; i++)
+ {
+ string dn2e;
+ Encode12str(dn2e, settings->GetDirName(i));
+ dirnameVal.push_back(xmlrpc_c::value_string(dn2e));
+ }
+
+structVal["dir_names"] = xmlrpc_c::value_array(dirnameVal);
+
+*retvalPtr = xmlrpc_c::value_struct(structVal);
+}
+
+void METHOD_LOGIN::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string login = paramList.getString(0);
+std::string password = paramList.getString(1);
+paramList.verifyEnd(2);
+
+std::map<std::string, xmlrpc_c::value> structVal;
+
+std::string cookie;
+if (config->CheckAdmin(login, password, &cookie))
+ {
+ structVal["result"] = xmlrpc_c::value_boolean(false);
+ structVal["cookie"] = xmlrpc_c::value_string("");
+ }
+else
+ {
+ structVal["result"] = xmlrpc_c::value_boolean(true);
+ structVal["cookie"] = xmlrpc_c::value_string(cookie);
+ }
+
+*retvalPtr = xmlrpc_c::value_struct(structVal);
+}
+
+void METHOD_LOGOUT::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+paramList.verifyEnd(1);
+
+std::map<std::string, xmlrpc_c::value> structVal;
+
+if (config->LogoutAdmin(cookie))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ }
+else
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(true);
+ }
+}
--- /dev/null
+#ifndef __INFO_METHODS_H__
+#define __INFO_METHODS_H__
+
+#include <xmlrpc-c/base.hpp>
+#include <xmlrpc-c/registry.hpp>
+
+#include "../../../users.h"
+#include "../../../tariffs.h"
+#include "../../../settings.h"
+
+// Forward declaration
+class RPC_CONFIG;
+
+class METHOD_INFO : public xmlrpc_c::method
+{
+public:
+ METHOD_INFO(TARIFFS * t,
+ USERS * u,
+ const SETTINGS * s)
+ : tariffs(t),
+ users(u),
+ settings(s)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalP);
+private:
+ TARIFFS * tariffs;
+ USERS * users;
+ const SETTINGS * settings;
+};
+
+class METHOD_LOGIN : public xmlrpc_c::method
+{
+public:
+ METHOD_LOGIN(RPC_CONFIG * c)
+ : config(c)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalP);
+private:
+ RPC_CONFIG * config;
+};
+
+class METHOD_LOGOUT : public xmlrpc_c::method
+{
+public:
+ METHOD_LOGOUT(RPC_CONFIG * c)
+ : config(c)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalP);
+private:
+ RPC_CONFIG * config;
+};
+
+#endif
--- /dev/null
+#include "messages_methods.h"
+
+#include "rpcconfig.h"
+#include "stg_message.h"
+#include "utils.h"
+
+//------------------------------------------------------------------------------
+
+void METHOD_MESSAGE_SEND::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::vector<xmlrpc_c::value> logins(paramList.getArray(1));
+std::map<std::string, xmlrpc_c::value> msgInfo(paramList.getStruct(2));
+paramList.verifyEnd(3);
+
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+STG_MSG message;
+
+std::map<std::string, xmlrpc_c::value>::iterator it;
+
+if ((it = msgInfo.find("version")) == msgInfo.end())
+ {
+ message.header.ver = 1; // Default value
+ }
+else
+ {
+ message.header.ver = xmlrpc_c::value_int(it->second);
+ }
+
+if ((it = msgInfo.find("type")) == msgInfo.end())
+ {
+ message.header.type = 1; // default value
+ }
+else
+ {
+ message.header.type = xmlrpc_c::value_int(it->second);
+ }
+
+if ((it = msgInfo.find("repeat")) == msgInfo.end())
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+message.header.repeat = xmlrpc_c::value_int(it->second);
+
+if ((it = msgInfo.find("repeat_period")) == msgInfo.end())
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+message.header.repeatPeriod = xmlrpc_c::value_int(it->second);
+
+if ((it = msgInfo.find("show_time")) == msgInfo.end())
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+message.header.showTime = xmlrpc_c::value_int(it->second);
+
+if ((it = msgInfo.find("text")) == msgInfo.end())
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+message.text = IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "CP1251");
+
+message.header.creationTime = stgTime;
+message.header.lastSendTime = 0;
+
+std::vector<xmlrpc_c::value>::iterator lit;
+for (lit = logins.begin(); lit != logins.end(); ++lit)
+ {
+ user_iter ui;
+ if (users->FindByName(xmlrpc_c::value_string(*lit), &ui))
+ {
+ printfd(__FILE__, "METHOD_MESSAGE_SEND::execute(): 'User '%s' not found'\n", std::string(xmlrpc_c::value_string(*lit)).c_str());
+ }
+ else
+ {
+ ui->AddMessage(&message);
+ }
+ }
+
+*retvalPtr = xmlrpc_c::value_boolean(true);
+}
--- /dev/null
+#ifndef __MESSAGES_METHODS_H__
+#define __MESSAGES_METHODS_H__
+
+#include <xmlrpc-c/base.hpp>
+#include <xmlrpc-c/registry.hpp>
+
+#include "../../../users.h"
+
+class RPC_CONFIG;
+
+class METHOD_MESSAGE_SEND : public xmlrpc_c::method {
+public:
+ METHOD_MESSAGE_SEND(RPC_CONFIG * c,
+ USERS * u)
+ : config(c),
+ users(u)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr);
+private:
+ RPC_CONFIG * config;
+ USERS * users;
+};
+
+#endif
--- /dev/null
+#include "rpcconfig.h"
+
+#include <cstdlib>
+#include <csignal>
+#include "info_methods.h"
+#include "users_methods.h"
+#include "tariffs_methods.h"
+#include "admins_methods.h"
+#include "messages_methods.h"
+
+class RPC_CONFIG_CREATOR
+{
+private:
+ RPC_CONFIG * rpcconfig;
+
+public:
+ RPC_CONFIG_CREATOR()
+ : rpcconfig(new RPC_CONFIG())
+ {
+ };
+ ~RPC_CONFIG_CREATOR()
+ {
+ delete rpcconfig;
+ };
+
+ RPC_CONFIG * GetPlugin()
+ {
+ return rpcconfig;
+ };
+};
+
+RPC_CONFIG_CREATOR rpcc;
+
+RPC_CONFIG_SETTINGS::RPC_CONFIG_SETTINGS()
+ : errorStr(),
+ port(0),
+ cookieTimeout(0)
+{
+}
+
+int RPC_CONFIG_SETTINGS::ParseIntInRange(const string & str,
+ int min,
+ int max,
+ int * val)
+{
+if (str2x(str.c_str(), *val))
+ {
+ errorStr = "Incorrect value \'" + str + "\'.";
+ return -1;
+ }
+if (*val < min || *val > max)
+ {
+ errorStr = "Value \'" + str + "\' out of range.";
+ return -1;
+ }
+return 0;
+}
+
+int RPC_CONFIG_SETTINGS::ParseSettings(const MODULE_SETTINGS & s)
+{
+int p;
+PARAM_VALUE pv;
+vector<PARAM_VALUE>::const_iterator pvi;
+
+pv.param = "Port";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end())
+ {
+ errorStr = "Parameter \'Port\' not found.";
+ printfd(__FILE__, "Parameter 'Port' not found\n");
+ return -1;
+ }
+if (ParseIntInRange(pvi->value[0], 2, 65535, &p))
+ {
+ errorStr = "Cannot parse parameter \'Port\': " + errorStr;
+ printfd(__FILE__, "Cannot parse parameter 'Port'\n");
+ return -1;
+ }
+port = p;
+
+pv.param = "CookieTimeout";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end())
+ {
+ cookieTimeout = 1800; // 30 * 60
+ }
+else
+ {
+ if (str2x(pvi->value[0], cookieTimeout))
+ {
+ errorStr = "Incorrect value of CookieTimeout: \'" + pvi->value[0] + "\'";
+ printfd(__FILE__, "Incorrect value of 'CookieTimeout'\n");
+ return -1;
+ }
+ }
+
+return 0;
+}
+
+BASE_PLUGIN * GetPlugin()
+{
+return rpcc.GetPlugin();
+}
+
+RPC_CONFIG::RPC_CONFIG()
+ : rpcServer(NULL)
+{
+
+}
+
+RPC_CONFIG::~RPC_CONFIG()
+{
+// delete server
+delete rpcServer;
+}
+
+int RPC_CONFIG::ParseSettings()
+{
+int ret = rpcConfigSettings.ParseSettings(settings);
+
+if (ret)
+ errorStr = rpcConfigSettings.GetStrError();
+
+return ret;
+}
+
+int RPC_CONFIG::Start()
+{
+InitiateRegistry();
+running = true;
+rpcServer = new xmlrpc_c::serverAbyss(
+ rpcRegistry,
+ rpcConfigSettings.GetPort(),
+ "/var/log/stargazer_rpc.log"
+ );
+if (pthread_create(&tid, NULL, Run, this))
+ {
+ errorStr = "Failed to create RPC thread";
+ printfd(__FILE__, "Failed to crate RPC thread\n");
+ return -1;
+ }
+return 0;
+}
+
+int RPC_CONFIG::Stop()
+{
+running = false;
+for (int i = 0; i < 5 && !stopped; ++i)
+ usleep(200000);
+//rpcServer->terminate();
+if (!stopped)
+ {
+ if (pthread_kill(tid, SIGTERM))
+ {
+ errorStr = "Failed to kill thread";
+ printfd(__FILE__, "Failed to kill thread\n");
+ }
+ for (int i = 0; i < 25 && !stopped; ++i)
+ usleep(200000);
+ if (!stopped)
+ {
+ printfd(__FILE__, "Failed to stop RPC thread\n");
+ errorStr = "Failed to stop RPC thread";
+ return -1;
+ }
+ else
+ {
+ pthread_join(tid, NULL);
+ }
+ }
+return 0;
+}
+
+void * RPC_CONFIG::Run(void * rc)
+{
+RPC_CONFIG * config = static_cast<RPC_CONFIG *>(rc);
+
+config->stopped = false;
+while (config->running)
+ {
+ config->rpcServer->runOnce();
+ }
+config->stopped = true;
+
+return NULL;
+}
+
+bool RPC_CONFIG::GetAdminInfo(const std::string & cookie,
+ ADMIN_INFO * info)
+{
+std::map<std::string,
+ ADMIN_INFO>::iterator it;
+
+it = cookies.find(cookie);
+
+if (it == cookies.end())
+ {
+ return true;
+ }
+
+if (difftime(it->second.accessTime, time(NULL)) >
+ rpcConfigSettings.GetCookieTimeout())
+ {
+ cookies.erase(it);
+ return true;
+ }
+
+// Update access time
+time(&it->second.accessTime);
+*info = it->second;
+return false;
+}
+
+bool RPC_CONFIG::CheckAdmin(const std::string & login,
+ const std::string & password,
+ std::string * cookie)
+{
+ADMIN admin;
+
+if (!admins->AdminCorrect(login, password, &admin))
+ {
+ return true;
+ }
+
+ADMIN_INFO info;
+time(&info.accessTime);
+info.admin = login;
+info.priviledges = *admin.GetPriv();
+*cookie = GetCookie();
+cookies[*cookie] = info;
+
+return false;
+}
+
+bool RPC_CONFIG::LogoutAdmin(const std::string & cookie)
+{
+std::map<std::string,
+ ADMIN_INFO>::iterator it;
+
+it = cookies.find(cookie);
+
+if (it == cookies.end())
+ {
+ return true;
+ }
+
+cookies.erase(it);
+
+return false;
+}
+
+std::string RPC_CONFIG::GetCookie() const
+{
+std::string charset("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890");
+std::string cookie;
+
+for (int i = 0; i < 64; ++i)
+ {
+ cookie += charset[rand() % charset.length()];
+ };
+
+return cookie;
+}
+
+void RPC_CONFIG::InitiateRegistry()
+{
+// manage registry
+xmlrpc_c::methodPtr const methodInfoPtr(new METHOD_INFO(
+ tariffs,
+ users,
+ stgSettings
+ ));
+rpcRegistry.addMethod("stargazer.info", methodInfoPtr);
+
+xmlrpc_c::methodPtr const methodLoginPtr(new METHOD_LOGIN(
+ this
+ ));
+rpcRegistry.addMethod("stargazer.login", methodLoginPtr);
+
+xmlrpc_c::methodPtr const methodLogoutPtr(new METHOD_LOGOUT(
+ this
+ ));
+rpcRegistry.addMethod("stargazer.logout", methodLogoutPtr);
+
+xmlrpc_c::methodPtr const methodGetUserPtr(new METHOD_USER_GET(
+ this,
+ users
+ ));
+rpcRegistry.addMethod("stargazer.get_user", methodGetUserPtr);
+
+xmlrpc_c::methodPtr const methodAddUserPtr(new METHOD_USER_ADD(
+ this,
+ admins,
+ users
+ ));
+rpcRegistry.addMethod("stargazer.add_user", methodAddUserPtr);
+
+xmlrpc_c::methodPtr const methodDelUserPtr(new METHOD_USER_DEL(
+ this,
+ admins,
+ users
+ ));
+rpcRegistry.addMethod("stargazer.del_user", methodDelUserPtr);
+
+xmlrpc_c::methodPtr const methodGetUsersPtr(new METHOD_USERS_GET(
+ this,
+ users
+ ));
+rpcRegistry.addMethod("stargazer.get_users", methodGetUsersPtr);
+
+xmlrpc_c::methodPtr const methodChgUserPtr(new METHOD_USER_CHG(
+ this,
+ admins,
+ store,
+ users
+ ));
+rpcRegistry.addMethod("stargazer.chg_user", methodChgUserPtr);
+
+xmlrpc_c::methodPtr const methodAddCashPtr(new METHOD_USER_CASH_ADD(
+ this,
+ admins,
+ store,
+ users
+ ));
+rpcRegistry.addMethod("stargazer.add_cash", methodAddCashPtr);
+
+xmlrpc_c::methodPtr const methodSetCashPtr(new METHOD_USER_CASH_SET(
+ this,
+ admins,
+ store,
+ users
+ ));
+rpcRegistry.addMethod("stargazer.set_cash", methodSetCashPtr);
+
+xmlrpc_c::methodPtr const methodTariffChangePtr(new METHOD_USER_TARIFF_CHANGE(
+ this,
+ admins,
+ tariffs,
+ store,
+ users
+ ));
+rpcRegistry.addMethod("stargazer.tariff_change", methodTariffChangePtr);
+
+xmlrpc_c::methodPtr const methodGetTariffPtr(new METHOD_TARIFF_GET(
+ this,
+ tariffs
+ ));
+rpcRegistry.addMethod("stargazer.get_tariff", methodGetTariffPtr);
+
+xmlrpc_c::methodPtr const methodChgTariffPtr(new METHOD_TARIFF_CHG(
+ this,
+ admins,
+ tariffs
+ ));
+rpcRegistry.addMethod("stargazer.chg_tariff", methodChgTariffPtr);
+
+xmlrpc_c::methodPtr const methodGetTariffsPtr(new METHOD_TARIFFS_GET(
+ this,
+ tariffs
+ ));
+rpcRegistry.addMethod("stargazer.get_tariffs", methodGetTariffsPtr);
+
+xmlrpc_c::methodPtr const methodAddTariffPtr(new METHOD_TARIFF_ADD(
+ this,
+ admins,
+ tariffs
+ ));
+rpcRegistry.addMethod("stargazer.add_tariff", methodAddTariffPtr);
+
+xmlrpc_c::methodPtr const methodDelTariffPtr(new METHOD_TARIFF_DEL(
+ this,
+ admins,
+ tariffs,
+ users
+ ));
+rpcRegistry.addMethod("stargazer.del_tariff", methodDelTariffPtr);
+
+xmlrpc_c::methodPtr const methodGetAdminPtr(new METHOD_ADMIN_GET(
+ this,
+ admins
+ ));
+rpcRegistry.addMethod("stargazer.get_admin", methodGetAdminPtr);
+
+xmlrpc_c::methodPtr const methodAddAdminPtr(new METHOD_ADMIN_ADD(
+ this,
+ admins
+ ));
+rpcRegistry.addMethod("stargazer.add_admin", methodAddAdminPtr);
+
+xmlrpc_c::methodPtr const methodDelAdminPtr(new METHOD_ADMIN_DEL(
+ this,
+ admins
+ ));
+rpcRegistry.addMethod("stargazer.del_admin", methodDelAdminPtr);
+
+xmlrpc_c::methodPtr const methodChgAdminPtr(new METHOD_ADMIN_CHG(
+ this,
+ admins
+ ));
+rpcRegistry.addMethod("stargazer.chg_admin", methodChgAdminPtr);
+
+xmlrpc_c::methodPtr const methodGetAdminsPtr(new METHOD_ADMINS_GET(
+ this,
+ admins
+ ));
+rpcRegistry.addMethod("stargazer.get_admins", methodGetAdminsPtr);
+
+xmlrpc_c::methodPtr const methodSendMessagePtr(new METHOD_MESSAGE_SEND(
+ this,
+ users
+ ));
+rpcRegistry.addMethod("stargazer.send_message", methodSendMessagePtr);
+
+xmlrpc_c::methodPtr const methodGetOnlinIPsPtr(new METHOD_GET_ONLINE_IPS(
+ this,
+ users
+ ));
+rpcRegistry.addMethod("stargazer.get_online_ips", methodGetOnlinIPsPtr);
+}
+
--- /dev/null
+#ifndef __RPC_CONFIG_H__
+#define __RPC_CONFIG_H__
+
+#include <string>
+
+#include <xmlrpc-c/base.hpp>
+#include <xmlrpc-c/registry.hpp>
+#include <xmlrpc-c/server_abyss.hpp>
+
+#include <pthread.h>
+
+#include "base_plugin.h"
+#include "base_store.h"
+#include "base_settings.h"
+#include "admin_conf.h"
+#include "../../../admin.h"
+#include "../../../admins.h"
+#include "../../../users.h"
+#include "../../../tariffs.h"
+#include "../../../traffcounter.h"
+#include "../../../settings.h"
+
+#define RPC_CONFIG_VERSION "Stargazer RPC v. 0.2"
+
+extern "C" BASE_PLUGIN * GetPlugin();
+
+class RPC_CONFIG_SETTINGS
+{
+public:
+ RPC_CONFIG_SETTINGS();
+ virtual ~RPC_CONFIG_SETTINGS() {};
+ const std::string & GetStrError() const { return errorStr; };
+ int ParseSettings(const MODULE_SETTINGS & s);
+ uint16_t GetPort() const { return port; };
+ double GetCookieTimeout() const { return cookieTimeout; };
+private:
+ int ParseIntInRange(const std::string & str,
+ int min,
+ int max,
+ int * val);
+ std::string errorStr;
+ int port;
+ double cookieTimeout;
+};
+
+struct ADMIN_INFO
+{
+ std::string admin;
+ time_t accessTime;
+ PRIV priviledges;
+};
+
+class RPC_CONFIG :public BASE_PLUGIN
+{
+public:
+ RPC_CONFIG();
+ virtual ~RPC_CONFIG();
+
+ void SetUsers(USERS * u) { users = u; };
+ void SetTariffs(TARIFFS * t) { tariffs = t; };
+ void SetAdmins(ADMINS * a) { admins = a; };
+ void SetStore(BASE_STORE * s) { store = s; };
+ void SetTraffcounter(TRAFFCOUNTER *) {};
+ void SetStgSettings(const SETTINGS * s) { stgSettings = s; };
+ void SetSettings(const MODULE_SETTINGS & s) { settings = s; };
+ int ParseSettings();
+
+ int Start();
+ int Stop();
+ int Reload() { return 0; };
+ bool IsRunning() { return running && !stopped; };
+
+ const string & GetStrError() const { return errorStr; };
+ const string GetVersion() const { return RPC_CONFIG_VERSION; };
+ uint16_t GetStartPosition() const { return 220; };
+ uint16_t GetStopPosition() const { return 220; };
+
+ bool GetAdminInfo(const std::string & cookie,
+ ADMIN_INFO * info);
+ bool CheckAdmin(const std::string & login,
+ const std::string & password,
+ std::string * cookie);
+ bool LogoutAdmin(const std::string & cookie);
+
+private:
+ mutable string errorStr;
+ RPC_CONFIG_SETTINGS rpcConfigSettings;
+ USERS * users;
+ ADMINS * admins;
+ TARIFFS * tariffs;
+ BASE_STORE * store;
+ MODULE_SETTINGS settings;
+ const SETTINGS * stgSettings;
+ xmlrpc_c::registry rpcRegistry;
+ xmlrpc_c::serverAbyss * rpcServer;
+ bool running;
+ bool stopped;
+ pthread_t tid;
+ std::map<std::string,
+ ADMIN_INFO> cookies;
+
+ static void * Run(void *);
+ std::string GetCookie() const;
+ void InitiateRegistry();
+};
+
+#endif
--- /dev/null
+#include "tariff_helper.h"
+
+void TARIFF_HELPER::GetTariffInfo(xmlrpc_c::value * info) const
+{
+std::map<std::string, xmlrpc_c::value> structVal;
+
+structVal["result"] = xmlrpc_c::value_boolean(true);
+structVal["name"] = xmlrpc_c::value_string(data.tariffConf.name);
+structVal["fee"] = xmlrpc_c::value_double(data.tariffConf.fee);
+structVal["freemb"] = xmlrpc_c::value_double(data.tariffConf.free);
+structVal["passivecost"] = xmlrpc_c::value_double(data.tariffConf.passiveCost);
+structVal["traffType"] = xmlrpc_c::value_int(data.tariffConf.traffType);
+
+std::vector<xmlrpc_c::value> prices(DIR_NUM);
+
+for (unsigned i = 0; i < DIR_NUM; ++i)
+ {
+ std::map<std::string, xmlrpc_c::value> dirPrice;
+ dirPrice["hday"] = xmlrpc_c::value_int(data.dirPrice[i].hDay);
+ dirPrice["mday"] = xmlrpc_c::value_int(data.dirPrice[i].mDay);
+ dirPrice["hnight"] = xmlrpc_c::value_int(data.dirPrice[i].hNight);
+ dirPrice["mnight"] = xmlrpc_c::value_int(data.dirPrice[i].mNight);
+ dirPrice["pricedaya"] = xmlrpc_c::value_double(data.dirPrice[i].priceDayA * 1024 * 1024);
+ dirPrice["pricedayb"] = xmlrpc_c::value_double(data.dirPrice[i].priceDayB * 1024 * 1024);
+ dirPrice["pricenighta"] = xmlrpc_c::value_double(data.dirPrice[i].priceNightA * 1024 * 1024);
+ dirPrice["pricenightb"] = xmlrpc_c::value_double(data.dirPrice[i].priceNightB * 1024 * 1024);
+ dirPrice["threshold"] = xmlrpc_c::value_int(data.dirPrice[i].threshold);
+ dirPrice["singleprice"] = xmlrpc_c::value_boolean(data.dirPrice[i].singlePrice);
+ dirPrice["nodiscount"] = xmlrpc_c::value_boolean(data.dirPrice[i].noDiscount);
+ prices[i] = xmlrpc_c::value_struct(dirPrice);
+ }
+
+structVal["dirprices"] = xmlrpc_c::value_array(prices);
+
+*info = xmlrpc_c::value_struct(structVal);
+}
+
+bool TARIFF_HELPER::SetTariffInfo(const xmlrpc_c::value & info)
+{
+std::map<std::string, xmlrpc_c::value> structVal(
+ static_cast<std::map<std::string, xmlrpc_c::value> >(xmlrpc_c::value_struct(info))
+ );
+
+std::map<std::string, xmlrpc_c::value>::iterator it;
+
+if ((it = structVal.find("fee")) != structVal.end())
+ {
+ data.tariffConf.fee = xmlrpc_c::value_double(it->second);
+ }
+
+if ((it = structVal.find("freemb")) != structVal.end())
+ {
+ data.tariffConf.free = xmlrpc_c::value_double(it->second);
+ }
+
+if ((it = structVal.find("passivecost")) != structVal.end())
+ {
+ data.tariffConf.passiveCost = xmlrpc_c::value_double(it->second);
+ }
+
+if ((it = structVal.find("traffType")) != structVal.end())
+ {
+ data.tariffConf.traffType = xmlrpc_c::value_int(it->second);
+ }
+
+if ((it = structVal.find("dirprices")) != structVal.end())
+ {
+ std::vector<xmlrpc_c::value> prices(
+ xmlrpc_c::value_array(it->second).vectorValueValue()
+ );
+
+ for (unsigned i = 0; i < DIR_NUM; ++i)
+ {
+ std::map<std::string, xmlrpc_c::value> dirPrice(
+ static_cast<std::map<std::string, xmlrpc_c::value> >(xmlrpc_c::value_struct(prices[i]))
+ );
+ data.dirPrice[i].mDay = xmlrpc_c::value_int(dirPrice["mday"]);
+ data.dirPrice[i].hDay = xmlrpc_c::value_int(dirPrice["hday"]);
+ data.dirPrice[i].mNight = xmlrpc_c::value_int(dirPrice["mnight"]);
+ data.dirPrice[i].hNight = xmlrpc_c::value_int(dirPrice["hnight"]);
+ data.dirPrice[i].priceDayA = xmlrpc_c::value_double(dirPrice["pricedaya"]) / 1024 / 1024;
+ data.dirPrice[i].priceDayB = xmlrpc_c::value_double(dirPrice["pricedayb"]) / 1024 / 1024;
+ data.dirPrice[i].priceNightA = xmlrpc_c::value_double(dirPrice["pricenighta"]) / 1024 / 1024;
+ data.dirPrice[i].priceNightB = xmlrpc_c::value_double(dirPrice["pricenightb"]) / 1024 / 1024;
+ data.dirPrice[i].threshold = xmlrpc_c::value_int(dirPrice["threshold"]);
+ data.dirPrice[i].singlePrice = xmlrpc_c::value_boolean(dirPrice["singleprice"]);
+ data.dirPrice[i].noDiscount = xmlrpc_c::value_boolean(dirPrice["nodiscount"]);
+ }
+ }
+
+return false;
+}
--- /dev/null
+#ifndef __TARIFF_HELPER_H__
+#define __TARIFF_HELPER_H__
+
+#include <xmlrpc-c/base.hpp>
+#include "../../../tariff.h"
+#include "tariff_conf.h"
+
+class TARIFF_HELPER
+{
+public:
+ TARIFF_HELPER(TARIFF_DATA & td)
+ : data(td)
+ {}
+
+ void GetTariffInfo(xmlrpc_c::value * info) const;
+ bool SetTariffInfo(const xmlrpc_c::value & info);
+private:
+ TARIFF_DATA & data;
+};
+
+#endif
+
+
--- /dev/null
+#include "rpcconfig.h"
+#include "tariffs_methods.h"
+#include "tariff_helper.h"
+
+void METHOD_TARIFF_GET::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string name = paramList.getString(1);
+paramList.verifyEnd(2);
+
+std::map<std::string, xmlrpc_c::value> structVal;
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ structVal["result"] = xmlrpc_c::value_boolean(false);
+ *retvalPtr = xmlrpc_c::value_struct(structVal);
+ return;
+ }
+
+const TARIFF * tariff = tariffs->FindByName(name);
+
+if (!tariff)
+ {
+ structVal["result"] = xmlrpc_c::value_boolean(false);
+ *retvalPtr = xmlrpc_c::value_struct(structVal);
+ return;
+ }
+
+TARIFF_DATA td;
+
+tariff->GetTariffData(&td);
+
+TARIFF_HELPER helper(td);
+
+helper.GetTariffInfo(retvalPtr);
+}
+
+void METHOD_TARIFF_CHG::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string name = paramList.getString(1);
+xmlrpc_c::value_struct info(paramList.getStruct(2));
+paramList.verifyEnd(3);
+
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+ADMIN admin;
+
+if (admins->FindAdmin(adminInfo.admin, &admin))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+const TARIFF * tariff = tariffs->FindByName(name);
+
+if (!tariff)
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+TARIFF_DATA td;
+
+tariff->GetTariffData(&td);
+
+TARIFF_HELPER helper(td);
+
+helper.SetTariffInfo(info);
+
+if (tariffs->Chg(td, admin))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+*retvalPtr = xmlrpc_c::value_boolean(true);
+}
+
+void METHOD_TARIFFS_GET::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+paramList.verifyEnd(1);
+
+std::map<std::string, xmlrpc_c::value> structVal;
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ structVal["result"] = xmlrpc_c::value_boolean(false);
+ *retvalPtr = xmlrpc_c::value_struct(structVal);
+ return;
+ }
+
+std::vector<xmlrpc_c::value> tariffsInfo;
+
+
+std::list<TARIFF_DATA> dataList;
+tariffs->GetTariffsData(&dataList);
+std::list<TARIFF_DATA>::const_iterator it = dataList.begin();
+for (; it != dataList.end(); ++it)
+ {
+ xmlrpc_c::value info;
+ TARIFF_DATA td(*it); // 'cause TARIFF_HELPER work in both ways and take not const referense
+ TARIFF_HELPER helper(td);
+ helper.GetTariffInfo(&info);
+ tariffsInfo.push_back(info);
+ }
+
+*retvalPtr = xmlrpc_c::value_array(tariffsInfo);
+}
+
+void METHOD_TARIFF_ADD::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string tariff = paramList.getString(1);
+std::string enc;
+paramList.verifyEnd(2);
+
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+ADMIN admin;
+
+if (admins->FindAdmin(adminInfo.admin, &admin))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+if (tariffs->Add(tariff, admin))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+*retvalPtr = xmlrpc_c::value_boolean(true);
+}
+
+void METHOD_TARIFF_DEL::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string tariff = paramList.getString(1);
+paramList.verifyEnd(2);
+
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+ADMIN admin;
+
+if (admins->FindAdmin(adminInfo.admin, &admin))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+if (users->TariffInUse(tariff))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+if (tariffs->Del(tariff, admin))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+*retvalPtr = xmlrpc_c::value_boolean(true);
+}
--- /dev/null
+#ifndef __TARIFFS_METHODS_H__
+#define __TARIFFS_METHODS_H__
+
+#include <xmlrpc-c/base.hpp>
+#include <xmlrpc-c/registry.hpp>
+
+#include "../../../tariffs.h"
+
+class RPC_CONFIG;
+
+class METHOD_TARIFF_GET : public xmlrpc_c::method {
+public:
+ METHOD_TARIFF_GET(RPC_CONFIG * c,
+ TARIFFS * t)
+ : config(c),
+ tariffs(t)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr);
+private:
+ RPC_CONFIG * config;
+ TARIFFS * tariffs;
+};
+
+class METHOD_TARIFF_CHG : public xmlrpc_c::method {
+public:
+ METHOD_TARIFF_CHG(RPC_CONFIG * c,
+ ADMINS * a,
+ TARIFFS * t)
+ : config(c),
+ admins(a),
+ tariffs(t)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr);
+private:
+ RPC_CONFIG * config;
+ ADMINS * admins;
+ TARIFFS * tariffs;
+};
+
+class METHOD_TARIFFS_GET : public xmlrpc_c::method {
+public:
+ METHOD_TARIFFS_GET(RPC_CONFIG * c,
+ TARIFFS * t)
+ : config(c),
+ tariffs(t)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr);
+private:
+ RPC_CONFIG * config;
+ TARIFFS * tariffs;
+};
+
+class METHOD_TARIFF_ADD : public xmlrpc_c::method {
+public:
+ METHOD_TARIFF_ADD(RPC_CONFIG * c,
+ ADMINS * a,
+ TARIFFS * t)
+ : config(c),
+ admins(a),
+ tariffs(t)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalP);
+private:
+ RPC_CONFIG * config;
+ ADMINS * admins;
+ TARIFFS * tariffs;
+};
+
+class METHOD_TARIFF_DEL : public xmlrpc_c::method {
+public:
+ METHOD_TARIFF_DEL(RPC_CONFIG * c,
+ ADMINS * a,
+ TARIFFS * t,
+ USERS * u)
+ : config(c),
+ admins(a),
+ tariffs(t),
+ users(u)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalP);
+private:
+ RPC_CONFIG * config;
+ ADMINS * admins;
+ TARIFFS * tariffs;
+ USERS * users;
+};
+
+#endif
--- /dev/null
+#include "user_helper.h"
+
+#include "user_ips.h"
+#include "utils.h"
+
+//------------------------------------------------------------------------------
+
+void USER_HELPER::GetUserInfo(xmlrpc_c::value * info,
+ bool hidePassword)
+{
+std::string enc;
+
+std::map<std::string, xmlrpc_c::value> structVal;
+
+structVal["result"] = xmlrpc_c::value_boolean(true);
+structVal["login"] = xmlrpc_c::value_string(iter->GetLogin());
+
+if (!hidePassword)
+ {
+ structVal["password"] = xmlrpc_c::value_string(iter->property.password.Get());
+ }
+else
+ {
+ structVal["password"] = xmlrpc_c::value_string("++++++++");
+ }
+
+structVal["cash"] = xmlrpc_c::value_double(iter->property.cash.Get());
+structVal["freemb"] = xmlrpc_c::value_double(iter->property.freeMb.Get());
+structVal["credit"] = xmlrpc_c::value_double(iter->property.credit.Get());
+
+if (iter->property.nextTariff.Get() != "")
+ {
+ structVal["tariff"] = xmlrpc_c::value_string(
+ iter->property.tariffName.Get() +
+ "/" +
+ iter->property.nextTariff.Get()
+ );
+ }
+else
+ {
+ structVal["tariff"] = xmlrpc_c::value_string(iter->property.tariffName.Get());
+ }
+
+structVal["note"] = xmlrpc_c::value_string(IconvString(iter->property.note, "KOI8-R", "UTF-8"));
+
+structVal["phone"] = xmlrpc_c::value_string(IconvString(iter->property.phone, "KOI8-R", "UTF-8"));
+
+structVal["address"] = xmlrpc_c::value_string(IconvString(iter->property.address, "KOI8-R", "UTF-8"));
+
+structVal["email"] = xmlrpc_c::value_string(IconvString(iter->property.email, "KOI8-R", "UTF-8"));
+
+std::vector<xmlrpc_c::value> userdata;
+
+userdata.push_back(xmlrpc_c::value_string(IconvString(iter->property.userdata0.Get(), "KOI8-R", "UTF-8")));
+userdata.push_back(xmlrpc_c::value_string(IconvString(iter->property.userdata1.Get(), "KOI8-R", "UTF-8")));
+userdata.push_back(xmlrpc_c::value_string(IconvString(iter->property.userdata2.Get(), "KOI8-R", "UTF-8")));
+userdata.push_back(xmlrpc_c::value_string(IconvString(iter->property.userdata3.Get(), "KOI8-R", "UTF-8")));
+userdata.push_back(xmlrpc_c::value_string(IconvString(iter->property.userdata4.Get(), "KOI8-R", "UTF-8")));
+userdata.push_back(xmlrpc_c::value_string(IconvString(iter->property.userdata5.Get(), "KOI8-R", "UTF-8")));
+userdata.push_back(xmlrpc_c::value_string(IconvString(iter->property.userdata6.Get(), "KOI8-R", "UTF-8")));
+userdata.push_back(xmlrpc_c::value_string(IconvString(iter->property.userdata7.Get(), "KOI8-R", "UTF-8")));
+userdata.push_back(xmlrpc_c::value_string(IconvString(iter->property.userdata8.Get(), "KOI8-R", "UTF-8")));
+userdata.push_back(xmlrpc_c::value_string(IconvString(iter->property.userdata9.Get(), "KOI8-R", "UTF-8")));
+
+structVal["userdata"] = xmlrpc_c::value_array(userdata);
+
+structVal["name"] = xmlrpc_c::value_string(IconvString(iter->property.realName, "KOI8-R", "UTF-8"));
+
+structVal["group"] = xmlrpc_c::value_string(IconvString(iter->property.group, "KOI8-R", "UTF-8"));
+
+structVal["status"] = xmlrpc_c::value_boolean(iter->GetConnected());
+structVal["aonline"] = xmlrpc_c::value_boolean(iter->property.alwaysOnline.Get());
+structVal["currip"] = xmlrpc_c::value_string(inet_ntostring(iter->GetCurrIP()));
+structVal["pingtime"] = xmlrpc_c::value_int(iter->GetPingTime());
+structVal["ips"] = xmlrpc_c::value_string(iter->property.ips.Get().GetIpStr());
+
+std::map<std::string, xmlrpc_c::value> traffInfo;
+std::vector<xmlrpc_c::value> mu(DIR_NUM);
+std::vector<xmlrpc_c::value> md(DIR_NUM);
+std::vector<xmlrpc_c::value> su(DIR_NUM);
+std::vector<xmlrpc_c::value> sd(DIR_NUM);
+
+DIR_TRAFF upload;
+DIR_TRAFF download;
+DIR_TRAFF supload;
+DIR_TRAFF sdownload;
+download = iter->property.down.Get();
+upload = iter->property.up.Get();
+sdownload = iter->GetSessionUpload();
+supload = iter->GetSessionDownload();
+
+for (int j = 0; j < DIR_NUM; j++)
+ {
+ std::string value;
+ x2str(upload[j], value);
+ mu[j] = xmlrpc_c::value_string(value);
+ x2str(download[j], value);
+ md[j] = xmlrpc_c::value_string(value);
+ x2str(supload[j], value);
+ su[j] = xmlrpc_c::value_string(value);
+ x2str(sdownload[j], value);
+ sd[j] = xmlrpc_c::value_string(value);
+ }
+
+traffInfo["mu"] = xmlrpc_c::value_array(mu);
+traffInfo["md"] = xmlrpc_c::value_array(md);
+traffInfo["su"] = xmlrpc_c::value_array(su);
+traffInfo["sd"] = xmlrpc_c::value_array(sd);
+
+structVal["traff"] = xmlrpc_c::value_struct(traffInfo);
+
+structVal["down"] = xmlrpc_c::value_boolean(iter->property.disabled.Get());
+structVal["disableddetailstat"] = xmlrpc_c::value_boolean(iter->property.disabledDetailStat.Get());
+structVal["passive"] = xmlrpc_c::value_boolean(iter->property.passive.Get());
+structVal["lastcash"] = xmlrpc_c::value_double(iter->property.lastCashAdd.Get());
+structVal["lasttimecash"] = xmlrpc_c::value_int(iter->property.lastCashAddTime.Get());
+structVal["lastactivitytime"] = xmlrpc_c::value_int(iter->property.lastActivityTime.Get());
+structVal["creditexpire"] = xmlrpc_c::value_int(iter->property.creditExpire.Get());
+
+*info = xmlrpc_c::value_struct(structVal);
+}
+
+//------------------------------------------------------------------------------
+
+bool USER_HELPER::SetUserInfo(const xmlrpc_c::value & info,
+ const ADMIN & admin,
+ const std::string & login,
+ const BASE_STORE & store)
+{
+std::map<std::string, xmlrpc_c::value> structVal(
+ static_cast<std::map<std::string, xmlrpc_c::value> >(xmlrpc_c::value_struct(info))
+ );
+
+std::map<std::string, xmlrpc_c::value>::iterator it;
+
+if ((it = structVal.find("password")) != structVal.end())
+ {
+ bool res = iter->property.password.Set(xmlrpc_c::value_string(it->second),
+ admin,
+ login,
+ &store);
+ if (!res)
+ {
+ return true;
+ }
+ }
+
+if ((it = structVal.find("ips")) != structVal.end())
+ {
+ USER_IPS ips;
+ ips = StrToIPS(xmlrpc_c::value_string(it->second));
+ bool res = iter->property.ips.Set(ips,
+ admin,
+ login,
+ &store);
+ if (!res)
+ {
+ return true;
+ }
+ }
+
+if ((it = structVal.find("address")) != structVal.end())
+ {
+ bool res = iter->property.address.Set(IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "KOI8-R"),
+ admin,
+ login,
+ &store);
+ if (!res)
+ {
+ return true;
+ }
+ }
+
+if ((it = structVal.find("phone")) != structVal.end())
+ {
+ bool res = iter->property.phone.Set(IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "KOI8-R"),
+ admin,
+ login,
+ &store);
+ if (!res)
+ {
+ return true;
+ }
+ }
+
+if ((it = structVal.find("email")) != structVal.end())
+ {
+ bool res = iter->property.email.Set(IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "KOI8-R"),
+ admin,
+ login,
+ &store);
+ if (!res)
+ {
+ return true;
+ }
+ }
+
+if ((it = structVal.find("creditexpire")) != structVal.end())
+ {
+ bool res = iter->property.creditExpire.Set(xmlrpc_c::value_int(it->second),
+ admin,
+ login,
+ &store);
+ if (!res)
+ {
+ return true;
+ }
+ }
+
+if ((it = structVal.find("credit")) != structVal.end())
+ {
+ bool res = iter->property.credit.Set(xmlrpc_c::value_double(it->second),
+ admin,
+ login,
+ &store);
+ if (!res)
+ {
+ return true;
+ }
+ }
+
+if ((it = structVal.find("freemb")) != structVal.end())
+ {
+ bool res = iter->property.freeMb.Set(xmlrpc_c::value_double(it->second),
+ admin,
+ login,
+ &store);
+ if (!res)
+ {
+ return true;
+ }
+ }
+
+if ((it = structVal.find("disabled")) != structVal.end())
+ {
+ bool res = iter->property.disabled.Set(xmlrpc_c::value_boolean(it->second),
+ admin,
+ login,
+ &store);
+ if (!res)
+ {
+ return true;
+ }
+ }
+
+if ((it = structVal.find("passive")) != structVal.end())
+ {
+ bool res = iter->property.passive.Set(xmlrpc_c::value_boolean(it->second),
+ admin,
+ login,
+ &store);
+ if (!res)
+ {
+ return true;
+ }
+ }
+
+if ((it = structVal.find("aonline")) != structVal.end())
+ {
+ bool res = iter->property.alwaysOnline.Set(xmlrpc_c::value_boolean(it->second),
+ admin,
+ login,
+ &store);
+ if (!res)
+ {
+ return true;
+ }
+ }
+
+if ((it = structVal.find("disableddetailstat")) != structVal.end())
+ {
+ bool res = iter->property.disabledDetailStat.Set(xmlrpc_c::value_boolean(it->second),
+ admin,
+ login,
+ &store);
+ if (!res)
+ {
+ return true;
+ }
+ }
+
+if ((it = structVal.find("name")) != structVal.end())
+ {
+ bool res = iter->property.realName.Set(IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "KOI8-R"),
+ admin,
+ login,
+ &store);
+ if (!res)
+ {
+ return true;
+ }
+ }
+
+if ((it = structVal.find("group")) != structVal.end())
+ {
+ bool res = iter->property.group.Set(IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "KOI8-R"),
+ admin,
+ login,
+ &store);
+ if (!res)
+ {
+ return true;
+ }
+ }
+
+if ((it = structVal.find("note")) != structVal.end())
+ {
+ bool res = iter->property.note.Set(IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "KOI8-R"),
+ admin,
+ login,
+ &store);
+ if (!res)
+ {
+ return true;
+ }
+ }
+
+if ((it = structVal.find("userdata")) != structVal.end())
+ {
+ std::vector<USER_PROPERTY_LOGGED<string> *> userdata;
+ userdata.push_back(iter->property.userdata0.GetPointer());
+ userdata.push_back(iter->property.userdata1.GetPointer());
+ userdata.push_back(iter->property.userdata2.GetPointer());
+ userdata.push_back(iter->property.userdata3.GetPointer());
+ userdata.push_back(iter->property.userdata4.GetPointer());
+ userdata.push_back(iter->property.userdata5.GetPointer());
+ userdata.push_back(iter->property.userdata6.GetPointer());
+ userdata.push_back(iter->property.userdata7.GetPointer());
+ userdata.push_back(iter->property.userdata8.GetPointer());
+ userdata.push_back(iter->property.userdata9.GetPointer());
+
+ std::vector<xmlrpc_c::value> udata(
+ xmlrpc_c::value_array(it->second).vectorValueValue()
+ );
+
+ for (unsigned i = 0; i < userdata.size(); ++i)
+ {
+ bool res = userdata[i]->Set(IconvString(xmlrpc_c::value_string(udata[i]), "UTF-8", "KOI8-R"),
+ admin,
+ login,
+ &store);
+ if (!res)
+ {
+ return true;
+ }
+ }
+ }
+
+if ((it = structVal.find("traff")) != structVal.end())
+ {
+ std::map<std::string, xmlrpc_c::value> traff(
+ static_cast<std::map<std::string, xmlrpc_c::value> >(xmlrpc_c::value_struct(it->second))
+ );
+
+ std::vector<xmlrpc_c::value> data;
+ DIR_TRAFF dtData;
+ dtData = iter->property.up.Get();
+ if ((it = traff.find("mu")) != traff.end())
+ {
+ data = xmlrpc_c::value_array(it->second).vectorValueValue();
+
+ for (int i = 0; i < std::min(DIR_NUM, static_cast<int>(data.size())); ++i)
+ {
+ int64_t value;
+ if (str2x(xmlrpc_c::value_string(data[i]), value))
+ {
+ printfd(__FILE__, "USER_HELPER::SetUserInfo(): 'Invalid month upload value'\n");
+ }
+ else
+ {
+ dtData[i] = value;
+ }
+ }
+ bool res = iter->property.up.Set(dtData,
+ admin,
+ login,
+ &store);
+ if (!res)
+ {
+ return true;
+ }
+ }
+ dtData = iter->property.down.Get();
+ if ((it = traff.find("md")) != traff.end())
+ {
+ data = xmlrpc_c::value_array(it->second).vectorValueValue();
+
+ for (int i = 0; i < std::min(DIR_NUM, static_cast<int>(data.size())); ++i)
+ {
+ int64_t value;
+ if (str2x(xmlrpc_c::value_string(data[i]), value))
+ {
+ printfd(__FILE__, "USER_HELPER::SetUserInfo(): 'Invalid month download value'\n");
+ }
+ else
+ {
+ dtData[i] = value;
+ }
+ }
+ bool res = iter->property.down.Set(dtData,
+ admin,
+ login,
+ &store);
+ if (!res)
+ {
+ return true;
+ }
+ }
+ }
+
+return false;
+}
--- /dev/null
+#ifndef __USER_HELPER_H__
+#define __USER_HELPER_H__
+
+#include <string>
+
+#include <xmlrpc-c/base.hpp>
+#include "../../../users.h"
+#include "../../../admin.h"
+#include "base_store.h"
+
+class USER_HELPER
+{
+public:
+ USER_HELPER(user_iter & it)
+ : iter(it)
+ {
+ }
+
+ void GetUserInfo(xmlrpc_c::value * info,
+ bool hidePassword = false);
+ bool SetUserInfo(const xmlrpc_c::value & info,
+ const ADMIN & admin,
+ const std::string & login,
+ const BASE_STORE & store);
+private:
+ user_iter & iter;
+};
+
+#endif
--- /dev/null
+#include "users_methods.h"
+
+#include "rpcconfig.h"
+#include "user_helper.h"
+#include "user_ips.h"
+#include "utils.h"
+
+#include "common.h"
+
+//------------------------------------------------------------------------------
+
+void METHOD_USER_GET::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string login = paramList.getString(1);
+std::string enc;
+paramList.verifyEnd(2);
+
+std::map<std::string, xmlrpc_c::value> structVal;
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ structVal["result"] = xmlrpc_c::value_boolean(false);
+ *retvalPtr = xmlrpc_c::value_struct(structVal);
+ return;
+ }
+
+user_iter u;
+
+if (users->FindByName(login, &u))
+ {
+ structVal["result"] = xmlrpc_c::value_boolean(false);
+ *retvalPtr = xmlrpc_c::value_struct(structVal);
+ return;
+ }
+
+USER_HELPER uhelper(u);
+
+if (!adminInfo.priviledges.userConf || !adminInfo.priviledges.userPasswd)
+ {
+ uhelper.GetUserInfo(retvalPtr, true);
+ return;
+ }
+
+uhelper.GetUserInfo(retvalPtr);
+}
+
+//------------------------------------------------------------------------------
+
+void METHOD_USER_ADD::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string login = paramList.getString(1);
+std::string enc;
+paramList.verifyEnd(2);
+
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+ADMIN admin;
+
+if (admins->FindAdmin(adminInfo.admin, &admin))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+user_iter u;
+
+if (users->FindByName(login, &u))
+ {
+ if (users->Add(login, admin))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+ *retvalPtr = xmlrpc_c::value_boolean(true);
+ return;
+ }
+
+*retvalPtr = xmlrpc_c::value_boolean(false);
+return;
+}
+
+//------------------------------------------------------------------------------
+
+void METHOD_USER_DEL::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string login = paramList.getString(1);
+std::string enc;
+paramList.verifyEnd(2);
+
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+ADMIN admin;
+
+if (admins->FindAdmin(adminInfo.admin, &admin))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+user_iter u;
+
+if (users->FindByName(login, &u))
+ {
+ users->Del(login, admin);
+ *retvalPtr = xmlrpc_c::value_boolean(true);
+ return;
+ }
+
+*retvalPtr = xmlrpc_c::value_boolean(false);
+return;
+}
+
+//------------------------------------------------------------------------------
+
+void METHOD_USERS_GET::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string enc;
+paramList.verifyEnd(1);
+
+std::map<std::string, xmlrpc_c::value> structVal;
+std::vector<xmlrpc_c::value> retval;
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ structVal["result"] = xmlrpc_c::value_boolean(false);
+ *retvalPtr = xmlrpc_c::value_struct(structVal);
+ return;
+ }
+
+bool hidePassword = !adminInfo.priviledges.userConf ||
+ !adminInfo.priviledges.userPasswd;
+
+user_iter u;
+
+int h = users->OpenSearch();
+if (!h)
+ {
+ printfd(__FILE__, "users->OpenSearch() error\n");
+ users->CloseSearch(h);
+ return;
+ }
+
+while (1)
+ {
+ if (users->SearchNext(h, &u))
+ {
+ break;
+ }
+
+ xmlrpc_c::value info;
+
+ USER_HELPER uhelper(u);
+
+ uhelper.GetUserInfo(&info, hidePassword);
+
+ retval.push_back(info);
+ }
+
+*retvalPtr = xmlrpc_c::value_array(retval);
+}
+
+//------------------------------------------------------------------------------
+
+void METHOD_USER_CHG::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string login = paramList.getString(1);
+xmlrpc_c::value_struct info(paramList.getStruct(2));
+std::string enc;
+paramList.verifyEnd(3);
+
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+ADMIN admin;
+
+if (admins->FindAdmin(adminInfo.admin, &admin))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+user_iter u;
+
+if (users->FindByName(login, &u))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+USER_HELPER uhelper(u);
+
+if (!adminInfo.priviledges.userConf || !adminInfo.priviledges.userPasswd)
+ {
+ uhelper.SetUserInfo(info, admin, login, *store);
+ }
+else
+ {
+ uhelper.SetUserInfo(info, admin, login, *store);
+ }
+
+u->WriteConf();
+u->WriteStat();
+
+*retvalPtr = xmlrpc_c::value_boolean(true);
+}
+
+//------------------------------------------------------------------------------
+
+void METHOD_USER_CASH_ADD::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string login = paramList.getString(1);
+double amount = paramList.getDouble(2);
+std::string comment = IconvString(paramList.getString(3), "UTF-8", "KOI8-R");
+std::string enc;
+paramList.verifyEnd(4);
+
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+ADMIN admin;
+
+if (admins->FindAdmin(adminInfo.admin, &admin))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+user_iter u;
+
+if (users->FindByName(login, &u))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+double cash = u->property.cash.Get();
+cash += amount;
+
+if (!u->property.cash.Set(cash, admin, login, store, comment))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+u->WriteStat();
+
+*retvalPtr = xmlrpc_c::value_boolean(true);
+}
+
+//------------------------------------------------------------------------------
+
+void METHOD_USER_CASH_SET::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string login = paramList.getString(1);
+double cash = paramList.getDouble(2);
+std::string comment = IconvString(paramList.getString(3), "UTF-8", "KOI8-R");
+std::string enc;
+paramList.verifyEnd(4);
+
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+ADMIN admin;
+
+if (admins->FindAdmin(adminInfo.admin, &admin))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+user_iter u;
+
+if (users->FindByName(login, &u))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+if (!u->property.cash.Set(cash, admin, login, store, comment))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+u->WriteStat();
+
+*retvalPtr = xmlrpc_c::value_boolean(true);
+}
+
+//------------------------------------------------------------------------------
+
+void METHOD_USER_TARIFF_CHANGE::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string login = paramList.getString(1);
+std::string tariff = paramList.getString(2);
+bool delayed = paramList.getBoolean(3);
+std::string comment = IconvString(paramList.getString(4), "UTF-8", "KOI8-R");
+std::string enc;
+paramList.verifyEnd(5);
+
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+ADMIN admin;
+
+if (admins->FindAdmin(adminInfo.admin, &admin))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+user_iter u;
+
+if (users->FindByName(login, &u))
+ {
+ *retvalPtr = xmlrpc_c::value_boolean(false);
+ return;
+ }
+
+if (tariffs->FindByName(tariff))
+ {
+ if (delayed)
+ {
+ if (u->property.nextTariff.Set(tariff,
+ admin,
+ login,
+ store))
+ {
+ u->WriteConf();
+ *retvalPtr = xmlrpc_c::value_boolean(true);
+ return;
+ }
+ }
+ if (u->property.tariffName.Set(tariff,
+ admin,
+ login,
+ store))
+ {
+ u->WriteConf();
+ *retvalPtr = xmlrpc_c::value_boolean(true);
+ return;
+ }
+ }
+
+*retvalPtr = xmlrpc_c::value_boolean(false);
+}
+
+//------------------------------------------------------------------------------
+
+void METHOD_GET_ONLINE_IPS::execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::vector<xmlrpc_c::value> subnetsStr = paramList.getArray(1);
+paramList.verifyEnd(2);
+
+std::vector<IP_MASK> subnets;
+
+std::vector<xmlrpc_c::value>::iterator it;
+
+for (it = subnetsStr.begin(); it != subnetsStr.end(); ++it)
+ {
+ IP_MASK ipm;
+ if (ParseNet(xmlrpc_c::value_string(*it), ipm))
+ {
+ printfd(__FILE__, "METHOD_GET_ONLINE_IPS::execute(): Failed to parse subnet ('%s')\n", std::string(xmlrpc_c::value_string(*it)).c_str());
+ }
+ else
+ {
+ subnets.push_back(ipm);
+ }
+ }
+
+std::map<std::string, xmlrpc_c::value> structVal;
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+ {
+ structVal["result"] = xmlrpc_c::value_boolean(false);
+ *retvalPtr = xmlrpc_c::value_struct(structVal);
+ return;
+ }
+
+std::vector<xmlrpc_c::value> ips;
+
+user_iter u;
+
+int handle = users->OpenSearch();
+if (!handle)
+ {
+ printfd(__FILE__, "users->OpenSearch() error\n");
+ users->CloseSearch(handle);
+ return;
+ }
+
+while (1)
+ {
+ if (users->SearchNext(handle, &u))
+ {
+ break;
+ }
+
+ if (u->GetAuthorized())
+ {
+ uint32_t ip = u->GetCurrIP();
+
+ std::vector<IP_MASK>::iterator it;
+ for (it = subnets.begin(); it != subnets.end(); ++it)
+ {
+ if ((it->ip & it->mask) == (ip & it->mask))
+ {
+ ips.push_back(xmlrpc_c::value_string(inet_ntostring(u->GetCurrIP())));
+ break;
+ }
+ }
+ }
+ }
+
+structVal["ips"] = xmlrpc_c::value_array(ips);
+
+*retvalPtr = xmlrpc_c::value_struct(structVal);
+}
+
+bool METHOD_GET_ONLINE_IPS::ParseNet(const std::string & net, IP_MASK & ipm) const
+{
+size_t pos = net.find_first_of('/');
+
+if (pos == std::string::npos)
+ {
+ printfd(__FILE__, "METHOD_GET_ONLINE_IPS::ParseNet(): Network address is not in CIDR-notation\n");
+ return true;
+ }
+
+int res = inet_pton(AF_INET, net.substr(0, pos).c_str(), &ipm.ip);
+
+if (res < 0)
+ {
+ printfd(__FILE__, "METHOD_GET_ONLINE_IPS::ParseNet(): '%s'\n", strerror(errno));
+ return true;
+ }
+else if (res == 0)
+ {
+ printfd(__FILE__, "METHOD_GET_ONLINE_IPS::ParseNet(): Invalid network address\n", strerror(errno));
+ return true;
+ }
+
+if (str2x(net.substr(pos + 1, net.length() - pos - 1), ipm.mask))
+ {
+ printfd(__FILE__, "METHOD_GET_ONLINE_IPS::ParseNet(): Invalid network mask\n");
+ return true;
+ }
+if (ipm.mask > 32)
+ {
+ printfd(__FILE__, "METHOD_GET_ONLINE_IPS::ParseNet(): Network mask is out of range\n");
+ return true;
+ }
+ipm.mask = htonl(0xffFFffFF << (32 - ipm.mask));
+
+return false;
+}
--- /dev/null
+#ifndef __USERS_METHODS_H__
+#define __USERS_METHODS_H__
+
+#include <xmlrpc-c/base.hpp>
+#include <xmlrpc-c/registry.hpp>
+
+#include "../../../users.h"
+#include "../../../user.h"
+
+class RPC_CONFIG;
+
+class METHOD_USER_GET : public xmlrpc_c::method {
+public:
+ METHOD_USER_GET(RPC_CONFIG * c,
+ USERS * u)
+ : config(c),
+ users(u)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalP);
+private:
+ RPC_CONFIG * config;
+ USERS * users;
+};
+
+class METHOD_USER_ADD : public xmlrpc_c::method {
+public:
+ METHOD_USER_ADD(RPC_CONFIG * c,
+ ADMINS * a,
+ USERS * u)
+ : config(c),
+ admins(a),
+ users(u)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalP);
+private:
+ RPC_CONFIG * config;
+ ADMINS * admins;
+ USERS * users;
+};
+
+class METHOD_USER_DEL : public xmlrpc_c::method {
+public:
+ METHOD_USER_DEL(RPC_CONFIG * c,
+ ADMINS * a,
+ USERS * u)
+ : config(c),
+ admins(a),
+ users(u)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalP);
+private:
+ RPC_CONFIG * config;
+ ADMINS * admins;
+ USERS * users;
+};
+
+class METHOD_USERS_GET : public xmlrpc_c::method {
+public:
+ METHOD_USERS_GET(RPC_CONFIG * c,
+ USERS * u)
+ : config(c),
+ users(u)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalP);
+private:
+ RPC_CONFIG * config;
+ USERS * users;
+};
+
+class METHOD_USER_CHG : public xmlrpc_c::method {
+public:
+ METHOD_USER_CHG(RPC_CONFIG * c,
+ ADMINS * a,
+ BASE_STORE * s,
+ USERS * u)
+ : config(c),
+ admins(a),
+ store(s),
+ users(u)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalP);
+private:
+ RPC_CONFIG * config;
+ ADMINS * admins;
+ BASE_STORE * store;
+ USERS * users;
+};
+
+class METHOD_USER_CASH_ADD : public xmlrpc_c::method {
+public:
+ METHOD_USER_CASH_ADD(RPC_CONFIG * c,
+ ADMINS * a,
+ BASE_STORE * s,
+ USERS * u)
+ : config(c),
+ admins(a),
+ store(s),
+ users(u)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalP);
+private:
+ RPC_CONFIG * config;
+ ADMINS * admins;
+ BASE_STORE * store;
+ USERS * users;
+};
+
+class METHOD_USER_CASH_SET : public xmlrpc_c::method {
+public:
+ METHOD_USER_CASH_SET(RPC_CONFIG * c,
+ ADMINS * a,
+ BASE_STORE * s,
+ USERS * u)
+ : config(c),
+ admins(a),
+ store(s),
+ users(u)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalP);
+private:
+ RPC_CONFIG * config;
+ ADMINS * admins;
+ BASE_STORE * store;
+ USERS * users;
+};
+
+class METHOD_USER_TARIFF_CHANGE : public xmlrpc_c::method {
+public:
+ METHOD_USER_TARIFF_CHANGE(RPC_CONFIG * c,
+ ADMINS * a,
+ TARIFFS * t,
+ BASE_STORE * s,
+ USERS * u)
+ : config(c),
+ admins(a),
+ tariffs(t),
+ store(s),
+ users(u)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalP);
+private:
+ RPC_CONFIG * config;
+ ADMINS * admins;
+ TARIFFS * tariffs;
+ BASE_STORE * store;
+ USERS * users;
+};
+
+class METHOD_GET_ONLINE_IPS : public xmlrpc_c::method {
+public:
+ METHOD_GET_ONLINE_IPS(RPC_CONFIG * c,
+ USERS * u)
+ : config(c),
+ users(u)
+ {
+ }
+
+ void execute(xmlrpc_c::paramList const & paramList,
+ xmlrpc_c::value * const retvalP);
+private:
+ RPC_CONFIG * config;
+ USERS * users;
+
+ bool ParseNet(const std::string & net, IP_MASK & ipm) const;
+};
+
+#endif
--- /dev/null
+#include <string>
+#include <cerrno>
+#include <cstring>
+#include <iconv.h>
+
+#include "utils.h"
+#include "common.h"
+
+//-----------------------------------------------------------------------------
+std::string IconvString(const std::string & src,
+ const std::string & from,
+ const std::string & to)
+{
+if (src.empty())
+ return std::string();
+
+size_t inBytesLeft = src.length() + 1;
+size_t outBytesLeft = src.length() * 2 + 1;
+
+char * inBuf = new char[inBytesLeft];
+char * outBuf = new char[outBytesLeft];
+
+strncpy(inBuf, src.c_str(), src.length());
+
+inBuf[src.length()] = 0;
+
+#if defined(FREE_BSD) || defined(FREE_BSD5)
+const char * srcPos = inBuf;
+#else
+char * srcPos = inBuf;
+#endif
+char * dstPos = outBuf;
+
+iconv_t handle = iconv_open(to.c_str(),
+ from.c_str());
+
+if (handle == iconv_t(-1))
+ {
+ if (errno == EINVAL)
+ {
+ printfd(__FILE__, "IconvString(): iconv from %s to %s failed\n", from.c_str(), to.c_str());
+ delete[] outBuf;
+ delete[] inBuf;
+ return src;
+ }
+ else
+ printfd(__FILE__, "IconvString(): iconv_open error\n");
+
+ delete[] outBuf;
+ delete[] inBuf;
+ return src;
+ }
+
+size_t res = iconv(handle,
+ &srcPos, &inBytesLeft,
+ &dstPos, &outBytesLeft);
+
+if (res == size_t(-1))
+ {
+ printfd(__FILE__, "IconvString(): '%s'\n", strerror(errno));
+
+ iconv_close(handle);
+ delete[] outBuf;
+ delete[] inBuf;
+ return src;
+ }
+
+dstPos = 0;
+
+std::string dst(outBuf);
+
+iconv_close(handle);
+
+delete[] outBuf;
+delete[] inBuf;
+
+return dst;
+}
--- /dev/null
+#ifndef __UTILS_H__
+#define __UTILS_H__
+
+#include <string>
+
+std::string IconvString(const std::string & src,
+ const std::string & from = "UTF-8",
+ const std::string & to = "KOI8-R");
+
+#endif
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.11 2010/03/04 10:47:45 faust Exp $
+###############################################################################
+
+include ../../../../../Makefile.conf
+
+PROG = mod_conf_sg.so
+
+SRCS = ./stgconfig.cpp \
+ ./rsconf.cpp \
+ ./configproto.cpp \
+ ./parser.cpp \
+ ./parser_tariff.cpp \
+ ./parser_admin.cpp
+
+LIBS += -lexpat \
+ $(LIB_THREAD)
+
+STGLIBS = -lstg_common -lstg_logger -lstg_crypto
+
+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
+ */
+
+/*
+ * Date: 27.10.2002
+ */
+
+/*
+ * Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+ /*
+ $Revision: 1.22 $
+ $Date: 2010/10/04 20:24:14 $
+ $Author: faust $
+ */
+
+
+#include <unistd.h>
+
+#include "configproto.h"
+
+//-----------------------------------------------------------------------------
+void ParseXMLStart(void *data, const char *el, const char **attr)
+{
+CONFIGPROTO * cp = static_cast<CONFIGPROTO *>(data);
+
+if (cp->currParser)
+ {
+ cp->currParser->SetAnswerList(&cp->answerList);
+ cp->currParser->SetCurrAdmin(cp->currAdmin);
+ cp->currParser->ParseStart(data, el, attr);
+ }
+else
+ {
+ for (unsigned int i = 0; i < cp->dataParser.size(); i++)
+ {
+ cp->dataParser[i]->SetAnswerList(&cp->answerList);
+ //cp->currAdmin->SetAdminIP(cp->GetAdminIP());
+ cp->dataParser[i]->SetCurrAdmin(cp->currAdmin);
+ cp->dataParser[i]->Reset();
+ if (cp->dataParser[i]->ParseStart(data, el, attr) == 0)
+ {
+ cp->currParser = cp->dataParser[i];
+ break;
+ }
+ else
+ {
+ cp->dataParser[i]->Reset();
+ }
+ }
+ }
+}
+//-----------------------------------------------------------------------------
+void ParseXMLEnd(void *data, const char *el)
+{
+CONFIGPROTO * cp = static_cast<CONFIGPROTO *>(data);
+if (cp->currParser)
+ {
+ if (cp->currParser->ParseEnd(data, el) == 0)
+ {
+ cp->currParser = NULL;
+ }
+ }
+else
+ {
+ for (unsigned int i = 0; i < cp->dataParser.size(); i++)
+ {
+ if (cp->dataParser[i]->ParseEnd(data, el) == 0)
+ {
+ break;
+ }
+ }
+ }
+}
+//-----------------------------------------------------------------------------
+CONFIGPROTO::CONFIGPROTO()
+ : adminIP(0),
+ port(0),
+ nonstop(1),
+ state(0),
+ currAdmin(),
+ WriteServLog(GetStgLogger()),
+ outerSocket(0),
+ listenSocket(0),
+ admins(NULL),
+ //users(NULL),
+ //tariffs(NULL),
+ //store(NULL),
+ //settings(NULL),
+ currParser(NULL)
+{
+dataParser.push_back(&parserGetServInfo);
+
+dataParser.push_back(&parserGetUsers);
+dataParser.push_back(&parserGetUser);
+dataParser.push_back(&parserChgUser);
+dataParser.push_back(&parserAddUser);
+dataParser.push_back(&parserDelUser);
+dataParser.push_back(&parserCheckUser);
+dataParser.push_back(&parserSendMessage);
+
+dataParser.push_back(&parserGetTariffs);
+dataParser.push_back(&parserAddTariff);
+dataParser.push_back(&parserDelTariff);
+dataParser.push_back(&parserChgTariff);
+
+dataParser.push_back(&parserGetAdmins);
+dataParser.push_back(&parserChgAdmin);
+dataParser.push_back(&parserDelAdmin);
+dataParser.push_back(&parserAddAdmin);
+
+xmlParser = XML_ParserCreate(NULL);
+
+if (!xmlParser)
+ {
+ WriteServLog("Couldn't allocate memory for parser.");
+ exit(1);
+ }
+
+//XML_SetElementHandler(parser, ParseXMLStart, ParseXMLEnd);
+}
+//-----------------------------------------------------------------------------
+CONFIGPROTO::~CONFIGPROTO()
+{
+XML_ParserFree(xmlParser);
+}
+//-----------------------------------------------------------------------------
+int CONFIGPROTO::ParseCommand()
+{
+list<string>::iterator n;
+int done = 0;
+char str[9];
+int len;
+
+if (requestList.empty())
+ return 0;
+
+n = requestList.begin();
+
+strncpy(str, (*n).c_str(), 8);
+str[8] = 0;
+
+XML_ParserReset(xmlParser, NULL);
+XML_SetElementHandler(xmlParser, ParseXMLStart, ParseXMLEnd);
+XML_SetUserData(xmlParser, this);
+
+while(nonstop)
+ {
+ strncpy(str, (*n).c_str(), 8);
+ str[8] = 0;
+ len = strlen(str);
+
+ n++;
+ if (n == requestList.end())
+ done = 1;
+ n--;
+
+ if (XML_Parse(xmlParser, (*n).c_str(), len, done) == XML_STATUS_ERROR)
+ {
+ WriteServLog("Invalid configuration request");
+ printfd(__FILE__, "Parse error at line %d:\n%s\n",
+ XML_GetCurrentLineNumber(xmlParser),
+ XML_ErrorString(XML_GetErrorCode(xmlParser)));
+ if (currParser)
+ {
+ printfd(__FILE__, "Parser reset\n");
+ currParser->Reset();
+ currParser = NULL;
+ }
+
+ return -1;
+ }
+
+ if (done)
+ return 0;
+
+ n++;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+void CONFIGPROTO::SetPort(uint16_t p)
+{
+port = p;
+}
+//-----------------------------------------------------------------------------
+/*void CONFIGPROTO::SetHostAllow(HOSTALLOW *)
+{
+//hostAllow = ha;
+}*/
+//-----------------------------------------------------------------------------
+void CONFIGPROTO::SetAdmins(ADMINS * a)
+{
+admins = a;
+for (unsigned int i = 0; i < dataParser.size(); i++)
+ {
+ dataParser[i]->SetAdmins(a);
+ }
+
+}
+//-----------------------------------------------------------------------------
+void CONFIGPROTO::SetUsers(USERS * u)
+{
+//users = u;
+for (unsigned int i = 0; i < dataParser.size(); i++)
+ {
+ dataParser[i]->SetUsers(u);
+ }
+
+}
+//-----------------------------------------------------------------------------
+void CONFIGPROTO::SetTariffs(TARIFFS * t)
+{
+//tariffs = t;
+for (unsigned int i = 0; i < dataParser.size(); i++)
+ {
+ dataParser[i]->SetTariffs(t);
+ }
+}
+//-----------------------------------------------------------------------------
+void CONFIGPROTO::SetStore(BASE_STORE * s)
+{
+//store = s;
+for (unsigned int i = 0; i < dataParser.size(); i++)
+ {
+ dataParser[i]->SetStore(s);
+ }
+}
+//-----------------------------------------------------------------------------
+void CONFIGPROTO::SetStgSettings(const SETTINGS * s)
+{
+//settings = s;
+for (unsigned int i = 0; i < dataParser.size(); i++)
+ {
+ dataParser[i]->SetStgSettings(s);
+ }
+}
+//-----------------------------------------------------------------------------
+/*void CONFIGPROTO::Start()
+{
+finished = false;
+threadExited = false;
+status = starting;
+
+xmlParser = XML_ParserCreate(NULL);
+
+if (!xmlParser)
+ {
+ WriteServLog("Couldn't allocate memory for parser.");
+ }
+
+pthread_create(&thrReciveSendConf, NULL, ReciveSendConf, this);
+status = started;
+}*/
+//-----------------------------------------------------------------------------
+/*int CONFIGPROTO::Stop()
+{
+nonstop = true;
+close(outerSocket);
+return 0;
+}*/
+//-----------------------------------------------------------------------------
+/*void CONFIGPROTO::Restart()
+{
+//Stop();
+//Start();
+}*/
+//-----------------------------------------------------------------------------
+/*CONF_STATUS CONFIGPROTO::Status()
+{
+//return status;
+}
+//-----------------------------------------------------------------------------
+*/
+const string & CONFIGPROTO::GetStrError()
+{
+return errorStr;
+}
+//-----------------------------------------------------------------------------
+uint32_t CONFIGPROTO::GetAdminIP()
+{
+return adminIP;
+}
+//-----------------------------------------------------------------------------
--- /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>
+ */
+
+ /*
+ $Revision: 1.14 $
+ $Date: 2010/10/04 20:24:14 $
+ $Author: faust $
+ */
+
+
+#ifndef CONFIGPROTO_H
+#define CONFIGPROTO_H
+
+#include <expat.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <string>
+
+#include "parser.h"
+#include "../../../users.h"
+#include "../../../admins.h"
+#include "../../../tariffs.h"
+#include "stg_logger.h"
+
+using namespace std;
+
+#define STG_HEADER "SG04"
+#define OK_HEADER "OKHD"
+#define ERR_HEADER "ERHD"
+#define OK_LOGIN "OKLG"
+#define ERR_LOGIN "ERLG"
+#define OK_LOGINS "OKLS"
+#define ERR_LOGINS "ERLS"
+
+//-----------------------------------------------------------------------------
+class CONFIGPROTO
+{
+public:
+ CONFIGPROTO();
+ ~CONFIGPROTO();
+
+ void SetPort(uint16_t port);
+ //void SetHostAllow(HOSTALLOW * ha);
+ void SetAdmins(ADMINS * a);
+ void SetUsers(USERS * u);
+ void SetTariffs(TARIFFS * t);
+ void SetStore(BASE_STORE * s);
+ void SetStgSettings(const SETTINGS * s);
+ const string & GetAdminLogin();
+ uint32_t GetAdminIP();
+ int Prepare();
+ int Stop();
+ const string & GetStrError();
+ static void * Run(void * a);
+
+private:
+ int RecvHdr(int sock);
+ int RecvLogin(int sock);
+ int SendLoginAnswer(int sock, int err);
+ int SendHdrAnswer(int sock, int err);
+ int RecvLoginS(int sock);
+ int SendLoginSAnswer(int sock, int err);
+ int RecvData(int sock);
+ int SendDataAnswer(int sock);
+ void SendError(const char * text);
+ void WriteLogAccessFailed(uint32_t ip);
+
+ int ParseCommand();
+
+ list<string> answerList;
+ list<string> requestList;
+ uint32_t adminIP;
+ string adminLogin;
+ uint16_t port;
+ pthread_t thrReciveSendConf;
+ bool nonstop;
+ int state;
+ //HOSTALLOW * hostAllow;
+ ADMIN currAdmin;
+ STG_LOGGER & WriteServLog;
+
+ int outerSocket;
+ int listenSocket;
+ struct sockaddr_in outerAddr;
+ socklen_t outerAddrLen;
+
+ PARSER_GET_SERVER_INFO parserGetServInfo;
+
+ PARSER_GET_USERS parserGetUsers;
+ PARSER_GET_USER parserGetUser;
+ PARSER_CHG_USER parserChgUser;
+ PARSER_ADD_USER parserAddUser;
+ PARSER_DEL_USER parserDelUser;
+ PARSER_CHECK_USER parserCheckUser;
+ PARSER_SEND_MESSAGE parserSendMessage;
+
+ PARSER_GET_ADMINS parserGetAdmins;
+ PARSER_ADD_ADMIN parserAddAdmin;
+ PARSER_DEL_ADMIN parserDelAdmin;
+ PARSER_CHG_ADMIN parserChgAdmin;
+
+ PARSER_GET_TARIFFS parserGetTariffs;
+ PARSER_ADD_TARIFF parserAddTariff;
+ PARSER_DEL_TARIFF parserDelTariff;
+ PARSER_CHG_TARIFF parserChgTariff;
+
+ ADMINS * admins;
+ //USERS * users;
+ //TARIFFS * tariffs;
+ //BASE_STORE * store;
+ //const SETTINGS * settings;
+
+ BASE_PARSER * currParser;
+ vector<BASE_PARSER*> dataParser;
+
+ XML_Parser xmlParser;
+
+ string errorStr;
+
+ friend void ParseXMLStart(void *data, const char *el, const char **attr);
+ friend void ParseXMLEnd(void *data, const char *el);
+};
+//-----------------------------------------------------------------------------
+#endif //CONFIGPROTO_H
+
--- /dev/null
+#include <unistd.h>
+#include "net_configurator.h"
+#include "../../internal_configurator.h"
+
+//-----------------------------------------------------------------------------
+const string & NET_CONFIGURATOR_SETTINGS::GetStrError()
+{
+return strError;
+}
+//-----------------------------------------------------------------------------
+int NET_CONFIGURATOR_SETTINGS::ReadSettings(const CONFIGFILE &cf)
+{
+if (cf.ReadUShortInt("AdminPort", &port, 5555) != 0)
+ {
+ strError = "Cannot read parameter AdminPort.";
+ return -1;
+ }
+if (port < 1 || port > 65535)
+ {
+ strError = "Incorrect value AdminPort.";
+ return -1;
+ }
+
+string strOrder;
+cf.ReadString("AdminOrder", &strOrder, "allow,deny");
+if (hostAllow.ParseOrder(strOrder.c_str()) < 0)
+ {
+ strError = string("Error in parameter AdminOrder. ") + hostAllow.GetStrError();
+ return -1;
+ }
+
+string strAllow;
+cf.ReadString("AdminAllowFrom", &strAllow, "all");
+if (hostAllow.ParseHosts(strAllow.c_str(), hostsAllow) != 0)
+ {
+ strError = string("Error in parameter AdminAllowFrom. ") + hostAllow.GetStrError();
+ return -1;
+ }
+
+string strDeny;
+cf.ReadString("AdminDenyFrom", &strDeny, "");
+if (hostAllow.ParseHosts(strDeny.c_str(), hostsDeny) != 0)
+ {
+ strError = string("Error in parameter AdminDenyFrom. ") + hostAllow.GetStrError();
+ return -1;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+uint16_t NET_CONFIGURATOR_SETTINGS::GetPort()
+{
+return port;
+}
+//-----------------------------------------------------------------------------
+HOSTALLOW * NET_CONFIGURATOR_SETTINGS::GetHostAllow()
+{
+return &hostAllow;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+NET_CONFIGURATOR::NET_CONFIGURATOR()
+{
+hostAllow = settings.GetHostAllow();
+}
+//-----------------------------------------------------------------------------
+NET_CONFIGURATOR::~NET_CONFIGURATOR()
+{
+
+}
+//-----------------------------------------------------------------------------
+void NET_CONFIGURATOR::SetStgConfigurator(BASE_INT_CONFIGURATOR * bsc)
+{
+stgConfigurator = bsc;
+cp.SetStgConfigurator(stgConfigurator);
+}
+//-----------------------------------------------------------------------------
+int NET_CONFIGURATOR::UserGetAll(string * login,
+ USER_CONF_RES * conf,
+ USER_STAT_RES * stat,
+ time_t lastUpdate)
+{
+return 0;
+}
+//-----------------------------------------------------------------------------
+int NET_CONFIGURATOR::TatiffGetAll(TARIFF_CONF * conf)
+{
+return 0;
+}
+//-----------------------------------------------------------------------------
+int NET_CONFIGURATOR::AdminGetAll(ADMIN_CONF * conf)
+{
+return 0;
+}
+//-----------------------------------------------------------------------------
+const string & NET_CONFIGURATOR::GetStrError()
+{
+return strError;
+}
+//-----------------------------------------------------------------------------
+void NET_CONFIGURATOR::Start()
+{
+cp.SetPort(settings.GetPort());
+cp.SetHostAllow(settings.GetHostAllow());
+cp.Start();
+}
+//-----------------------------------------------------------------------------
+void NET_CONFIGURATOR::Stop()
+{
+cp.Stop();
+}
+//-----------------------------------------------------------------------------
+void NET_CONFIGURATOR::Restart()
+{
+cp.Restart();
+}
+//-----------------------------------------------------------------------------
+CONF_STATUS NET_CONFIGURATOR::Status()
+{
+return cp.Status();
+}
+//-----------------------------------------------------------------------------
+BASE_SETTINGS * NET_CONFIGURATOR::GetConfiguratorSettings()
+{
+return &settings;
+}
+//-----------------------------------------------------------------------------
+void NET_CONFIGURATOR::SetAdmins(const ADMINS * a)
+{
+cp.SetAdmins(a);
+}
+//-----------------------------------------------------------------------------
+
--- /dev/null
+ /*
+ $Revision: 1.2 $
+ $Date: 2005/10/30 21:34:28 $
+ */
+
+#ifndef NET_CONFIGURATOR_H
+#define NET_CONFIGURATOR_H
+
+#include <time.h>
+#include <string>
+
+#include "../../base_ext_configurator.h"
+#include "../../base_int_configurator.h"
+#include "../../base_settings.h"
+#include "hostallow.h"
+#include "conffiles.h"
+#include "configproto.h"
+
+using namespace std;
+//-----------------------------------------------------------------------------
+class NET_CONFIGURATOR_SETTINGS: public BASE_SETTINGS
+{
+public:
+ virtual ~NET_CONFIGURATOR_SETTINGS(){};
+virtual const string & GetStrError();
+ virtual int ReadSettings(const CONFIGFILE & cf);
+ uint16_t GetPort();
+ HOSTALLOW * GetHostAllow();
+
+private:
+ string strError;
+ uint16_t port;
+ HOSTALLOW hostAllow;
+};
+//-----------------------------------------------------------------------------
+class NET_CONFIGURATOR: public BASE_EXT_CONFIGURATOR
+{
+public:
+ NET_CONFIGURATOR();
+ virtual ~NET_CONFIGURATOR();
+ virtual void SetStgConfigurator(BASE_INT_CONFIGURATOR *);
+ virtual int UserGetAll(string * login,
+ USER_CONF_RES * conf,
+ USER_STAT_RES * stat,
+ time_t lastUpdate);
+ virtual int TatiffGetAll(TARIFF_CONF * conf);
+ virtual int AdminGetAll(ADMIN_CONF * conf);
+ virtual const string & GetStrError();
+ virtual void Start();
+ virtual void Stop();
+ virtual void Restart();
+ virtual CONF_STATUS Status();
+ virtual BASE_SETTINGS * GetConfiguratorSettings();
+ virtual void SetAdmins(const ADMINS * a);
+
+private:
+ HOSTALLOW * hostAllow;
+ BASE_INT_CONFIGURATOR * stgConfigurator;
+ NET_CONFIGURATOR_SETTINGS settings;
+ string strError;
+ CONFIGPROTO cp;
+};
+//-----------------------------------------------------------------------------
+#endif //NET_CONFIGURATOR_H
+
--- /dev/null
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+#include <sys/utsname.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sstream>
+
+#include "parser.h"
+#include "version.h"
+
+#define UNAME_LEN (256)
+//-----------------------------------------------------------------------------
+// GET SERVER INFO
+//-----------------------------------------------------------------------------
+int PARSER_GET_SERVER_INFO::ParseStart(void *, const char *el, const char **)
+{
+answerList->erase(answerList->begin(), answerList->end());
+if (strcasecmp(el, "GetServerInfo") == 0)
+ {
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int PARSER_GET_SERVER_INFO::ParseEnd(void *, const char *el)
+{
+if (strcasecmp(el, "GetServerInfo") == 0)
+ {
+ CreateAnswer();
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+void PARSER_GET_SERVER_INFO::CreateAnswer()
+{
+char s[UNAME_LEN + 128];
+char un[UNAME_LEN];
+struct utsname utsn;
+
+int tariff_type;
+
+tariff_type = 2;
+
+uname(&utsn);
+un[0] = 0;
+
+strcat(un, utsn.sysname);
+strcat(un, " ");
+strcat(un, utsn.release);
+strcat(un, " ");
+strcat(un, utsn.machine);
+strcat(un, " ");
+strcat(un, utsn.nodename);
+
+//answerList->clear();
+answerList->erase(answerList->begin(), answerList->end());
+answerList->push_back("<ServerInfo>");
+
+sprintf(s, "<version value=\"%s\"/>", SERVER_VERSION);
+answerList->push_back(s);
+
+sprintf(s, "<tariff_num value=\"%d\"/>", tariffs->GetTariffsNum());
+answerList->push_back(s);
+
+sprintf(s, "<tariff value=\"%d\"/>", 2);
+answerList->push_back(s);
+
+sprintf(s, "<users_num value=\"%d\"/>", users->GetUserNum());
+answerList->push_back(s);
+
+sprintf(s, "<uname value=\"%s\"/>", un);
+answerList->push_back(s);
+
+sprintf(s, "<dir_num value=\"%d\"/>", DIR_NUM);
+answerList->push_back(s);
+
+sprintf(s, "<day_fee value=\"%d\"/>", settings->GetDayFee());
+answerList->push_back(s);
+
+for (int i = 0; i< DIR_NUM; i++)
+ {
+ string dn2e;
+ Encode12str(dn2e, settings->GetDirName(i));
+ sprintf(s, "<dir_name_%d value=\"%s\"/>", i, dn2e.c_str());
+ answerList->push_back(s);
+ }
+
+answerList->push_back("</ServerInfo>");
+}
+//-----------------------------------------------------------------------------
+// GET USER
+//-----------------------------------------------------------------------------
+PARSER_GET_USER::PARSER_GET_USER()
+{
+
+}
+//-----------------------------------------------------------------------------
+int PARSER_GET_USER::ParseStart(void *, const char *el, const char **attr)
+{
+if (strcasecmp(el, "GetUser") == 0)
+ {
+ if (attr[0] && attr[1])
+ login = attr[1];
+ else
+ {
+ //login.clear();
+ login.erase(login.begin(), login.end());
+ return -1;
+ }
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int PARSER_GET_USER::ParseEnd(void *, const char *el)
+{
+if (strcasecmp(el, "GetUser") == 0)
+ {
+ CreateAnswer();
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+void PARSER_GET_USER::CreateAnswer()
+{
+string s;
+string enc;
+
+user_iter u;
+
+answerList->erase(answerList->begin(), answerList->end());
+
+if (users->FindByName(login, &u))
+ {
+ s = "<user result=\"error\"/>";
+ answerList->push_back(s);
+ return;
+ }
+
+s = "<user result=\"ok\">";
+answerList->push_back(s);
+
+s = "<login value=\"" + u->GetLogin() + "\"/>";
+answerList->push_back(s);
+
+if (currAdmin.GetPriv()->userConf || currAdmin.GetPriv()->userPasswd)
+ s = "<password value=\"" + u->property.password.Get() + "\" />";
+else
+ s = "<password value=\"++++++\"/>";
+answerList->push_back(s);
+
+strprintf(&s, "<cash value=\"%f\" />", u->property.cash.Get());
+answerList->push_back(s);
+
+strprintf(&s, "<freemb value=\"%f\" />", u->property.freeMb.Get());
+answerList->push_back(s);
+
+strprintf(&s, "<credit value=\"%f\" />", u->property.credit.Get());
+answerList->push_back(s);
+
+if (u->property.nextTariff.Get() != "")
+ {
+ strprintf(&s, "<tariff value=\"%s/%s\" />",
+ u->property.tariffName.Get().c_str(),
+ u->property.nextTariff.Get().c_str());
+ }
+else
+ {
+ strprintf(&s, "<tariff value=\"%s\" />",
+ u->property.tariffName.Get().c_str());
+ }
+
+answerList->push_back(s);
+
+Encode12str(enc, u->property.note);
+s = "<note value=\"" + enc + "\" />";
+answerList->push_back(s);
+
+Encode12str(enc, u->property.phone);
+s = "<phone value=\"" + enc + "\" />";
+answerList->push_back(s);
+
+Encode12str(enc, u->property.address);
+s = "<address value=\"" + enc + "\" />";
+answerList->push_back(s);
+
+Encode12str(enc, u->property.email);
+s = "<email value=\"" + enc + "\" />";
+answerList->push_back(s);
+
+
+vector<USER_PROPERTY_LOGGED<string> *> userdata;
+userdata.push_back(u->property.userdata0.GetPointer());
+userdata.push_back(u->property.userdata1.GetPointer());
+userdata.push_back(u->property.userdata2.GetPointer());
+userdata.push_back(u->property.userdata3.GetPointer());
+userdata.push_back(u->property.userdata4.GetPointer());
+userdata.push_back(u->property.userdata5.GetPointer());
+userdata.push_back(u->property.userdata6.GetPointer());
+userdata.push_back(u->property.userdata7.GetPointer());
+userdata.push_back(u->property.userdata8.GetPointer());
+userdata.push_back(u->property.userdata9.GetPointer());
+
+string tmpI;
+for (unsigned i = 0; i < userdata.size(); i++)
+ {
+ Encode12str(enc, userdata[i]->Get());
+ s = "<UserData" + x2str(i, tmpI) + " value=\"" + enc + "\" />";
+ answerList->push_back(s);
+ }
+
+Encode12str(enc, u->property.realName);
+s = "<name value=\"" + enc + "\" />";
+answerList->push_back(s);
+
+Encode12str(enc, u->property.group);
+s = "<GROUP value=\"" + enc + "\" />";
+answerList->push_back(s);
+
+strprintf(&s, "<status value=\"%d\" />", u->GetConnected());
+answerList->push_back(s);
+
+strprintf(&s, "<aonline value=\"%d\" />", u->property.alwaysOnline.Get());
+answerList->push_back(s);
+
+strprintf(&s, "<currip value=\"%s\" />", inet_ntostring(u->GetCurrIP()).c_str());
+answerList->push_back(s);
+
+strprintf(&s, "<PingTime value=\"%lu\" />", u->GetPingTime());
+answerList->push_back(s);
+
+stringstream sstr;
+sstr << u->property.ips.Get();
+strprintf(&s, "<ip value=\"%s\" />", sstr.str().c_str());
+answerList->push_back(s);
+
+char * ss;
+ss = new char[DIR_NUM*25*4 + 50];
+char st[50];
+sprintf(ss, "<traff");
+DIR_TRAFF upload;
+DIR_TRAFF download;
+download = u->property.down.Get();
+upload = u->property.up.Get();
+
+for (int j = 0; j < DIR_NUM; j++)
+ {
+ string s;
+ x2str(upload[j], s);
+ sprintf(st, " MU%d=\"%s\"", j, s.c_str());
+ strcat(ss, st);
+
+ x2str(download[j], s);
+ sprintf(st, " MD%d=\"%s\"", j, s.c_str());
+ strcat(ss, st);
+
+ sprintf(st, " SU%d=\"0\"", j);
+ strcat(ss, st);
+
+ sprintf(st, " SD%d=\"0\"", j);
+ strcat(ss, st);
+ }
+strcat(ss, " />");
+answerList->push_back(ss);
+delete[] ss;
+
+strprintf(&s, "<down value=\"%d\" />", u->property.disabled.Get());
+answerList->push_back(s);
+
+strprintf(&s, "<DisableDetailStat value=\"%d\" />", u->property.disabledDetailStat.Get());
+answerList->push_back(s);
+
+strprintf(&s, "<passive value=\"%d\" />", u->property.passive.Get());
+answerList->push_back(s);
+
+strprintf(&s, "<LastCash value=\"%f\" />", u->property.lastCashAdd.Get());
+answerList->push_back(s);
+
+strprintf(&s, "<LastTimeCash value=\"%ld\" />", u->property.lastCashAddTime.Get());
+answerList->push_back(s);
+
+strprintf(&s, "<LastActivityTime value=\"%ld\" />", u->property.lastActivityTime.Get());
+answerList->push_back(s);
+
+strprintf(&s, "<CreditExpire value=\"%ld\" />", u->property.creditExpire.Get());
+answerList->push_back(s);
+
+strprintf(&s, "</user>");
+answerList->push_back(s);
+}
+//-----------------------------------------------------------------------------
+// GET USERS
+//-----------------------------------------------------------------------------
+PARSER_GET_USERS::PARSER_GET_USERS()
+{
+lastUserUpdateTime = 0;
+}
+//-----------------------------------------------------------------------------
+int PARSER_GET_USERS::ParseStart(void *, const char *el, const char ** attr)
+{
+/*if (attr && *attr && *(attr+1))
+ {
+ printfd(__FILE__, "attr=%s %s\n", *attr, *(attr+1));
+ }
+else
+ {
+ printfd(__FILE__, "attr = NULL\n");
+ }*/
+
+lastUpdateFound = false;
+if (strcasecmp(el, "GetUsers") == 0)
+ {
+ while (attr && *attr && *(attr+1))
+ {
+ if (strcasecmp(*attr, "LastUpdate") == 0)
+ {
+ if (str2x(*(attr+1), lastUserUpdateTime) == 0)
+ {
+ //printfd(__FILE__, "lastUserUpdateTime=%d\n", lastUserUpdateTime);
+ lastUpdateFound = true;
+ }
+ else
+ {
+ //printfd(__FILE__, "NO lastUserUpdateTime\n");
+ }
+ }
+ ++attr;
+ }
+
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int PARSER_GET_USERS::ParseEnd(void *, const char *el)
+{
+if (strcasecmp(el, "GetUsers") == 0)
+ {
+ CreateAnswer();
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+void PARSER_GET_USERS::CreateAnswer()
+{
+answerList->erase(answerList->begin(), answerList->end());
+
+string s;
+string userStart;
+string traffStart;
+string traffMiddle;
+string traffFinish;
+string middle;
+string userFinish;
+
+
+string enc;
+
+user_iter u;
+
+int h = users->OpenSearch();
+if (!h)
+ {
+ printfd(__FILE__, "users->OpenSearch() error\n");
+ users->CloseSearch(h);
+ return;
+ }
+string updateTime;
+x2str(time(NULL), updateTime);
+
+if (lastUpdateFound)
+ answerList->push_back("<Users LastUpdate=\"" + updateTime + "\">");
+else
+ answerList->push_back("<Users>");
+
+while (1)
+ {
+ if (users->SearchNext(h, &u))
+ {
+ break;
+ }
+ userStart = "<user login=\"" + u->GetLogin() + "\">";
+ middle = "";
+
+ if (u->property.password.ModificationTime() > lastUserUpdateTime)
+ {
+ if (currAdmin.GetPriv()->userConf || currAdmin.GetPriv()->userPasswd)
+ s = "<password value=\"" + u->property.password.Get() + "\" />";
+ else
+ s = "<password value=\"++++++\"/>";
+ middle += s;
+ }
+
+
+ if (u->property.cash.ModificationTime() > lastUserUpdateTime)
+ {
+ strprintf(&s, "<cash value=\"%f\" />", u->property.cash.Get());
+ middle += s;
+ //printfd(__FILE__, "cash value=\"%f\"\n", u->property.cash.Get());
+ }
+
+
+ if (u->property.freeMb.ModificationTime() > lastUserUpdateTime)
+ {
+ strprintf(&s, "<freemb value=\"%f\" />", u->property.freeMb.Get());
+ middle += s;
+ }
+
+ if (u->property.credit.ModificationTime() > lastUserUpdateTime)
+ {
+ strprintf(&s, "<credit value=\"%f\" />", u->property.credit.Get());
+ middle += s;
+ }
+
+ if (u->property.nextTariff.Get() != "")
+ {
+ if (u->property.tariffName.ModificationTime() > lastUserUpdateTime
+ || u->property.nextTariff.ModificationTime() > lastUserUpdateTime)
+ {
+ strprintf(&s, "<tariff value=\"%s/%s\" />",
+ u->property.tariffName.Get().c_str(),
+ u->property.nextTariff.Get().c_str());
+ middle += s;
+ }
+ }
+ else
+ {
+ if (u->property.tariffName.ModificationTime() > lastUserUpdateTime)
+ {
+ strprintf(&s, "<tariff value=\"%s\" />",
+ u->property.tariffName.Get().c_str());
+ middle += s;
+ }
+ }
+
+ if (u->property.note.ModificationTime() > lastUserUpdateTime)
+ {
+ Encode12str(enc, u->property.note);
+ strprintf(&s, "<note value=\"%s\" />", enc.c_str());
+ middle += s;
+ }
+
+ if (u->property.phone.ModificationTime() > lastUserUpdateTime)
+ {
+ Encode12str(enc, u->property.phone);
+ strprintf(&s, "<phone value=\"%s\" />", enc.c_str());
+ middle += s;
+ }
+
+ if (u->property.address.ModificationTime() > lastUserUpdateTime)
+ {
+ Encode12str(enc, u->property.address);
+ strprintf(&s, "<address value=\"%s\" />", enc.c_str());
+ middle += s;
+ }
+
+ if (u->property.email.ModificationTime() > lastUserUpdateTime)
+ {
+ Encode12str(enc, u->property.email);
+ strprintf(&s, "<email value=\"%s\" />", enc.c_str());
+ middle += s;
+ }
+
+ vector<USER_PROPERTY_LOGGED<string> *> userdata;
+ userdata.push_back(u->property.userdata0.GetPointer());
+ userdata.push_back(u->property.userdata1.GetPointer());
+ userdata.push_back(u->property.userdata2.GetPointer());
+ userdata.push_back(u->property.userdata3.GetPointer());
+ userdata.push_back(u->property.userdata4.GetPointer());
+ userdata.push_back(u->property.userdata5.GetPointer());
+ userdata.push_back(u->property.userdata6.GetPointer());
+ userdata.push_back(u->property.userdata7.GetPointer());
+ userdata.push_back(u->property.userdata8.GetPointer());
+ userdata.push_back(u->property.userdata9.GetPointer());
+
+ string tmpI;
+ for (unsigned i = 0; i < userdata.size(); i++)
+ {
+ if (userdata[i]->ModificationTime() > lastUserUpdateTime)
+ {
+ Encode12str(enc, userdata[i]->Get());
+ s = "<UserData" + x2str(i, tmpI) + " value=\"" + enc + "\" />";
+ middle += s;
+ }
+ }
+
+ if (u->property.realName.ModificationTime() > lastUserUpdateTime)
+ {
+ Encode12str(enc, u->property.realName);
+ strprintf(&s, "<name value=\"%s\" />", enc.c_str());
+ middle += s;
+ }
+
+ if (u->property.group.ModificationTime() > lastUserUpdateTime)
+ {
+ Encode12str(enc, u->property.group);
+ strprintf(&s, "<GROUP value=\"%s\" />", enc.c_str());
+ middle += s;
+ }
+
+ if (u->property.alwaysOnline.ModificationTime() > lastUserUpdateTime)
+ {
+ strprintf(&s, "<aonline value=\"%d\" />", u->property.alwaysOnline.Get());
+ middle += s;
+ }
+
+ if (u->GetCurrIPModificationTime() > lastUserUpdateTime)
+ {
+ strprintf(&s, "<currip value=\"%s\" />", inet_ntostring(u->GetCurrIP()).c_str());
+ middle += s;
+ }
+
+
+ if (u->GetConnectedModificationTime() > lastUserUpdateTime)
+ {
+ strprintf(&s, "<status value=\"%d\" />", u->GetConnected());
+ middle += s;
+ }
+
+ if (u->GetPingTime() > lastUserUpdateTime)
+ {
+ strprintf(&s, "<PingTime value=\"%lu\" />", u->GetPingTime());
+ middle += s;
+ }
+
+ if (u->property.ips.ModificationTime() > lastUserUpdateTime)
+ {
+ stringstream sstr;
+ sstr << u->property.ips.Get();
+ strprintf(&s, "<ip value=\"%s\" />", sstr.str().c_str());
+ middle += s;
+ }
+
+ char st[50];
+ traffStart = "<traff";
+ DIR_TRAFF upload;
+ DIR_TRAFF download;
+ download = u->property.down.Get();
+ upload = u->property.up.Get();
+ traffMiddle = "";
+
+ if (u->property.up.ModificationTime() > lastUserUpdateTime)
+ {
+ for (int j = 0; j < DIR_NUM; j++)
+ {
+ string s;
+ x2str(upload[j], s);
+ sprintf(st, " MU%d=\"%s\" ", j, s.c_str());
+ traffMiddle += st;
+ }
+ }
+
+ if (u->property.down.ModificationTime() > lastUserUpdateTime)
+ {
+ for (int j = 0; j < DIR_NUM; j++)
+ {
+ x2str(download[j], s);
+ sprintf(st, " MD%d=\"%s\" ", j, s.c_str());
+ traffMiddle += st;
+ }
+ }
+
+ traffFinish = " />";
+ if (traffMiddle.length() > 0)
+ {
+ middle += traffStart;
+ middle += traffMiddle;
+ middle += traffFinish;
+ }
+
+ if (u->property.disabled.ModificationTime() > lastUserUpdateTime)
+ {
+ strprintf(&s, "<down value=\"%d\" />", u->property.disabled.Get());
+ middle += s;
+ }
+
+ if (u->property.disabledDetailStat.ModificationTime() > lastUserUpdateTime)
+ {
+ strprintf(&s, "<DisableDetailStat value=\"%d\" />", u->property.disabledDetailStat.Get());
+ middle += s;
+ }
+
+ //printfd(__FILE__, ">>>>> %s\n", s.c_str());
+
+ if (u->property.passive.ModificationTime() > lastUserUpdateTime)
+ {
+ strprintf(&s, "<passive value=\"%d\" />", u->property.passive.Get());
+ middle += s;
+ }
+
+ if (u->property.lastCashAdd.ModificationTime() > lastUserUpdateTime)
+ {
+ strprintf(&s, "<LastCash value=\"%f\" />", u->property.lastCashAdd.Get());
+ middle += s;
+ }
+
+ if (u->property.lastCashAddTime.ModificationTime() > lastUserUpdateTime)
+ {
+ strprintf(&s, "<LastTimeCash value=\"%ld\" />", u->property.lastCashAddTime.Get());
+ middle += s;
+ }
+
+
+ if (u->property.lastActivityTime.ModificationTime() > lastUserUpdateTime)
+ {
+ strprintf(&s, "<LastActivityTime value=\"%ld\" />", u->property.lastActivityTime.Get());
+ middle += s;
+ }
+
+ if (u->property.creditExpire.ModificationTime() > lastUserUpdateTime)
+ {
+ strprintf(&s, "<CreditExpire value=\"%ld\" />", u->property.creditExpire.Get());
+ middle += s;
+ }
+
+
+ userFinish = "</user>";
+
+ if (middle.length() > 0)
+ {
+ /*printfd(__FILE__, "login: %s\n", u->GetLogin().c_str());
+ printfd(__FILE__, "middle: %s\n", middle.c_str());*/
+
+ answerList->push_back(userStart);
+ answerList->push_back(middle);
+ answerList->push_back(userFinish);
+ }
+ }
+
+users->CloseSearch(h);
+
+//answerList->push_back("</Users>");
+
+answerList->push_back("</Users>");
+}
+//-----------------------------------------------------------------------------
+// ADD USER
+//-----------------------------------------------------------------------------
+PARSER_ADD_USER::PARSER_ADD_USER()
+{
+depth = 0;
+}
+//-----------------------------------------------------------------------------
+int PARSER_ADD_USER::ParseStart(void *, const char *el, const char **attr)
+{
+depth++;
+
+if (depth == 1)
+ {
+ if (strcasecmp(el, "AddUser") == 0)
+ {
+ return 0;
+ }
+ }
+else
+ {
+ if (strcasecmp(el, "login") == 0)
+ {
+ login = attr[1];
+ return 0;
+ }
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int PARSER_ADD_USER::ParseEnd(void *, const char *el)
+{
+if (depth == 1)
+ {
+ if (strcasecmp(el, "AddUser") == 0)
+ {
+ CreateAnswer();
+ depth--;
+ return 0;
+ }
+ }
+
+depth--;
+return -1;
+}
+//-----------------------------------------------------------------------------
+void PARSER_ADD_USER::Reset()
+{
+BASE_PARSER::Reset();
+depth = 0;
+}
+//-----------------------------------------------------------------------------
+void PARSER_ADD_USER::CreateAnswer()
+{
+//answerList->clear();
+answerList->erase(answerList->begin(), answerList->end());
+
+if (CheckUserData() == 0)
+ {
+ answerList->push_back("<AddUser result=\"ok\"/>");
+ }
+else
+ {
+ answerList->push_back("<AddUser result=\"error\" reason=\"Access denied\"/>");
+ }
+}
+//-----------------------------------------------------------------------------
+int PARSER_ADD_USER::CheckUserData()
+{
+user_iter u;
+if (users->FindByName(login, &u))
+ {
+ return users->Add(login, currAdmin);
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+// PARSER CHG USER
+//-----------------------------------------------------------------------------
+PARSER_CHG_USER::PARSER_CHG_USER()
+{
+usr = NULL;
+ucr = NULL;
+upr = NULL;
+downr = NULL;
+
+Reset();
+}
+//-----------------------------------------------------------------------------
+PARSER_CHG_USER::~PARSER_CHG_USER()
+{
+delete usr;
+delete ucr;
+delete[] upr;
+delete[] downr;
+}
+//-----------------------------------------------------------------------------
+void PARSER_CHG_USER::Reset()
+{
+depth = 0;
+delete usr;
+
+delete ucr;
+
+delete[] upr;
+
+delete[] downr;
+
+usr = new USER_STAT_RES;
+ucr = new USER_CONF_RES;
+
+upr = new RESETABLE<uint64_t>[DIR_NUM];
+downr = new RESETABLE<uint64_t>[DIR_NUM];
+};
+//-----------------------------------------------------------------------------
+string PARSER_CHG_USER::EncChar2String(const char * strEnc)
+{
+string str;
+Decode21str(str, strEnc);
+return str;
+}
+//-----------------------------------------------------------------------------
+int PARSER_CHG_USER::ParseStart(void *, const char *el, const char **attr)
+{
+depth++;
+
+if (depth == 1)
+ {
+ if (strcasecmp(el, "SetUser") == 0)
+ {
+ return 0;
+ }
+ }
+else
+ {
+ //printfd(__FILE__, "el=%s\n", el);
+ if (strcasecmp(el, "login") == 0)
+ {
+ login = attr[1];
+ return 0;
+ }
+
+ if (strcasecmp(el, "ip") == 0)
+ {
+ try
+ {
+ ucr->ips = StrToIPS(attr[1]);
+ }
+ catch (...)
+ {
+ printfd(__FILE__, "StrToIPS Error!\n");
+ }
+ }
+
+ if (strcasecmp(el, "password") == 0)
+ {
+ ucr->password = attr[1];
+ return 0;
+ }
+
+ if (strcasecmp(el, "address") == 0)
+ {
+ ucr->address = EncChar2String(attr[1]);
+ return 0;
+ }
+
+ if (strcasecmp(el, "aonline") == 0)
+ {
+ ucr->alwaysOnline = (*(attr[1]) != '0');
+ return 0;
+ }
+
+ if (strcasecmp(el, "cash") == 0)
+ {
+ if (attr[2] && (strcasecmp(attr[2], "msg") == 0))
+ {
+ cashMsg = EncChar2String(attr[3]);
+ }
+
+ double cash;
+ if (strtodouble2(attr[1], cash) == 0)
+ usr->cash = cash;
+
+ if (strcasecmp(attr[0], "set") == 0)
+ cashMustBeAdded = false;
+
+ if (strcasecmp(attr[0], "add") == 0)
+ cashMustBeAdded = true;
+
+ return 0;
+ }
+
+ if (strcasecmp(el, "CreditExpire") == 0)
+ {
+ long int creditExpire = 0;
+ if (str2x(attr[1], creditExpire) == 0)
+ ucr->creditExpire = (time_t)creditExpire;
+
+ return 0;
+ }
+
+ if (strcasecmp(el, "credit") == 0)
+ {
+ double credit;
+ if (strtodouble2(attr[1], credit) == 0)
+ ucr->credit = credit;
+ return 0;
+ }
+
+ if (strcasecmp(el, "freemb") == 0)
+ {
+ double freeMb;
+ if (strtodouble2(attr[1], freeMb) == 0)
+ usr->freeMb = freeMb;
+ return 0;
+ }
+
+ if (strcasecmp(el, "down") == 0)
+ {
+ int down = 0;
+ if (str2x(attr[1], down) == 0)
+ ucr->disabled = down;
+ return 0;
+ }
+
+ if (strcasecmp(el, "DisableDetailStat") == 0)
+ {
+ int disabledDetailStat = 0;
+ if (str2x(attr[1], disabledDetailStat) == 0)
+ ucr->disabledDetailStat = disabledDetailStat;
+ return 0;
+ }
+
+ if (strcasecmp(el, "email") == 0)
+ {
+ ucr->email = EncChar2String(attr[1]);
+ return 0;
+ }
+
+ for (int i = 0; i < USERDATA_NUM; i++)
+ {
+ char name[15];
+ sprintf(name, "userdata%d", i);
+ if (strcasecmp(el, name) == 0)
+ {
+ ucr->userdata[i] = EncChar2String(attr[1]);
+ return 0;
+ }
+ }
+
+ if (strcasecmp(el, "group") == 0)
+ {
+ ucr->group = EncChar2String(attr[1]);
+ return 0;
+ }
+
+ if (strcasecmp(el, "note") == 0)
+ {
+ ucr->note = EncChar2String(attr[1]);
+ return 0;
+ }
+
+ if (strcasecmp(el, "passive") == 0)
+ {
+ int passive = 0;
+ if (str2x(attr[1], passive) == 0)
+ ucr->passive = passive;
+ return 0;
+ }
+
+ if (strcasecmp(el, "phone") == 0)
+ {
+ ucr->phone = EncChar2String(attr[1]);
+ return 0;
+ }
+
+ if (strcasecmp(el, "Name") == 0)
+ {
+ ucr->realName = EncChar2String(attr[1]);
+ return 0;
+ }
+
+ if (strcasecmp(el, "traff") == 0)
+ {
+ int j = 0;
+ int dir;
+ DIR_TRAFF dtu;
+ DIR_TRAFF dtd;
+ unsigned long long t = 0;
+ while (attr[j])
+ {
+ dir = attr[j][2] - '0';
+
+ if (strncasecmp(attr[j], "md", 2) == 0)
+ {
+ str2x(attr[j+1], t);
+ dtd[dir] = t;
+ downr[dir] = t;
+ }
+ if (strncasecmp(attr[j], "mu", 2) == 0)
+ {
+ str2x(attr[j+1], t);
+ dtu[dir] = t;
+ upr[dir] = t;
+ }
+ j+=2;
+ }
+ usr->down = dtd;
+ usr->up = dtu;
+ return 0;
+ }
+
+ if (strcasecmp(el, "tariff") == 0)
+ {
+ if (strcasecmp(attr[0], "now") == 0)
+ ucr->tariffName = attr[1];
+
+ if (strcasecmp(attr[0], "delayed") == 0)
+ ucr->nextTariff = attr[1];
+
+ return 0;
+ }
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int PARSER_CHG_USER::ParseEnd(void *, const char *el)
+{
+if (depth == 1)
+ {
+ if (strcasecmp(el, "SetUser") == 0)
+ {
+ AplayChanges();
+ CreateAnswer();
+ depth--;
+ return 0;
+ }
+ }
+
+depth--;
+return -1;
+}
+//-----------------------------------------------------------------------------
+void PARSER_CHG_USER::CreateAnswer()
+{
+//answerList->clear();
+answerList->erase(answerList->begin(), answerList->end());
+
+switch (res)
+ {
+ case 0:
+ answerList->push_back("<SetUser result=\"ok\"/>");
+ break;
+ case -1:
+ answerList->push_back("<SetUser result=\"error\"/>");
+ break;
+ case -2:
+ answerList->push_back("<SetUser result=\"error\"/>");
+ break;
+ default:
+ answerList->push_back("<SetUser result=\"error\"/>");
+ break;
+ }
+
+}
+//-----------------------------------------------------------------------------
+int PARSER_CHG_USER::CheckUserData()
+{
+return true;
+}
+//-----------------------------------------------------------------------------
+int PARSER_CHG_USER::AplayChanges()
+{
+user_iter u;
+
+res = 0;
+if (users->FindByName(login, &u))
+ {
+ res = -1;
+ return -1;
+ }
+
+if (!ucr->ips.res_empty())
+ if (!u->property.ips.Set(ucr->ips.const_data(), currAdmin, login, store))
+ res = -1;
+
+if (!ucr->address.res_empty())
+ if (!u->property.address.Set(ucr->address.const_data(), currAdmin, login, store))
+ res = -1;
+
+if (!ucr->alwaysOnline.res_empty())
+ if (!u->property.alwaysOnline.Set(ucr->alwaysOnline.const_data(),
+ currAdmin, login, store))
+ res = -1;
+
+if (!ucr->creditExpire.res_empty())
+ if (!u->property.creditExpire.Set(ucr->creditExpire.const_data(),
+ currAdmin, login, store))
+ res = -1;
+
+if (!ucr->credit.res_empty())
+ if (!u->property.credit.Set(ucr->credit.const_data(), currAdmin, login, store))
+ res = -1;
+
+if (!usr->freeMb.res_empty())
+ if (!u->property.freeMb.Set(usr->freeMb.const_data(), currAdmin, login, store))
+ res = -1;
+
+if (!ucr->disabled.res_empty())
+ if (!u->property.disabled.Set(ucr->disabled.const_data(), currAdmin, login, store))
+ res = -1;
+
+if (!ucr->disabledDetailStat.res_empty())
+ if (!u->property.disabledDetailStat.Set(ucr->disabledDetailStat.const_data(), currAdmin, login, store))
+ res = -1;
+
+if (!ucr->email.res_empty())
+ if (!u->property.email.Set(ucr->email.const_data(), currAdmin, login, store))
+ res = -1;
+
+if (!ucr->group.res_empty())
+ if (!u->property.group.Set(ucr->group.const_data(), currAdmin, login, store))
+ res = -1;
+
+if (!ucr->note.res_empty())
+ if (!u->property.note.Set(ucr->note.const_data(), currAdmin, login, store))
+ res = -1;
+
+vector<USER_PROPERTY_LOGGED<string> *> userdata;
+userdata.push_back(u->property.userdata0.GetPointer());
+userdata.push_back(u->property.userdata1.GetPointer());
+userdata.push_back(u->property.userdata2.GetPointer());
+userdata.push_back(u->property.userdata3.GetPointer());
+userdata.push_back(u->property.userdata4.GetPointer());
+userdata.push_back(u->property.userdata5.GetPointer());
+userdata.push_back(u->property.userdata6.GetPointer());
+userdata.push_back(u->property.userdata7.GetPointer());
+userdata.push_back(u->property.userdata8.GetPointer());
+userdata.push_back(u->property.userdata9.GetPointer());
+
+for (int i = 0; i < (int)userdata.size(); i++)
+ {
+ if (!ucr->userdata[i].res_empty())
+ {
+ if(!userdata[i]->Set(ucr->userdata[i].const_data(), currAdmin, login, store))
+ res = -1;
+ }
+ }
+
+if (!ucr->passive.res_empty())
+ if (!u->property.passive.Set(ucr->passive.const_data(), currAdmin, login, store))
+ res = -1;
+
+if (!ucr->password.res_empty())
+ if (!u->property.password.Set(ucr->password.const_data(), currAdmin, login, store))
+ res = -1;
+
+if (!ucr->phone.res_empty())
+ if (!u->property.phone.Set(ucr->phone.const_data(), currAdmin, login, store))
+ res = -1;
+
+if (!ucr->realName.res_empty())
+ if (!u->property.realName.Set(ucr->realName.const_data(), currAdmin, login, store))
+ res = -1;
+
+
+if (!usr->cash.res_empty())
+ {
+ //if (currAdmin->GetPriv()->userCash)
+ {
+ if (cashMustBeAdded)
+ {
+ if (!u->property.cash.Set(usr->cash.const_data() + u->property.cash,
+ currAdmin,
+ login,
+ store,
+ cashMsg))
+ res = -1;
+ }
+ else
+ {
+ if (!u->property.cash.Set(usr->cash.const_data(), currAdmin, login, store, cashMsg))
+ res = -1;
+ }
+ }
+ }
+
+
+if (!ucr->tariffName.res_empty())
+ {
+ if (tariffs->FindByName(ucr->tariffName.const_data()))
+ {
+ if (!u->property.tariffName.Set(ucr->tariffName.const_data(), currAdmin, login, store))
+ res = -1;
+ u->ResetNextTariff();
+ }
+ else
+ {
+ //WriteServLog("SetUser: Tariff %s not found", ud.conf.tariffName.c_str());
+ res = -1;
+ }
+ }
+
+if (!ucr->nextTariff.res_empty())
+ {
+ if (tariffs->FindByName(ucr->nextTariff.const_data()))
+ {
+ if (!u->property.nextTariff.Set(ucr->nextTariff.const_data(), currAdmin, login, store))
+ res = -1;
+ }
+ else
+ {
+ //WriteServLog("SetUser: Tariff %s not found", ud.conf.tariffName.c_str());
+ res = -1;
+ }
+ }
+
+DIR_TRAFF up = u->property.up;
+DIR_TRAFF down = u->property.down;
+int upCount = 0;
+int downCount = 0;
+for (int i = 0; i < DIR_NUM; i++)
+ {
+ if (!upr[i].res_empty())
+ {
+ up[i] = upr[i];
+ upCount++;
+ }
+ if (!downr[i].res_empty())
+ {
+ down[i] = downr[i];
+ downCount++;
+ }
+ }
+
+if (upCount)
+ if (!u->property.up.Set(up, currAdmin, login, store))
+ res = -1;
+
+if (downCount)
+ if (!u->property.down.Set(down, currAdmin, login, store))
+ res = -1;
+
+/*if (!usr->down.res_empty())
+ {
+ u->property.down.Set(usr->down.const_data(), currAdmin, login, store);
+ }
+if (!usr->up.res_empty())
+ {
+ u->property.up.Set(usr->up.const_data(), currAdmin, login, store);
+ }*/
+
+u->WriteConf();
+u->WriteStat();
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+// SEND MESSAGE
+//-----------------------------------------------------------------------------
+int PARSER_SEND_MESSAGE::ParseStart(void *, const char *el, const char **attr)
+{
+if (strcasecmp(el, "Message") == 0)
+ {
+ for (int i = 0; i < 14; i++)
+ {
+ if (attr[i] == NULL)
+ {
+ result = res_params_error;
+ CreateAnswer();
+ printfd(__FILE__, "To few parameters\n");
+ return 0;
+ }
+ }
+
+ for (int i = 0; i < 14; i+=2)
+ {
+ if (strcasecmp(attr[i], "login") == 0)
+ {
+ ParseLogins(attr[i+1]);
+ /*if (users->FindByName(login, &u))
+ {
+ result = res_unknown;
+ break;
+ }*/
+ }
+
+ if (strcasecmp(attr[i], "MsgVer") == 0)
+ {
+ str2x(attr[i+1], msg.header.ver);
+ if (msg.header.ver != 1)
+ result = res_params_error;
+ }
+
+ if (strcasecmp(attr[i], "MsgType") == 0)
+ {
+ str2x(attr[i+1], msg.header.type);
+ if (msg.header.type != 1)
+ result = res_params_error;
+ }
+
+ if (strcasecmp(attr[i], "Repeat") == 0)
+ {
+ str2x(attr[i+1], msg.header.repeat);
+ if (msg.header.repeat < 0)
+ result = res_params_error;
+ }
+
+ if (strcasecmp(attr[i], "RepeatPeriod") == 0)
+ {
+ str2x(attr[i+1], msg.header.repeatPeriod);
+ }
+
+ if (strcasecmp(attr[i], "ShowTime") == 0)
+ {
+ str2x(attr[i+1], msg.header.showTime);
+ }
+
+ if (strcasecmp(attr[i], "Text") == 0)
+ {
+ Decode21str(msg.text, attr[i+1]);
+ result = res_ok;
+ }
+ }
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int PARSER_SEND_MESSAGE::ParseEnd(void *, const char *el)
+{
+//MSG msg;
+if (strcasecmp(el, "Message") == 0)
+ {
+ result = res_unknown;
+ for (unsigned i = 0; i < logins.size(); i++)
+ {
+ if (users->FindByName(logins[i], &u))
+ {
+ printfd(__FILE__, "User not found. %s\n", logins[i].c_str());
+ continue;
+ }
+ msg.header.creationTime = stgTime;
+ u->AddMessage(&msg);
+ result = res_ok;
+ }
+ /*if (result == res_ok)
+ {
+ if (strcmp(login, "*") == 0)
+ {
+ msg.text = text;
+ msg.prio = pri;
+ printfd(__FILE__, "SendMsg text: %s\n", text);
+ users->GetAllUsers(SendMessageAllUsers, &msg);
+ }
+ else
+ {
+ u->AddMessage(pri, text);
+ }
+ }*/
+ CreateAnswer();
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int PARSER_SEND_MESSAGE::ParseLogins(const char * login)
+{
+char * p;
+char * l = new char[strlen(login) + 1];
+strcpy(l, login);
+p = strtok(l, ":");
+logins.clear();
+while(p)
+ {
+ logins.push_back(p);
+ p = strtok(NULL, ":");
+ }
+
+delete[] l;
+return 0;
+}
+//-----------------------------------------------------------------------------
+void PARSER_SEND_MESSAGE::CreateAnswer()
+{
+//answerList->clear();
+answerList->erase(answerList->begin(), answerList->end());
+//answerList->push_back("<SendMessageResult value=\"ok\"/>");
+//
+switch (result)
+ {
+ case res_ok:
+ answerList->push_back("<SendMessageResult value=\"ok\"/>");
+ break;
+ case res_params_error:
+ printfd(__FILE__, "res_params_error\n");
+ answerList->push_back("<SendMessageResult value=\"Parameters error\"/>");
+ break;
+ case res_unknown:
+ printfd(__FILE__, "res_unknown\n");
+ answerList->push_back("<SendMessageResult value=\"Unknown user\"/>");
+ break;
+ default:
+ printfd(__FILE__, "res_default\n");
+ }
+
+}
+//-----------------------------------------------------------------------------
+// DEL USER
+//-----------------------------------------------------------------------------
+int PARSER_DEL_USER::ParseStart(void *, const char *el, const char **attr)
+{
+res = 0;
+if (strcasecmp(el, "DelUser") == 0)
+ {
+ if (attr[0] == NULL || attr[1] == NULL)
+ {
+ //CreateAnswer("Parameters error!");
+ CreateAnswer();
+ return 0;
+ }
+
+ if (users->FindByName(attr[1], &u))
+ {
+ res = 1;
+ CreateAnswer();
+ return 0;
+ }
+ CreateAnswer();
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int PARSER_DEL_USER::ParseEnd(void *, const char *el)
+{
+if (strcasecmp(el, "DelUser") == 0)
+ {
+ if (!res)
+ users->Del(u->GetLogin(), currAdmin);
+
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+void PARSER_DEL_USER::CreateAnswer()
+{
+if (res)
+ answerList->push_back("<DelUser value=\"error\" reason=\"User not found\"/>");
+else
+ answerList->push_back("<DelUser value=\"ok\"/>");
+}
+//-----------------------------------------------------------------------------
+/*void PARSERDELUSER::CreateAnswer(char * mes)
+{
+//answerList->clear();
+answerList->erase(answerList->begin(), answerList->end());
+
+char str[255];
+sprintf(str, "<DelUser value=\"%s\"/>", mes);
+answerList->push_back(str);
+}*/
+//-----------------------------------------------------------------------------
+// CHECK USER
+// <checkuser login="vasya" password=\"123456\"/>
+//-----------------------------------------------------------------------------
+int PARSER_CHECK_USER::ParseStart(void *, const char *el, const char **attr)
+{
+result = false;
+
+if (strcasecmp(el, "CheckUser") == 0)
+ {
+ if (attr[0] == NULL || attr[1] == NULL
+ || attr[2] == NULL || attr[3] == NULL)
+ {
+ result = false;
+ CreateAnswer();
+ printfd(__FILE__, "PARSER_CHECK_USER - attr err\n");
+ return 0;
+ }
+
+ user_iter user;
+ if (users->FindByName(attr[1], &user))
+ {
+ result = false;
+ CreateAnswer();
+ printfd(__FILE__, "PARSER_CHECK_USER - login err\n");
+ return 0;
+ }
+
+ if (strcmp(user->property.password.Get().c_str(), attr[3]))
+ {
+ result = false;
+ CreateAnswer();
+ printfd(__FILE__, "PARSER_CHECK_USER - passwd err\n");
+ return 0;
+ }
+
+ result = true;
+ CreateAnswer();
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int PARSER_CHECK_USER::ParseEnd(void *, const char *el)
+{
+if (strcasecmp(el, "CheckUser") == 0)
+ {
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+void PARSER_CHECK_USER::CreateAnswer()
+{
+if (result)
+ answerList->push_back("<CheckUser value=\"Ok\"/>");
+else
+ answerList->push_back("<CheckUser value=\"Err\"/>");
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
--- /dev/null
+ /*
+ $Revision: 1.20 $
+ $Date: 2010/10/04 20:26:10 $
+ $Author: faust $
+ */
+
+#ifndef PARSER_H
+#define PARSER_H
+
+#include <list>
+#include <string>
+
+#include "resetable.h"
+#include "stg_const.h"
+#include "base_store.h"
+#include "../../../admins.h"
+#include "../../../users.h"
+#include "stg_message.h"
+
+using namespace std;
+
+//-----------------------------------------------------------------------------
+class BASE_PARSER
+{
+public:
+ BASE_PARSER()
+ : admins(NULL),
+ users(NULL),
+ tariffs(NULL),
+ store(NULL),
+ settings(NULL),
+ currAdmin(),
+ depth(0)
+ { };
+ 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 CreateAnswer() = 0;
+ virtual void SetAnswerList(list<string> * ansList) { answerList = ansList; };
+
+ virtual void SetUsers(USERS * u) { users = u; };
+ virtual void SetAdmins(ADMINS * a) { admins = a; };
+ virtual void SetTariffs(TARIFFS * t) { tariffs = t; };
+ virtual void SetStore(BASE_STORE * s) { store = s; };
+ virtual void SetStgSettings(const SETTINGS * s) { settings = s; };
+
+ virtual void SetCurrAdmin(const ADMIN & cua) { currAdmin = cua; };
+ virtual string & GetStrError(){return strError;};
+ virtual void Reset(){ answerList->clear(); depth = 0; };
+protected:
+ string strError;
+ ADMINS * admins;
+ USERS * users;
+ TARIFFS * tariffs;
+ BASE_STORE * store;
+ const SETTINGS * settings;
+ ADMIN currAdmin;
+ int depth;
+ list<string> * answerList;
+};
+//-----------------------------------------------------------------------------
+class PARSER_GET_ADMINS: public BASE_PARSER
+{
+public:
+ int ParseStart(void *data, const char *el, const char **attr);
+ int ParseEnd(void *data, const char *el);
+ void CreateAnswer();
+};
+//-----------------------------------------------------------------------------
+class PARSER_ADD_ADMIN: public BASE_PARSER
+{
+public:
+ int ParseStart(void *data, const char *el, const char **attr);
+ int ParseEnd(void *data, const char *el);
+ void CreateAnswer();
+private:
+ string adminToAdd;
+};
+//-----------------------------------------------------------------------------
+class PARSER_DEL_ADMIN: public BASE_PARSER
+{
+public:
+ int ParseStart(void *data, const char *el, const char **attr);
+ int ParseEnd(void *data, const char *el);
+ void CreateAnswer();
+private:
+ int CheckAttr(const char **attr);
+ string adminToDel;
+};
+//-----------------------------------------------------------------------------
+class PARSER_CHG_ADMIN: public BASE_PARSER
+{
+public:
+ int ParseStart(void *data, const char *el, const char **attr);
+ int ParseEnd(void *data, const char *el);
+ void CreateAnswer();
+private:
+ RESETABLE<string> login;
+ RESETABLE<string> password;
+ RESETABLE<string> privAsString;
+};
+//-----------------------------------------------------------------------------
+class PARSER_GET_SERVER_INFO: public BASE_PARSER
+{
+public:
+ int ParseStart(void *data, const char *el, const char **attr);
+ int ParseEnd(void *data, const char *el);
+ void CreateAnswer();
+};
+
+//-----------------------------------------------------------------------------
+class PARSER_GET_USER: public BASE_PARSER
+{
+public:
+ PARSER_GET_USER();
+ ~PARSER_GET_USER(){};
+ int ParseStart(void *data, const char *el, const char **attr);
+ int ParseEnd(void *data, const char *el);
+ void CreateAnswer();
+private:
+ string login;
+};
+//-----------------------------------------------------------------------------
+class PARSER_GET_USERS: public BASE_PARSER
+{
+public:
+ PARSER_GET_USERS();
+ int ParseStart(void *data, const char *el, const char **attr);
+ int ParseEnd(void *data, const char *el);
+ void CreateAnswer();
+private:
+ time_t lastUserUpdateTime;
+ bool lastUpdateFound;
+};
+//-----------------------------------------------------------------------------
+class PARSER_GET_TARIFFS: public BASE_PARSER
+{
+public:
+ int ParseStart(void *data, const char *el, const char **attr);
+ int ParseEnd(void *data, const char *el);
+ void CreateAnswer();
+};
+//-----------------------------------------------------------------------------
+class PARSER_ADD_TARIFF: public BASE_PARSER
+{
+public:
+ int ParseStart(void *data, const char *el, const char **attr);
+ int ParseEnd(void *data, const char *el);
+ void CreateAnswer();
+private:
+ string tariffToAdd;
+};
+//-----------------------------------------------------------------------------
+class PARSER_DEL_TARIFF: public BASE_PARSER
+{
+public:
+ int ParseStart(void *data, const char *el, const char **attr);
+ int ParseEnd(void *data, const char *el);
+ void CreateAnswer();
+private:
+ string tariffToDel;
+};
+//-----------------------------------------------------------------------------
+class PARSER_CHG_TARIFF: public BASE_PARSER
+{
+public:
+ int ParseStart(void *data, const char *el, const char **attr);
+ int ParseEnd(void *data, const char *el);
+ void CreateAnswer();
+private:
+ int ParseSlashedIntParams(int paramsNum, const string & s, int * params);
+ int ParseSlashedDoubleParams(int paramsNum, const string & s, double * params);
+ int CheckTariffData();
+ int AplayChanges();
+
+ TARIFF_DATA_RES td;
+};
+//-----------------------------------------------------------------------------/
+class PARSER_ADD_USER: public BASE_PARSER
+{
+public:
+ PARSER_ADD_USER();
+ virtual ~PARSER_ADD_USER(){};
+ int ParseStart(void *data, const char *el, const char **attr);
+ int ParseEnd(void *data, const char *el);
+ void CreateAnswer();
+ void Reset();
+private:
+ int CheckUserData();
+ string login;
+};
+//-----------------------------------------------------------------------------
+class PARSER_CHG_USER: public BASE_PARSER
+{
+public:
+ PARSER_CHG_USER();
+ ~PARSER_CHG_USER();
+ int ParseStart(void *data, const char *el, const char **attr);
+ int ParseEnd(void *data, const char *el);
+ void CreateAnswer();
+ void Reset();
+private:
+ string EncChar2String(const char *);
+
+ USER_STAT_RES * usr;
+ USER_CONF_RES * ucr;
+ RESETABLE<uint64_t> * upr;
+ RESETABLE<uint64_t> * downr;
+ string cashMsg;
+ string login;
+
+ int CheckUserData();
+ int AplayChanges();
+ bool cashMustBeAdded;
+ int res;
+};
+//-----------------------------------------------------------------------------
+class PARSER_DEL_USER: public BASE_PARSER
+{
+public:
+ int ParseStart(void *data, const char *el, const char **attr);
+ int ParseEnd(void *data, const char *el);
+ void CreateAnswer();
+
+private:
+ int res;
+ user_iter u;
+};
+//-----------------------------------------------------------------------------
+class PARSER_CHECK_USER: public BASE_PARSER
+{
+public:
+ int ParseStart(void *data, const char *el, const char **attr);
+ int ParseEnd(void *data, const char *el);
+ void CreateAnswer();
+private:
+ bool result;
+};
+//-----------------------------------------------------------------------------
+class PARSER_SEND_MESSAGE: public BASE_PARSER
+{
+public:
+ int ParseStart(void *data, const char *el, const char **attr);
+ int ParseEnd(void *data, const char *el);
+ void CreateAnswer();
+private:
+ enum {res_ok, res_params_error, res_unknown};
+ vector<string> logins;
+ int ParseLogins(const char * logins);
+ int result;
+ STG_MSG msg;
+ user_iter u;
+};
+//-----------------------------------------------------------------------------
+#endif //PARSER_H
+
+
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+
+#include "parser.h"
+
+//-----------------------------------------------------------------------------
+// GET ADMINS
+//-----------------------------------------------------------------------------
+int PARSER_GET_ADMINS::ParseStart(void *, const char *el, const char **)
+{
+if (strcasecmp(el, "GetAdmins") == 0)
+ {
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int PARSER_GET_ADMINS::ParseEnd(void *, const char *el)
+{
+if (strcasecmp(el, "GetAdmins") == 0)
+ {
+ CreateAnswer();
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+void PARSER_GET_ADMINS::CreateAnswer()
+{
+const PRIV * priv = currAdmin.GetPriv();
+if (!priv->adminChg)
+ {
+ //answerList->clear();
+ answerList->erase(answerList->begin(), answerList->end());
+
+ answerList->push_back("<Error Result=\"Error. Access denied.\"/>");
+ return;
+ }
+
+string s;
+//answerList->clear();
+answerList->erase(answerList->begin(), answerList->end());
+
+answerList->push_back("<Admins>");
+ADMIN_CONF ac;
+int h = admins->OpenSearch();
+
+unsigned int p;
+while (admins->SearchNext(h, &ac) == 0)
+ {
+ //memcpy(&p, &ac.priv, sizeof(unsigned int));
+ p = (ac.priv.userStat << 0) +
+ (ac.priv.userConf << 2) +
+ (ac.priv.userCash << 4) +
+ (ac.priv.userPasswd << 6) +
+ (ac.priv.userAddDel << 8) +
+ (ac.priv.adminChg << 10) +
+ (ac.priv.tariffChg << 12);
+ strprintf(&s, "<admin login=\"%s\" priv=\"%d\"/>", ac.login.c_str(), p);
+ answerList->push_back(s);
+ }
+admins->CloseSearch(h);
+answerList->push_back("</Admins>");
+}
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// DEL ADMIN
+//-----------------------------------------------------------------------------
+int PARSER_DEL_ADMIN::ParseStart(void *, const char *el, const char **attr)
+{
+strError = "";
+if (strcasecmp(el, "DelAdmin") == 0)
+ {
+ adminToDel = attr[1];
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int PARSER_DEL_ADMIN::ParseEnd(void *, const char *el)
+{
+if (strcasecmp(el, "DelAdmin") == 0)
+ {
+ CreateAnswer();
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+void PARSER_DEL_ADMIN::CreateAnswer()
+{
+//answerList->clear();
+answerList->erase(answerList->begin(), answerList->end());
+
+if (admins->Del(adminToDel, currAdmin) == 0)
+ {
+ answerList->push_back("<DelAdmin Result=\"Ok\"/>");
+ }
+else
+ {
+ string s;
+ strprintf(&s, "<DelAdmin Result=\"Error. %s\"/>", admins->GetStrError().c_str());
+ answerList->push_back(s);
+ }
+}
+//-----------------------------------------------------------------------------
+int PARSER_DEL_ADMIN::CheckAttr(const char **attr)
+{
+/* <DelAdmin login=\"admin\">
+ * attr[0] = "login" (word login)
+ * attr[1] = login, value of login
+ * attr[2] = NULL */
+
+if (strcasecmp(attr[0], "login") == 0 && attr[1] && !attr[2])
+ {
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+// ADD ADMIN
+//-----------------------------------------------------------------------------
+int PARSER_ADD_ADMIN::ParseStart(void *, const char *el, const char **attr)
+{
+if (strcasecmp(el, "AddAdmin") == 0)
+ {
+ adminToAdd = attr[1];
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int PARSER_ADD_ADMIN::ParseEnd(void *, const char *el)
+{
+//answerList->clear();
+answerList->erase(answerList->begin(), answerList->end());
+
+if (strcasecmp(el, "AddAdmin") == 0)
+ {
+ CreateAnswer();
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+void PARSER_ADD_ADMIN::CreateAnswer()
+{
+//answerList->clear();
+answerList->erase(answerList->begin(), answerList->end());
+
+if (admins->Add(adminToAdd, currAdmin) == 0)
+ {
+ answerList->push_back("<AddAdmin Result=\"Ok\"/>");
+ }
+else
+ {
+ string s;
+ strprintf(&s, "<AddAdmin Result=\"Error. %s\"/>", admins->GetStrError().c_str());
+ answerList->push_back(s);
+ }
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// CHG ADMIN
+//-----------------------------------------------------------------------------
+int PARSER_CHG_ADMIN::ParseStart(void *, const char *el, const char **attr)
+{
+if (strcasecmp(el, "ChgAdmin") == 0)
+ {
+ for (int i = 0; i < 6; i+=2)
+ {
+ printfd(__FILE__, "PARSER_CHG_ADMIN::attr[%d] = %s\n", i, attr[i]);
+ if (attr[i] == NULL)
+ break;
+
+ if (strcasecmp(attr[i], "Login") == 0)
+ {
+ login = attr[i + 1];
+ continue;
+ }
+
+ if (strcasecmp(attr[i], "Priv") == 0)
+ {
+ privAsString = attr[i + 1];
+ continue;
+ }
+
+ if (strcasecmp(attr[i], "Password") == 0)
+ {
+ password = attr[i + 1];
+ continue;
+ }
+ }
+
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int PARSER_CHG_ADMIN::ParseEnd(void *, const char *el)
+{
+if (strcasecmp(el, "ChgAdmin") == 0)
+ {
+ CreateAnswer();
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+void PARSER_CHG_ADMIN::CreateAnswer()
+{
+answerList->erase(answerList->begin(), answerList->end());
+
+ADMIN_CONF conf;
+conf.login = login;
+if (!login.res_empty())
+ {
+ string s;
+ //if (admins->FindAdmin(login.data()) != NULL)
+ // {
+ if (!password.res_empty())
+ conf.password = password.data();
+
+ if (!privAsString.res_empty())
+ {
+ int p = 0;
+ if (str2x(privAsString.data().c_str(), p) < 0)
+ {
+ strprintf(&s, "<ChgAdmin Result = \"Incorrect parameter Priv.\"/>" );
+ answerList->push_back(s);
+ return;
+ }
+ //memcpy(&conf.priv, &p, sizeof(conf.priv));
+ conf.priv.userStat = (p & 0x0003) >> 0x00; // 1+2
+ conf.priv.userConf = (p & 0x000C) >> 0x02; // 4+8
+ conf.priv.userCash = (p & 0x0030) >> 0x04; // 10+20
+ conf.priv.userPasswd = (p & 0x00C0) >> 0x06; // 40+80
+ conf.priv.userAddDel = (p & 0x0300) >> 0x08; // 100+200
+ conf.priv.adminChg = (p & 0x0C00) >> 0x0A; // 400+800
+ conf.priv.tariffChg = (p & 0x3000) >> 0x0C; // 1000+2000
+ }
+
+ if (admins->Change(conf, currAdmin) != 0)
+ {
+ strprintf(&s, "<ChgAdmin Result = \"%s\"/>", admins->GetStrError().c_str());
+ answerList->push_back(s);
+ }
+ else
+ {
+ answerList->push_back("<ChgAdmin Result = \"Ok\"/>");
+ }
+ return;
+ // }
+ //strprintf(&s, "<ChgAdmin Result = \"%s\"/>", admins->GetStrError().c_str());
+ //answerList->push_back(s);
+ //return;
+ }
+else
+ {
+ answerList->push_back("<ChgAdmin Result = \"Incorrect parameter login.\"/>");
+ }
+}
+//-----------------------------------------------------------------------------*/
+
--- /dev/null
+//#include <stdio.h>
+#include <cstring>
+
+#include "parser.h"
+
+const int pt_mega = 1024 * 1024;
+//-----------------------------------------------------------------------------
+// GET TARIFFS
+//-----------------------------------------------------------------------------
+int PARSER_GET_TARIFFS::ParseStart(void *, const char * el, const char **)
+{
+if (strcasecmp(el, "GetTariffs") == 0)
+ {
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int PARSER_GET_TARIFFS::ParseEnd(void *, const char * el)
+{
+if (strcasecmp(el, "GetTariffs") == 0)
+ {
+ CreateAnswer();
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+void PARSER_GET_TARIFFS::CreateAnswer()
+{
+string s;
+char vs[100];
+int hd, hn, md, mn;
+
+answerList->erase(answerList->begin(), answerList->end());
+
+answerList->push_back("<Tariffs>");
+
+std::list<TARIFF_DATA> dataList;
+tariffs->GetTariffsData(&dataList);
+std::list<TARIFF_DATA>::const_iterator it = dataList.begin();
+for (; it != dataList.end(); ++it)
+ {
+ s = "<tariff name=\"" + it->tariffConf.name + "\">";
+ answerList->push_back(s);
+
+ for (int j = 0; j < DIR_NUM; j++)
+ {
+ hd = it->dirPrice[j].hDay;
+ md = it->dirPrice[j].mDay;
+
+ hn = it->dirPrice[j].hNight;
+ mn = it->dirPrice[j].mNight;
+
+ strprintf(&s, "<Time%d value=\"%d:%d-%d:%d\"/>", j, hd, md, hn, mn);
+ answerList->push_back(s);
+ }
+
+ strprintf(&s, " <PriceDayA value=\"");
+ for (int i = 0; i < DIR_NUM; i++)
+ {
+ snprintf(vs, 100, "%.5f%s", it->dirPrice[i].priceDayA * pt_mega, i+1 == DIR_NUM?"":"/");
+ s += vs;
+ }
+ s += "\"/>";
+ answerList->push_back(s);
+
+ strprintf(&s, " <PriceDayB value=\"");
+ for (int i = 0; i < DIR_NUM; i++)
+ {
+ snprintf(vs, 100, "%.5f%s", it->dirPrice[i].priceDayB * pt_mega, i+1 == DIR_NUM?"":"/");
+ s += vs;
+ }
+ s += "\"/>";
+ answerList->push_back(s);
+
+ strprintf(&s, " <PriceNightA value=\"");
+ for (int i = 0; i < DIR_NUM; i++)
+ {
+ snprintf(vs, 100, "%.5f%s", it->dirPrice[i].priceNightA * pt_mega, i+1 == DIR_NUM?"":"/");
+ s += vs;
+ }
+ s += "\"/>";
+ answerList->push_back(s);
+
+ strprintf(&s, " <PriceNightB value=\"");
+ for (int i = 0; i < DIR_NUM; i++)
+ {
+ snprintf(vs, 100, "%.5f%s", it->dirPrice[i].priceNightB * pt_mega, i+1 == DIR_NUM?"":"/");
+ s += vs;
+ }
+ s += "\"/>";
+ answerList->push_back(s);
+
+ strprintf(&s, " <Threshold value=\"");
+ for (int i = 0; i < DIR_NUM; i++)
+ {
+ snprintf(vs, 100, "%d%s", it->dirPrice[i].threshold, i+1 == DIR_NUM?"":"/");
+ s += vs;
+ }
+ s += "\"/>";
+ answerList->push_back(s);
+
+ strprintf(&s, " <SinglePrice value=\"");
+ for (int i = 0; i < DIR_NUM; i++)
+ {
+ snprintf(vs, 100, "%d%s", it->dirPrice[i].singlePrice, i+1 == DIR_NUM?"":"/");
+ s += vs;
+ }
+ s += "\"/>";
+ answerList->push_back(s);
+
+ strprintf(&s, " <NoDiscount value=\"");
+ for (int i = 0; i < DIR_NUM; i++)
+ {
+ snprintf(vs, 100, "%d%s", it->dirPrice[i].noDiscount, i+1 == DIR_NUM?"":"/");
+ s += vs;
+ }
+ s += "\"/>";
+ answerList->push_back(s);
+
+ strprintf(&s, " <Fee value=\"%.5f\"/>", it->tariffConf.fee);
+ answerList->push_back(s);
+
+ strprintf(&s, " <PassiveCost value=\"%.5f\"/>", it->tariffConf.passiveCost);
+ answerList->push_back(s);
+
+ strprintf(&s, " <Free value=\"%.5f\"/>", it->tariffConf.free);
+ answerList->push_back(s);
+
+ switch (it->tariffConf.traffType)
+ {
+ case TRAFF_UP:
+ answerList->push_back("<TraffType value=\"up\"/>");
+ break;
+ case TRAFF_DOWN:
+ answerList->push_back("<TraffType value=\"down\"/>");
+ break;
+ case TRAFF_UP_DOWN:
+ answerList->push_back("<TraffType value=\"up+down\"/>");
+ break;
+ case TRAFF_MAX:
+ answerList->push_back("<TraffType value=\"max\"/>");
+ break;
+ }
+
+ answerList->push_back("</tariff>");
+ }
+answerList->push_back("</Tariffs>");
+}
+//-----------------------------------------------------------------------------
+// ADD TARIFF
+//-----------------------------------------------------------------------------
+int PARSER_ADD_TARIFF::ParseStart(void *, const char * el, const char ** attr)
+{
+if (strcasecmp(el, "AddTariff") == 0)
+ {
+ if (attr[1])
+ {
+ tariffToAdd = attr[1];
+ }
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int PARSER_ADD_TARIFF::ParseEnd(void *, const char * el)
+{
+if (strcasecmp(el, "AddTariff") == 0)
+ {
+ CreateAnswer();
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+void PARSER_ADD_TARIFF::CreateAnswer()
+{
+//answerList->clear();
+answerList->erase(answerList->begin(), answerList->end());
+
+if (tariffs->Add(tariffToAdd, currAdmin) == 0)
+ {
+ answerList->push_back("<AddTariff Result=\"Ok\"/>");
+ }
+else
+ {
+ string s;
+ strprintf(&s, "<AddTariff Result=\"Error. %s\"/>", tariffs->GetStrError().c_str());
+ answerList->push_back(s);
+ }
+}
+//-----------------------------------------------------------------------------
+// DEL TARIFF
+//-----------------------------------------------------------------------------
+int PARSER_DEL_TARIFF::ParseStart(void *, const char * el, const char ** attr)
+{
+strError = "";
+if (strcasecmp(el, "DelTariff") == 0)
+ {
+ tariffToDel = attr[1];
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int PARSER_DEL_TARIFF::ParseEnd(void *, const char * el)
+{
+if (strcasecmp(el, "DelTariff") == 0)
+ {
+ CreateAnswer();
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+void PARSER_DEL_TARIFF::CreateAnswer()
+{
+//answerList->clear();
+answerList->erase(answerList->begin(), answerList->end());
+
+if (users->TariffInUse(tariffToDel))
+ {
+ string s;
+ strprintf(&s, "<DelTariff Result=\"Error. Tariff \'%s\' cannot be deleted. Tariff in use.\"/>", tariffToDel.c_str());
+ answerList->push_back(s);
+ return;
+ }
+
+if (tariffs->Del(tariffToDel, currAdmin) == 0)
+ {
+ answerList->push_back("<DelTariff Result=\"Ok\"/>");
+ }
+else
+ {
+ string s;
+ strprintf(&s, "<DelTariff Result=\"Error. %s\"/>", tariffs->GetStrError().c_str());
+ answerList->push_back(s);
+ }
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// CHG TARIFF
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+int PARSER_CHG_TARIFF::ParseSlashedIntParams(int paramsNum, const string & s, int * params)
+{
+char * str = new char[s.size() + 1];
+char * p;
+strcpy(str, s.c_str());
+p = strtok(str, "/");
+
+for (int i = 0; i < paramsNum; i++)
+ {
+ if (p == NULL)
+ {
+ delete[] str;
+ return -1;
+ }
+
+ if (str2x(p, params[i]) != 0)
+ {
+ delete[] str;
+ return -1;
+ }
+
+ p = strtok(NULL, "/");
+ }
+
+delete[] str;
+return 0;
+}
+//-----------------------------------------------------------------------------
+int PARSER_CHG_TARIFF::ParseSlashedDoubleParams(int paramsNum, const string & s, double * params)
+{
+char * str = new char[s.size() + 1];
+char * p;
+strcpy(str, s.c_str());
+p = strtok(str, "/");
+
+for (int i = 0; i < paramsNum; i++)
+ {
+ if (p == NULL)
+ {
+ delete[] str;
+ return -1;
+ }
+
+ if (strtodouble2(p, params[i]) != 0)
+ {
+ delete[] str;
+ return -1;
+ }
+
+ p = strtok(NULL, "/");
+ }
+
+delete[] str;
+return 0;
+}
+//-----------------------------------------------------------------------------
+int PARSER_CHG_TARIFF::ParseStart(void *, const char * el, const char ** attr)
+{
+char st[50];
+double price[DIR_NUM];
+int t[DIR_NUM];
+depth++;
+
+if (depth == 1)
+ {
+ if (strcasecmp(el, "SetTariff") == 0)
+ {
+ td.tariffConf.name = attr[1];
+ return 0;
+ }
+ }
+else
+ {
+ string s;
+
+ if (strcasecmp(el, "PriceDayA") == 0)
+ {
+ s = attr[1];
+ if (ParseSlashedDoubleParams(DIR_NUM, s, price) == 0)
+ for (int j = 0; j < DIR_NUM; j++)
+ td.dirPrice[j].priceDayA = price[j] / pt_mega;
+ return 0;
+ }
+
+ if (strcasecmp(el, "PriceDayB") == 0)
+ {
+ s = attr[1];
+ if (ParseSlashedDoubleParams(DIR_NUM, s, price) == 0)
+ for (int j = 0; j < DIR_NUM; j++)
+ td.dirPrice[j].priceDayB = price[j] / pt_mega;
+ return 0;
+ }
+
+
+ if (strcasecmp(el, "PriceNightA") == 0)
+ {
+ s = attr[1];
+ if (ParseSlashedDoubleParams(DIR_NUM, s, price) == 0)
+ for (int j = 0; j < DIR_NUM; j++)
+ td.dirPrice[j].priceNightA = price[j] / pt_mega;
+ return 0;
+ }
+
+ if (strcasecmp(el, "PriceNightB") == 0)
+ {
+ s = attr[1];
+ if (ParseSlashedDoubleParams(DIR_NUM, s, price) == 0)
+ for (int j = 0; j < DIR_NUM; j++)
+ td.dirPrice[j].priceNightB = price[j] / pt_mega;
+ return 0;
+ }
+
+ if (strcasecmp(el, "Threshold") == 0)
+ {
+ s = attr[1];
+ if (ParseSlashedIntParams(DIR_NUM, s, t) == 0)
+ for (int j = 0; j < DIR_NUM; j++)
+ td.dirPrice[j].threshold = t[j];
+ return 0;
+ }
+
+ if (strcasecmp(el, "SinglePrice") == 0)
+ {
+ s = attr[1];
+ if (ParseSlashedIntParams(DIR_NUM, s, t) == 0)
+ for (int j = 0; j < DIR_NUM; j++)
+ td.dirPrice[j].singlePrice = t[j];
+ return 0;
+ }
+
+ if (strcasecmp(el, "NoDiscount") == 0)
+ {
+ s = attr[1];
+ if (ParseSlashedIntParams(DIR_NUM, s, t) == 0)
+ for (int j = 0; j < DIR_NUM; j++)
+ td.dirPrice[j].noDiscount = t[j];
+ return 0;
+ }
+
+ for (int j = 0; j < DIR_NUM; j++)
+ {
+ snprintf(st, 50, "Time%d", j);
+ if (strcasecmp(el, st) == 0)
+ {
+ int h1, m1, h2, m2;
+ if (ParseTariffTimeStr(attr[1], h1, m1, h2, m2) == 0)
+ {
+ td.dirPrice[j].hDay = h1;
+ td.dirPrice[j].mDay = m1;
+ td.dirPrice[j].hNight = h2;
+ td.dirPrice[j].mNight = m2;
+ }
+ return 0;
+ }
+ }
+
+ if (strcasecmp(el, "Fee") == 0)
+ {
+ double fee;
+ if (strtodouble2(attr[1], fee) == 0)
+ td.tariffConf.fee = fee;
+ return 0;
+ }
+
+ if (strcasecmp(el, "PassiveCost") == 0)
+ {
+ double pc;
+ if (strtodouble2(attr[1], pc) == 0)
+ td.tariffConf.passiveCost = pc;
+ return 0;
+ }
+ if (strcasecmp(el, "Free") == 0)
+ {
+ double free;
+ if (strtodouble2(attr[1], free) == 0)
+ td.tariffConf.free = free;
+ return 0;
+ }
+
+ if (strcasecmp(el, "TraffType") == 0)
+ {
+ if (strcasecmp(attr[1], "up") == 0)
+ {
+ td.tariffConf.traffType = TRAFF_UP;
+ return 0;
+ }
+
+ if (strcasecmp(attr[1], "down") == 0)
+ {
+ td.tariffConf.traffType = TRAFF_DOWN;
+ return 0;
+ }
+ if (strcasecmp(attr[1], "up+down") == 0)
+ {
+ td.tariffConf.traffType = TRAFF_UP_DOWN;
+ return 0;
+ }
+ if (strcasecmp(attr[1], "max") == 0)
+ {
+ td.tariffConf.traffType = TRAFF_MAX;
+ return 0;
+ }
+ return 0;
+ }
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int PARSER_CHG_TARIFF::ParseEnd(void *, const char * el)
+{
+if (depth == 1)
+ {
+ if (strcasecmp(el, "SetTariff") == 0)
+ {
+ CreateAnswer();
+ depth--;
+ return 0;
+ }
+ }
+
+depth--;
+return -1;
+}
+//-----------------------------------------------------------------------------
+void PARSER_CHG_TARIFF::CreateAnswer()
+{
+answerList->erase(answerList->begin(), answerList->end());
+
+if (!td.tariffConf.name.data().empty())
+ {
+ TARIFF_DATA tariffData = td.GetData();
+ if (tariffs->Chg(tariffData, currAdmin) == 0)
+ {
+ answerList->push_back("<SetTariff Result=\"ok\"/>");
+ return;
+ }
+ else
+ {
+ string s;
+ strprintf(&s, "<SetTariff Result=\"Change tariff error! %s\"/>", tariffs->GetStrError().c_str());
+ answerList->push_back(s);
+ return;
+ }
+ }
+answerList->push_back("<SetTariff Result=\"Change tariff error!\"/>");
+}
+//-----------------------------------------------------------------------------
--- /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
+ */
+
+/*******************************************************************
+*
+* DESCRIPTION: æÁÊÌ Ó ÏÓÎÏ×ÎÙÍÉ ÆÕÎËÃÉÑÍÉ ÄÌÑ ÓÅÔÅ×ÏÇÏ ÏÂÍÅÎÁ ÄÁÎÎÙÍÉ
+* Ó ÍÅÎÅÄÖÅÒÏÍ ËÌÉÅÎÔÏ×. ðÒÉÅÍ, ÐÅÒÅÄÁÞÁ É ÛÉÆÒÏ×ÁÎÉÅ ÓÏÏÂÝÅÎÉÊ.
+*
+* AUTHOR: Boris Mikhailenko <stg34@stargazer.dp.ua>
+*
+* $Revision: 1.24 $
+* $Date: 2010/10/04 20:24:54 $
+*
+*******************************************************************/
+
+/*#include <unistd.h>
+#include <stdio.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netinet/tcp.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <pthread.h>*/
+
+#include <cerrno>
+#include <csignal>
+
+#include "configproto.h"
+#include "blowfish.h"
+
+enum CONF_STATE
+ {
+ confHdr,
+ confLogin,
+ confLoginCipher,
+ confData
+ };
+
+enum
+ {
+ ans_ok = 0,
+ ans_err
+ };
+
+//-----------------------------------------------------------------------------
+int CONFIGPROTO::Prepare()
+{
+list<string> ansList; //óÀÄÁ ÂÕÄÅÔ ÐÏÍÅÝÅÎ ÏÔ×ÅÔ ÄÌÑ ÍÅÎÅÄÖÅÒÁ ËÌÉÅÎÔÏ×
+int res;
+struct sockaddr_in listenAddr;
+
+sigset_t sigmask, oldmask;
+sigemptyset(&sigmask);
+sigaddset(&sigmask, SIGINT);
+sigaddset(&sigmask, SIGTERM);
+sigaddset(&sigmask, SIGUSR1);
+sigaddset(&sigmask, SIGHUP);
+pthread_sigmask(SIG_BLOCK, &sigmask, &oldmask);
+
+listenSocket = socket(PF_INET, SOCK_STREAM, 0);
+
+if (listenSocket < 0)
+ {
+ errorStr = "Create NET_CONFIGURATOR socket failed.";
+ return -1;
+ }
+
+listenAddr.sin_family = PF_INET;
+listenAddr.sin_port = htons(port);
+listenAddr.sin_addr.s_addr = inet_addr("0.0.0.0");
+
+int lng = 1;
+
+if (0 != setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, &lng, 4))
+ {
+ errorStr = "Setsockopt failed. " + string(strerror(errno));
+ return -1;
+ }
+
+res = bind(listenSocket, (struct sockaddr*)&listenAddr, sizeof(listenAddr));
+
+if (res == -1)
+ {
+ errorStr = "Bind admin socket failed";
+ return -1;
+ }
+
+res = listen(listenSocket, 0);
+if (res == -1)
+ {
+ errorStr = "Listen admin socket failed";
+ return -1;
+ }
+outerAddrLen = sizeof(outerAddr);
+
+/*if (0 != fcntl(listenSocket, F_SETFL, O_NONBLOCK))
+ {
+ errorStr = "fcntl error!";
+ return -1;
+ }*/
+
+errorStr = "";
+nonstop = true;
+return 0;
+}
+//-----------------------------------------------------------------------------
+int CONFIGPROTO::Stop()
+{
+nonstop = false;
+close(listenSocket);
+//TODO: Idiotism
+int sock;
+struct sockaddr_in addr;
+socklen_t addrLen;
+addr.sin_family = PF_INET;
+addr.sin_port = htons(port);
+addr.sin_addr.s_addr = inet_addr("127.0.0.1");
+
+addrLen = sizeof(outerAddr);
+sock = socket(PF_INET, SOCK_STREAM, 0);
+connect(sock, (sockaddr*)&addr, addrLen);
+close(sock);
+//Idiotism end
+return 0;
+}
+//-----------------------------------------------------------------------------
+// æÕÎËÃÉÑ ÏÂÝÅÎÉÑ Ó ËÏÎÆÉÇÕÒÁÔÏÒÏÍ
+void * CONFIGPROTO::Run(void * a)
+{
+/*
+ * Function Name:ReciveSendConf
+ * Parameters: void * a ÕËÁÚÁÔÅÌØ ÎÁ ÜËÚÅÍÐÌÑÒ ËÌÁÓÓÁ CONFIGPROTO
+ * Description: üÔÁ ÆÕÎËÃÉÑ ÏÂÅÓÐÅÞÉ×ÁÅÔ ÓÅÔÅ×ÏÅ ×ÚÁÉÍÏÄÅÊÓÔ×ÉÅ
+ * Ó íÅÎÅÄÖÅÒÏÍ ëÌÉÅÎÔÏ×. ÷ ÅÅ ÚÁÄÁÞÉ ×ÈÏÄÉÔ: ÐÒÉÅÍ ÚÁÐÒÏÓÏ× ÐÏ TCP/IP
+ * ÉÈ ÒÁÓÛÉÆÒÏ×ËÁ, ÐÅÒÅÄÁÞÁ ÐÒÉÎÑÔÙÈ ÄÁÎÎÙÈ ÁÎÁÌÉÚÁÔÏÒÕ É ÏÔÐÒÁ×ËÁ ÏÔ×ÅÔÁ ÎÁÚÁÄ.
+ * Returns: ×ÏÚ×ÒÁÝÁÅÔ NULL
+ */
+
+CONFIGPROTO * cp = (CONFIGPROTO*)a;
+cp->state = confHdr;
+
+while (cp->nonstop)
+ {
+ cp->state = confHdr;
+ cp->outerSocket = accept(cp->listenSocket,
+ (struct sockaddr*)(&cp->outerAddr),
+ &cp->outerAddrLen);
+
+ if (!cp->nonstop)
+ {
+ continue;
+ }
+
+ if (cp->outerSocket == -1)
+ {
+ printfd(__FILE__, "accept failed\n");
+ usleep(100000);
+ continue;
+ }
+
+ cp->adminIP = *(unsigned int*)&(cp->outerAddr.sin_addr);
+
+ /* TODO
+ if (!cp->hostAllow->HostAllowed(cp->adminIP))
+ {
+ close(outerSocket);
+ continue;
+ }*/
+
+ printfd(__FILE__, "Connection accepted from %s\n", inet_ntostring(cp->outerAddr.sin_addr.s_addr).c_str());
+
+ if (cp->state == confHdr)
+ {
+ if (cp->RecvHdr(cp->outerSocket) < 0)
+ {
+ close(cp->outerSocket);
+ continue;
+ }
+ if (cp->state == confLogin)
+ {
+ if (cp->SendHdrAnswer(cp->outerSocket, ans_ok) < 0)
+ {
+ close(cp->outerSocket);
+ continue;
+ }
+
+ if (cp->RecvLogin(cp->outerSocket) < 0)
+ {
+ close(cp->outerSocket);
+ continue;
+ }
+
+ if (cp->state == confLoginCipher)
+ {
+ if (cp->SendLoginAnswer(cp->outerSocket, ans_ok) < 0)
+ {
+ close(cp->outerSocket);
+ continue;
+ }
+ if (cp->RecvLoginS(cp->outerSocket) < 0)
+ {
+ close(cp->outerSocket);
+ continue;
+ }
+
+ if (cp->state == confData)
+ {
+ if (cp->SendLoginSAnswer(cp->outerSocket, ans_ok) < 0)
+ {
+ close(cp->outerSocket);
+ continue;
+ }
+ if (cp->RecvData(cp->outerSocket) < 0)
+ {
+ close(cp->outerSocket);
+ continue;
+ }
+ cp->state = confHdr;
+ }
+ else
+ {
+ if (cp->SendLoginSAnswer(cp->outerSocket, ans_err) < 0)
+ {
+ close(cp->outerSocket);
+ continue;
+ }
+ cp->WriteLogAccessFailed(cp->adminIP);
+ }
+ }
+ else
+ {
+ cp->WriteLogAccessFailed(cp->adminIP);
+ }
+ }
+ else
+ {
+ cp->WriteLogAccessFailed(cp->adminIP);
+ if (cp->SendHdrAnswer(cp->outerSocket, ans_err) < 0)
+ {
+ close(cp->outerSocket);
+ continue;
+ }
+ }
+ }
+ else
+ {
+ cp->WriteLogAccessFailed(cp->adminIP);
+ }
+ close(cp->outerSocket);
+ }
+
+return NULL;
+}
+//-----------------------------------------------------------------------------
+int CONFIGPROTO::RecvHdr(int sock)
+{
+char buf[sizeof(STG_HEADER)];
+memset(buf, 0, sizeof(STG_HEADER));
+int ret;
+int stgHdrLen = strlen(STG_HEADER);
+for (int i = 0; i < stgHdrLen; i++)
+ {
+ ret = recv(sock, &buf[i], 1, 0);
+ if (ret <= 0)
+ {
+ state = confHdr;
+ return -1;
+ }
+ }
+
+if (0 == strncmp(buf, STG_HEADER, strlen(STG_HEADER)))
+ {
+ state = confLogin;
+ return 0;
+ }
+else
+ {
+ SendError("Bad request");
+ }
+
+state = confHdr;
+return -1;
+}
+//-----------------------------------------------------------------------------
+int CONFIGPROTO::SendHdrAnswer(int sock, int err)
+{
+int ret;
+
+if (err)
+ {
+ ret = send(sock, ERR_HEADER, sizeof(ERR_HEADER)-1, 0);
+ if (ret < 0)
+ {
+ WriteServLog("send ERR_HEADER error in SendHdrAnswer.");
+ return -1;
+ }
+ }
+else
+ {
+ ret = send(sock, OK_HEADER, sizeof(OK_HEADER)-1, 0);
+ if (ret < 0)
+ {
+ WriteServLog("send OK_HEADER error in SendHdrAnswer.");
+ return -1;
+ }
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int CONFIGPROTO::RecvLogin(int sock)
+{
+char login[ADM_LOGIN_LEN+1];
+int ret;
+
+memset(login, 0, ADM_LOGIN_LEN + 1);
+
+//printfd(__FILE__, "RecvLogin\n");
+
+/*for (int i = 0; i < ADM_LOGIN_LEN; i++)
+ {
+ ret = recv(sock, &login[i], 1, 0);
+
+ if (ret <= 0)
+ {
+ close(sock);
+ state = confHdr;
+ return ENODATA;
+ }
+ }*/
+
+ret = recv(sock, login, ADM_LOGIN_LEN, 0);
+
+if (ret < 0)
+ {
+ // Error in network
+ close(sock);
+ state = confHdr;
+ return ENODATA;
+ }
+
+if (ret < ADM_LOGIN_LEN)
+ {
+ // Error in protocol
+ close(sock);
+ state = confHdr;
+ return ENODATA;
+ }
+
+if (admins->FindAdmin(login, &currAdmin))
+ {
+ // Admin not found
+ close(sock);
+ state = confHdr;
+ return ENODATA;
+ }
+currAdmin.SetAdminIP(adminIP);
+adminLogin = login;
+state = confLoginCipher;
+return 0;
+}
+//-----------------------------------------------------------------------------
+int CONFIGPROTO::SendLoginAnswer(int sock, int)
+{
+int ret;
+
+ret = send(sock, OK_LOGIN, sizeof(OK_LOGIN)-1, 0);
+if (ret < 0)
+ {
+ WriteServLog("Send OK_LOGIN error in SendLoginAnswer.");
+ return -1;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int CONFIGPROTO::RecvLoginS(int sock)
+{
+char loginS[ADM_LOGIN_LEN + 1];
+char login[ADM_LOGIN_LEN + 1];
+int ret;
+BLOWFISH_CTX ctx;
+memset(loginS, 0, ADM_LOGIN_LEN + 1);
+
+//printfd(__FILE__, "RecvLoginS\n");
+
+/*for (int i = 0; i < ADM_LOGIN_LEN; i++)
+ {
+ ret = recv(sock, &loginS[i], 1, 0);
+
+ if (ret <= 0)
+ {
+ //printfd(__FILE__, "RecvLoginS close\n");
+ close(sock);
+ state = confHdr;
+ return ENODATA;
+ }
+ }*/
+
+int total = 0;
+
+while (total < ADM_LOGIN_LEN)
+ {
+ ret = recv(sock, &loginS[total], ADM_LOGIN_LEN - total, 0);
+
+ if (ret < 0)
+ {
+ // Network error
+ printfd(__FILE__, "recv error: '%s'\n", strerror(errno));
+ close(sock);
+ state = confHdr;
+ return ENODATA;
+ }
+
+ total += ret;
+ }
+
+// TODO: implement select on socket
+/*if (total < ADM_LOGIN_LEN)
+ {
+ // Protocol error
+ printfd(__FILE__, "Protocol error. Need %d bytes of cryptologin. Got %d bytes.\n", ADM_LOGIN_LEN, ret);
+ close(sock);
+ state = confHdr;
+ return ENODATA;
+ }*/
+
+if (currAdmin.GetLogin() == "")
+ {
+ state = confHdr;
+ return ENODATA;
+ }
+
+EnDecodeInit(currAdmin.GetPassword().c_str(), ADM_PASSWD_LEN, &ctx);
+
+for (int i = 0; i < ADM_LOGIN_LEN/8; i++)
+ {
+ DecodeString(login + i*8, loginS + i*8, &ctx);
+ }
+
+if (currAdmin == admins->GetNoAdmin())
+ {
+ // If there are no admins registered in the system - give access with any password
+ state = confData;
+ return 0;
+ }
+
+if (strncmp(currAdmin.GetLogin().c_str(), login, ADM_LOGIN_LEN) != 0)
+ {
+ state = confHdr;
+ return ENODATA;
+ }
+
+state = confData;
+return 0;
+}
+//-----------------------------------------------------------------------------
+int CONFIGPROTO::SendLoginSAnswer(int sock, int err)
+{
+int ret;
+
+if (err)
+ {
+ ret = send(sock, ERR_LOGINS, sizeof(ERR_LOGINS)-1, 0);
+ if (ret < 0)
+ {
+ WriteServLog("send ERR_LOGIN error in SendLoginAnswer.");
+ return -1;
+ }
+ }
+else
+ {
+ ret = send(sock, OK_LOGINS, sizeof(OK_LOGINS)-1, 0);
+ if (ret < 0)
+ {
+ WriteServLog("send OK_LOGINS error in SendLoginSAnswer.");
+ return -1;
+ }
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int CONFIGPROTO::RecvData(int sock)
+{
+//printfd(__FILE__, "RecvData\n");
+//int n = 0;
+int ret;
+char bufferS[8];
+char buffer[9];
+
+buffer[8] = 0;
+
+requestList.clear();
+BLOWFISH_CTX ctx;
+
+EnDecodeInit(currAdmin.GetPassword().c_str(), ADM_PASSWD_LEN, &ctx);
+
+while (1)
+ {
+ /*ret = recv(sock, &bufferS[n++], 1, 0);
+ if (ret <= 0)
+ {
+ //printfd(__FILE__, "RecvData close\n");
+ close(sock);
+ return 0;
+ }*/
+ int total = 0;
+ bool done = false;
+ while (total < 8)
+ {
+ ret = recv(sock, &bufferS[total], 8 - total, 0);
+ if (ret < 0)
+ {
+ // Network error
+ close(sock);
+ return 0;
+ }
+
+ if (ret < 8)
+ {
+ if (memchr(buffer, 0, ret) != NULL)
+ {
+ done = true;
+ break;
+ }
+ }
+
+ total += ret;
+ }
+
+ DecodeString(buffer, bufferS, &ctx);
+ requestList.push_back(std::string(buffer, total));
+
+ if (done || memchr(buffer, 0, total) != NULL)
+ {
+ // ëÏÎÅà ÐÏÓÙÌËÉ
+ if (ParseCommand())
+ {
+ SendError("Bad command");
+ }
+ return SendDataAnswer(sock);
+ }
+
+ /*if (n == 8)
+ {
+ n = 0;
+ DecodeString(buffer, bufferS, &ctx);
+ requestList.push_back(std::string(buffer, 8));
+ for (int j = 0; j < 8; j++)
+ {
+ if (buffer[j] == 0)
+ {
+ // ëÏÎÅà ÐÏÓÙÌËÉ
+ if (ParseCommand())
+ {
+ SendError("Bad command");
+ }
+ return SendDataAnswer(sock);
+ }
+ }
+ }*/
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int CONFIGPROTO::SendDataAnswer(int sock)
+{
+list<string>::iterator li;
+li = answerList.begin();
+
+BLOWFISH_CTX ctx;
+
+char buff[8];
+char buffS[8];
+int n = 0;
+int k = 0;
+int ret = 0;
+
+EnDecodeInit(currAdmin.GetPassword().c_str(), ADM_PASSWD_LEN, &ctx);
+
+while (li != answerList.end())
+ {
+ while ((*li).c_str()[k])
+ {
+ buff[n%8] = (*li).c_str()[k];
+ n++;
+ k++;
+
+ if (n%8 == 0)
+ {
+ EncodeString(buffS, buff, &ctx);
+ ret = send(sock, buffS, 8, 0);
+ if (ret < 0)
+ {
+ return -1;
+ }
+ }
+ }
+ k = 0;// new node
+ li++;
+ }
+
+if (answerList.empty()) {
+ return 0;
+}
+
+buff[n%8] = 0;
+EncodeString(buffS, buff, &ctx);
+
+answerList.clear();
+
+return send(sock, buffS, 8, 0);
+}
+//-----------------------------------------------------------------------------
+void CONFIGPROTO::SendError(const char * text)
+{
+char s[255];
+answerList.clear();
+sprintf(s, "<Error value=\"%s\"/>", text);
+answerList.push_back(s);
+}
+//-----------------------------------------------------------------------------
+void CONFIGPROTO::WriteLogAccessFailed(uint32_t ip)
+{
+WriteServLog("Admin's connect failed. IP %s", inet_ntostring(ip).c_str());
+}
+//-----------------------------------------------------------------------------
+
+
+
--- /dev/null
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include "stgconfig.h"
+#include "../../../tariffs.h"
+#include "../../../admins.h"
+#include "../../../users.h"
+
+class STGCONFIG_CREATOR
+{
+private:
+ STG_CONFIG * stgconfig;
+
+public:
+ STGCONFIG_CREATOR()
+ : stgconfig(new STG_CONFIG())
+ {
+ };
+ ~STGCONFIG_CREATOR()
+ {
+ delete stgconfig;
+ };
+
+ STG_CONFIG * GetPlugin()
+ {
+ return stgconfig;
+ };
+};
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+STGCONFIG_CREATOR stgc;
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+STG_CONFIG_SETTINGS::STG_CONFIG_SETTINGS()
+ : port(0)
+{
+}
+//-----------------------------------------------------------------------------
+const string& STG_CONFIG_SETTINGS::GetStrError() const
+{
+return errorStr;
+}
+//-----------------------------------------------------------------------------
+int STG_CONFIG_SETTINGS::ParseIntInRange(const string & str, int min, int max, int * val)
+{
+if (str2x(str.c_str(), *val))
+ {
+ errorStr = "Incorrect value \'" + str + "\'.";
+ return -1;
+ }
+if (*val < min || *val > max)
+ {
+ errorStr = "Value \'" + str + "\' out of range.";
+ return -1;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int STG_CONFIG_SETTINGS::ParseSettings(const MODULE_SETTINGS & s)
+{
+int p;
+PARAM_VALUE pv;
+vector<PARAM_VALUE>::const_iterator pvi;
+///////////////////////////
+pv.param = "Port";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end())
+ {
+ errorStr = "Parameter \'Port\' not found.";
+ printfd(__FILE__, "Parameter 'Port' not found\n");
+ return -1;
+ }
+if (ParseIntInRange(pvi->value[0], 2, 65535, &p))
+ {
+ errorStr = "Cannot parse parameter \'Port\': " + errorStr;
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+port = p;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+uint16_t STG_CONFIG_SETTINGS::GetPort()
+{
+return port;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+BASE_PLUGIN * GetPlugin()
+{
+return stgc.GetPlugin();
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+const string STG_CONFIG::GetVersion() const
+{
+return "Stg configurator v.0.08";
+}
+//-----------------------------------------------------------------------------
+STG_CONFIG::STG_CONFIG()
+{
+isRunning = false;
+nonstop = false;
+}
+//-----------------------------------------------------------------------------
+void STG_CONFIG::SetUsers(USERS * u)
+{
+users = u;
+}
+//-----------------------------------------------------------------------------
+void STG_CONFIG::SetTariffs(TARIFFS * t)
+{
+tariffs = t;
+}
+//-----------------------------------------------------------------------------
+void STG_CONFIG::SetAdmins(ADMINS * a)
+{
+admins = a;
+}
+//-----------------------------------------------------------------------------
+void STG_CONFIG::SetStore(BASE_STORE * s)
+{
+store = s;
+}
+//-----------------------------------------------------------------------------
+void STG_CONFIG::SetStgSettings(const SETTINGS * s)
+{
+stgSettings = s;
+}
+//-----------------------------------------------------------------------------
+void STG_CONFIG::SetSettings(const MODULE_SETTINGS & s)
+{
+settings = s;
+}
+//-----------------------------------------------------------------------------
+int STG_CONFIG::ParseSettings()
+{
+int ret = stgConfigSettings.ParseSettings(settings);
+if (ret)
+ errorStr = stgConfigSettings.GetStrError();
+return ret;
+}
+//-----------------------------------------------------------------------------
+const string & STG_CONFIG::GetStrError() const
+{
+return errorStr;
+}
+//-----------------------------------------------------------------------------
+int STG_CONFIG::Start()
+{
+if (isRunning)
+ return 0;
+
+nonstop = true;
+
+config.SetPort(stgConfigSettings.GetPort());
+config.SetAdmins(admins);
+config.SetUsers(users);
+config.SetTariffs(tariffs);
+config.SetStgSettings(stgSettings);
+config.SetStore(store);
+
+if (config.Prepare())
+ {
+ errorStr = config.GetStrError();
+ return -1;
+ }
+
+if (pthread_create(&thread, NULL, Run, this))
+ {
+ errorStr = "Cannot create thread.";
+ printfd(__FILE__, "Cannot create thread\n");
+ return -1;
+ }
+errorStr = "";
+return 0;
+}
+//-----------------------------------------------------------------------------
+int STG_CONFIG::Stop()
+{
+if (!isRunning)
+ return 0;
+
+config.Stop();
+
+//5 seconds to thread stops itself
+int i;
+for (i = 0; i < 25; i++)
+ {
+ if (!isRunning)
+ break;
+
+ usleep(200000);
+ }
+
+//after 5 seconds waiting thread still running. now killing it
+if (isRunning)
+ {
+ //TODO pthread_cancel()
+ if (pthread_kill(thread, SIGINT))
+ {
+ errorStr = "Cannot kill thread.";
+ printfd(__FILE__, "Cannot kill thread\n");
+ return -1;
+ }
+ printfd(__FILE__, "STG_CONFIG killed\n");
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+bool STG_CONFIG::IsRunning()
+{
+return isRunning;
+}
+//-----------------------------------------------------------------------------
+void * STG_CONFIG::Run(void * d)
+{
+STG_CONFIG * stgConf = (STG_CONFIG *)d;
+stgConf->isRunning = true;
+
+stgConf->config.Run(&stgConf->config);
+
+stgConf->isRunning = false;
+return NULL;
+}
+//-----------------------------------------------------------------------------
+uint16_t STG_CONFIG::GetStartPosition() const
+{
+return 220;
+}
+//-----------------------------------------------------------------------------
+uint16_t STG_CONFIG::GetStopPosition() const
+{
+return 220;
+}
+//-----------------------------------------------------------------------------
+
+
--- /dev/null
+#include <string>
+#include <pthread.h>
+#include "base_plugin.h"
+#include "base_store.h"
+#include "configproto.h"
+//#include "user_ips.h"
+//#include "../../../users.h"
+
+using namespace std;
+
+extern "C" BASE_PLUGIN * GetPlugin();
+
+class STG_CONFIG;
+
+//-----------------------------------------------------------------------------
+/*template <typename varParamType>
+class CHG_BEFORE_NOTIFIER: public PROPERTY_NOTIFIER_BASE<varParamType>
+{
+public:
+ void Notify(const varParamType & oldValue, const varParamType & newValue)
+ {
+ auth->Unauthorize(user);
+ }
+ void SetUser(USER * u) { user = u; }
+ void SetAuthorizaror(const AUTH_AO * a) { auth = a; }
+
+private:
+ USER * user;
+ const AUTH_AO * auth;
+};
+//-----------------------------------------------------------------------------
+template <typename varParamType>
+class CHG_AFTER_NOTIFIER: public PROPERTY_NOTIFIER_BASE<varParamType>
+{
+public:
+ void Notify(const varParamType & oldValue, const varParamType & newValue)
+ {
+ auth->UpdateUserAuthorization(user);
+ }
+ void SetUser(USER * u) { user = u; }
+ void SetAuthorizaror(const AUTH_AO * a) { auth = a; }
+
+private:
+ USER * user;
+ const AUTH_AO * auth;
+};*/
+//-----------------------------------------------------------------------------
+class STG_CONFIG_SETTINGS
+{
+public:
+ STG_CONFIG_SETTINGS();
+ virtual ~STG_CONFIG_SETTINGS(){};
+ const string & GetStrError() const;
+ int ParseSettings(const MODULE_SETTINGS & s);
+ uint16_t GetPort();
+private:
+ int ParseIntInRange(const string & str, int min, int max, int * val);
+ string errorStr;
+ int port;
+};
+//-----------------------------------------------------------------------------
+class STG_CONFIG :public BASE_PLUGIN
+{
+public:
+ STG_CONFIG();
+ virtual ~STG_CONFIG(){};
+
+ void SetUsers(USERS * u);
+ void SetTariffs(TARIFFS * t);
+ void SetAdmins(ADMINS * a);
+ void SetStore(BASE_STORE * s);
+ void SetTraffcounter(TRAFFCOUNTER *){};
+ void SetStgSettings(const SETTINGS * s);
+ void SetSettings(const MODULE_SETTINGS & s);
+ int ParseSettings();
+
+ int Start();
+ int Stop();
+ int Reload() { return 0; };
+ bool IsRunning();
+
+ const string & GetStrError() const;
+ const string GetVersion() const;
+ uint16_t GetStartPosition() const;
+ uint16_t GetStopPosition() const;
+
+private:
+ static void * Run(void *);
+ mutable string errorStr;
+ STG_CONFIG_SETTINGS stgConfigSettings;
+ pthread_t thread;
+ bool nonstop;
+ bool isRunning;
+ CONFIGPROTO config;
+ USERS * users;
+ ADMINS * admins;
+ TARIFFS * tariffs;
+ BASE_STORE * store;
+ MODULE_SETTINGS settings;
+ const SETTINGS * stgSettings;
+};
+//-----------------------------------------------------------------------------
+
+
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.9 2008/12/04 17:09:40 faust Exp $
+###############################################################################
+
+include ../../../../../Makefile.conf
+
+PROG = mod_conf_sg2.so
+
+SRCS = ./stgconfig.cpp \
+ ./rsconf.cpp \
+ ./configproto.cpp \
+ ./parser.cpp \
+ ./parser_tariff.cpp \
+ ./parser_admin.cpp
+
+LIBS += -lexpat \
+ $(LIB_THREAD)
+
+STGLIBS = -lstg_common -lstg_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
+ */
+
+/*
+ * Date: 27.10.2002
+ */
+
+/*
+ * Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+ /*
+ $Revision: 1.20 $
+ $Date: 2009/10/20 11:53:40 $
+ $Author: faust $
+ */
+
+
+//#include <string.h>
+//#include <stdio.h>
+#include <unistd.h>
+
+#include "configproto.h"
+
+//-----------------------------------------------------------------------------
+void ParseXMLStart(void *data, const char *el, const char **attr)
+{
+CONFIGPROTO * cp = (CONFIGPROTO*)(data);
+
+if (cp->currParser)
+ {
+ cp->currParser->SetAnswerList(&cp->answerList);
+ cp->currParser->SetCurrAdmin(cp->currAdmin);
+ cp->currParser->ParseStart(data, el, attr);
+ }
+else
+ {
+ for (unsigned int i = 0; i < cp->dataParser.size(); i++)
+ {
+ cp->dataParser[i]->SetAnswerList(&cp->answerList);
+ cp->currAdmin->SetAdminIP(cp->GetAdminIP());
+ cp->dataParser[i]->SetCurrAdmin(cp->currAdmin);
+ cp->dataParser[i]->Reset();
+ if (cp->dataParser[i]->ParseStart(data, el, attr) == 0)
+ {
+ cp->currParser = cp->dataParser[i];
+ break;
+ }
+ else
+ {
+ cp->dataParser[i]->Reset();
+ }
+ }
+ }
+}
+//-----------------------------------------------------------------------------
+void ParseXMLEnd(void *data, const char *el)
+{
+CONFIGPROTO * cp = (CONFIGPROTO*)(data);
+if (cp->currParser)
+ {
+ if (cp->currParser->ParseEnd(data, el) == 0)
+ {
+ cp->currParser = NULL;
+ }
+ }
+else
+ {
+ for (unsigned int i = 0; i < cp->dataParser.size(); i++)
+ {
+ if (cp->dataParser[i]->ParseEnd(data, el) == 0)
+ {
+ break;
+ }
+ }
+ }
+}
+//-----------------------------------------------------------------------------
+CONFIGPROTO::CONFIGPROTO()
+ : adminIP(0),
+ port(0),
+ nonstop(1),
+ state(0),
+ currAdmin(NULL),
+ WriteServLog(GetStgLogger()),
+ outerSocket(0),
+ listenSocket(0),
+ admins(NULL),
+ users(NULL),
+ tariffs(NULL),
+ store(NULL),
+ settings(NULL),
+ currParser(NULL)
+{
+dataParser.push_back(&parserGetServInfo);
+
+dataParser.push_back(&parserGetUsers);
+dataParser.push_back(&parserGetUser);
+dataParser.push_back(&parserChgUser);
+dataParser.push_back(&parserAddUser);
+dataParser.push_back(&parserDelUser);
+dataParser.push_back(&parserCheckUser);
+dataParser.push_back(&parserSendMessage);
+
+dataParser.push_back(&parserGetTariffs);
+dataParser.push_back(&parserAddTariff);
+dataParser.push_back(&parserDelTariff);
+dataParser.push_back(&parserChgTariff);
+
+dataParser.push_back(&parserGetAdmins);
+dataParser.push_back(&parserChgAdmin);
+dataParser.push_back(&parserDelAdmin);
+dataParser.push_back(&parserAddAdmin);
+
+xmlParser = XML_ParserCreate(NULL);
+
+if (!xmlParser)
+ {
+ WriteServLog("Couldn't allocate memory for parser.");
+ exit(1);
+ }
+
+//XML_SetElementHandler(parser, ParseXMLStart, ParseXMLEnd);
+}
+//-----------------------------------------------------------------------------
+CONFIGPROTO::~CONFIGPROTO()
+{
+XML_ParserFree(xmlParser);
+}
+//-----------------------------------------------------------------------------
+int CONFIGPROTO::ParseCommand()
+{
+list<string>::iterator n;
+int done = 0;
+char str[9];
+int len;
+
+if (requestList.empty())
+ return 0;
+
+n = requestList.begin();
+
+strncpy(str, (*n).c_str(), 8);
+str[8] = 0;
+
+XML_ParserReset(xmlParser, NULL);
+XML_SetElementHandler(xmlParser, ParseXMLStart, ParseXMLEnd);
+XML_SetUserData(xmlParser, this);
+
+while(nonstop)
+ {
+ strncpy(str, (*n).c_str(), 8);
+ str[8] = 0;
+ len = strlen(str);
+
+ n++;
+ if (n == requestList.end())
+ done = 1;
+ n--;
+
+ if (XML_Parse(xmlParser, (*n).c_str(), len, done) == XML_STATUS_ERROR)
+ {
+ WriteServLog("Invalid configuration request");
+ printfd(__FILE__, "Parse error at line %d:\n%s\n",
+ XML_GetCurrentLineNumber(xmlParser),
+ XML_ErrorString(XML_GetErrorCode(xmlParser)));
+ if (currParser)
+ {
+ printfd(__FILE__, "Parser reset\n");
+ currParser->Reset();
+ currParser = NULL;
+ }
+
+ return -1;
+ }
+
+ if (done)
+ return 0;
+
+ n++;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+void CONFIGPROTO::SetPort(uint16_t p)
+{
+port = p;
+}
+//-----------------------------------------------------------------------------
+/*void CONFIGPROTO::SetHostAllow(HOSTALLOW *)
+{
+//hostAllow = ha;
+}*/
+//-----------------------------------------------------------------------------
+void CONFIGPROTO::SetAdmins(ADMINS * a)
+{
+admins = a;
+for (unsigned int i = 0; i < dataParser.size(); i++)
+ {
+ dataParser[i]->SetAdmins(admins);
+ }
+
+}
+//-----------------------------------------------------------------------------
+void CONFIGPROTO::SetUsers(USERS * u)
+{
+users = u;
+for (unsigned int i = 0; i < dataParser.size(); i++)
+ {
+ dataParser[i]->SetUsers(users);
+ }
+
+}
+//-----------------------------------------------------------------------------
+void CONFIGPROTO::SetTariffs(TARIFFS * t)
+{
+tariffs = t;
+for (unsigned int i = 0; i < dataParser.size(); i++)
+ {
+ dataParser[i]->SetTariffs(tariffs);
+ }
+}
+//-----------------------------------------------------------------------------
+void CONFIGPROTO::SetStore(BASE_STORE * s)
+{
+store = s;
+for (unsigned int i = 0; i < dataParser.size(); i++)
+ {
+ dataParser[i]->SetStore(s);
+ }
+}
+//-----------------------------------------------------------------------------
+void CONFIGPROTO::SetStgSettings(const SETTINGS * s)
+{
+settings = s;
+for (unsigned int i = 0; i < dataParser.size(); i++)
+ {
+ dataParser[i]->SetStgSettings(settings);
+ }
+}
+//-----------------------------------------------------------------------------
+/*void CONFIGPROTO::Start()
+{
+finished = false;
+threadExited = false;
+status = starting;
+
+xmlParser = XML_ParserCreate(NULL);
+
+if (!xmlParser)
+ {
+ WriteServLog("Couldn't allocate memory for parser.");
+ }
+
+pthread_create(&thrReciveSendConf, NULL, ReciveSendConf, this);
+status = started;
+}*/
+//-----------------------------------------------------------------------------
+/*int CONFIGPROTO::Stop()
+{
+nonstop = true;
+close(outerSocket);
+return 0;
+}*/
+//-----------------------------------------------------------------------------
+/*void CONFIGPROTO::Restart()
+{
+//Stop();
+//Start();
+}*/
+//-----------------------------------------------------------------------------
+/*CONF_STATUS CONFIGPROTO::Status()
+{
+//return status;
+}
+//-----------------------------------------------------------------------------
+*/
+const string & CONFIGPROTO::GetStrError()
+{
+return errorStr;
+}
+//-----------------------------------------------------------------------------
+uint32_t CONFIGPROTO::GetAdminIP()
+{
+return adminIP;
+}
+//-----------------------------------------------------------------------------
--- /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>
+ */
+
+ /*
+ $Revision: 1.12 $
+ $Date: 2009/10/15 14:46:17 $
+ $Author: faust $
+ */
+
+
+#ifndef CONFIGPROTO_H
+#define CONFIGPROTO_H
+
+#include <expat.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <string>
+
+#include "parser.h"
+#include "../../../users.h"
+#include "../../../admins.h"
+#include "../../../tariffs.h"
+#include "stg_logger.h"
+
+using namespace std;
+
+#define STG_HEADER "SG04"
+#define OK_HEADER "OKHD"
+#define ERR_HEADER "ERHD"
+#define OK_LOGIN "OKLG"
+#define ERR_LOGIN "ERLG"
+#define OK_LOGINS "OKLS"
+#define ERR_LOGINS "ERLS"
+
+//-----------------------------------------------------------------------------
+class CONFIGPROTO
+{
+public:
+ CONFIGPROTO();
+ ~CONFIGPROTO();
+
+ void SetPort(uint16_t port);
+ //void SetHostAllow(HOSTALLOW * ha);
+ void SetAdmins(ADMINS * a);
+ void SetUsers(USERS * u);
+ void SetTariffs(TARIFFS * t);
+ void SetStore(BASE_STORE * s);
+ void SetStgSettings(const SETTINGS * s);
+ const string & GetAdminLogin();
+ uint32_t GetAdminIP();
+ int Prepare();
+ int Stop();
+ const string & GetStrError();
+ static void * Run(void * a);
+
+private:
+ int RecvHdr(int sock);
+ int RecvLogin(int sock);
+ int SendLoginAnswer(int sock, int err);
+ int SendHdrAnswer(int sock, int err);
+ int RecvLoginS(int sock);
+ int SendLoginSAnswer(int sock, int err);
+ int RecvData(int sock);
+ int SendDataAnswer(int sock);
+ void SendError(const char * text);
+ void WriteLogAccessFailed(uint32_t ip);
+
+ int ParseCommand();
+
+ list<string> answerList;
+ list<string> requestList;
+ uint32_t adminIP;
+ string adminLogin;
+ uint16_t port;
+ pthread_t thrReciveSendConf;
+ bool nonstop;
+ int state;
+ //HOSTALLOW * hostAllow;
+ const ADMIN * currAdmin;
+ STG_LOGGER & WriteServLog;
+
+ int outerSocket;
+ int listenSocket;
+ struct sockaddr_in outerAddr;
+ socklen_t outerAddrLen;
+
+ PARSER_GET_SERVER_INFO parserGetServInfo;
+
+ PARSER_GET_USERS parserGetUsers;
+ PARSER_GET_USER parserGetUser;
+ PARSER_CHG_USER parserChgUser;
+ PARSER_ADD_USER parserAddUser;
+ PARSER_DEL_USER parserDelUser;
+ PARSER_CHECK_USER parserCheckUser;
+ PARSER_SEND_MESSAGE parserSendMessage;
+
+ PARSER_GET_ADMINS parserGetAdmins;
+ PARSER_ADD_ADMIN parserAddAdmin;
+ PARSER_DEL_ADMIN parserDelAdmin;
+ PARSER_CHG_ADMIN parserChgAdmin;
+
+ PARSER_GET_TARIFFS parserGetTariffs;
+ PARSER_ADD_TARIFF parserAddTariff;
+ PARSER_DEL_TARIFF parserDelTariff;
+ PARSER_CHG_TARIFF parserChgTariff;
+
+ ADMINS * admins;
+ USERS * users;
+ TARIFFS * tariffs;
+ BASE_STORE * store;
+ const SETTINGS * settings;
+
+ BASE_PARSER * currParser;
+ vector<BASE_PARSER*> dataParser;
+
+ XML_Parser xmlParser;
+
+ string errorStr;
+
+ friend void ParseXMLStart(void *data, const char *el, const char **attr);
+ friend void ParseXMLEnd(void *data, const char *el);
+};
+//-----------------------------------------------------------------------------
+#endif //CONFIGPROTO_H
+
--- /dev/null
+#include <unistd.h>
+#include "net_configurator.h"
+#include "../../internal_configurator.h"
+
+//-----------------------------------------------------------------------------
+const string & NET_CONFIGURATOR_SETTINGS::GetStrError()
+{
+return strError;
+}
+//-----------------------------------------------------------------------------
+int NET_CONFIGURATOR_SETTINGS::ReadSettings(const CONFIGFILE &cf)
+{
+if (cf.ReadUShortInt("AdminPort", &port, 5555) != 0)
+ {
+ strError = "Cannot read parameter AdminPort.";
+ return -1;
+ }
+if (port < 1 || port > 65535)
+ {
+ strError = "Incorrect value AdminPort.";
+ return -1;
+ }
+
+string strOrder;
+cf.ReadString("AdminOrder", &strOrder, "allow,deny");
+if (hostAllow.ParseOrder(strOrder.c_str()) < 0)
+ {
+ strError = string("Error in parameter AdminOrder. ") + hostAllow.GetStrError();
+ return -1;
+ }
+
+string strAllow;
+cf.ReadString("AdminAllowFrom", &strAllow, "all");
+if (hostAllow.ParseHosts(strAllow.c_str(), hostsAllow) != 0)
+ {
+ strError = string("Error in parameter AdminAllowFrom. ") + hostAllow.GetStrError();
+ return -1;
+ }
+
+string strDeny;
+cf.ReadString("AdminDenyFrom", &strDeny, "");
+if (hostAllow.ParseHosts(strDeny.c_str(), hostsDeny) != 0)
+ {
+ strError = string("Error in parameter AdminDenyFrom. ") + hostAllow.GetStrError();
+ return -1;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+uint16_t NET_CONFIGURATOR_SETTINGS::GetPort()
+{
+return port;
+}
+//-----------------------------------------------------------------------------
+HOSTALLOW * NET_CONFIGURATOR_SETTINGS::GetHostAllow()
+{
+return &hostAllow;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+NET_CONFIGURATOR::NET_CONFIGURATOR()
+{
+hostAllow = settings.GetHostAllow();
+}
+//-----------------------------------------------------------------------------
+NET_CONFIGURATOR::~NET_CONFIGURATOR()
+{
+
+}
+//-----------------------------------------------------------------------------
+void NET_CONFIGURATOR::SetStgConfigurator(BASE_INT_CONFIGURATOR * bsc)
+{
+stgConfigurator = bsc;
+cp.SetStgConfigurator(stgConfigurator);
+}
+//-----------------------------------------------------------------------------
+int NET_CONFIGURATOR::UserGetAll(string * login,
+ USER_CONF_RES * conf,
+ USER_STAT_RES * stat,
+ time_t lastUpdate)
+{
+return 0;
+}
+//-----------------------------------------------------------------------------
+int NET_CONFIGURATOR::TatiffGetAll(TARIFF_CONF * conf)
+{
+return 0;
+}
+//-----------------------------------------------------------------------------
+int NET_CONFIGURATOR::AdminGetAll(ADMIN_CONF * conf)
+{
+return 0;
+}
+//-----------------------------------------------------------------------------
+const string & NET_CONFIGURATOR::GetStrError()
+{
+return strError;
+}
+//-----------------------------------------------------------------------------
+void NET_CONFIGURATOR::Start()
+{
+cp.SetPort(settings.GetPort());
+cp.SetHostAllow(settings.GetHostAllow());
+cp.Start();
+}
+//-----------------------------------------------------------------------------
+void NET_CONFIGURATOR::Stop()
+{
+cp.Stop();
+}
+//-----------------------------------------------------------------------------
+void NET_CONFIGURATOR::Restart()
+{
+cp.Restart();
+}
+//-----------------------------------------------------------------------------
+CONF_STATUS NET_CONFIGURATOR::Status()
+{
+return cp.Status();
+}
+//-----------------------------------------------------------------------------
+BASE_SETTINGS * NET_CONFIGURATOR::GetConfiguratorSettings()
+{
+return &settings;
+}
+//-----------------------------------------------------------------------------
+void NET_CONFIGURATOR::SetAdmins(const ADMINS * a)
+{
+cp.SetAdmins(a);
+}
+//-----------------------------------------------------------------------------
+
--- /dev/null
+ /*
+ $Revision: 1.2 $
+ $Date: 2005/10/30 21:34:28 $
+ */
+
+#ifndef NET_CONFIGURATOR_H
+#define NET_CONFIGURATOR_H
+
+#include <time.h>
+#include <string>
+
+#include "../../base_ext_configurator.h"
+#include "../../base_int_configurator.h"
+#include "../../base_settings.h"
+#include "hostallow.h"
+#include "conffiles.h"
+#include "configproto.h"
+
+using namespace std;
+//-----------------------------------------------------------------------------
+class NET_CONFIGURATOR_SETTINGS: public BASE_SETTINGS
+{
+public:
+ virtual ~NET_CONFIGURATOR_SETTINGS(){};
+virtual const string & GetStrError();
+ virtual int ReadSettings(const CONFIGFILE & cf);
+ uint16_t GetPort();
+ HOSTALLOW * GetHostAllow();
+
+private:
+ string strError;
+ uint16_t port;
+ HOSTALLOW hostAllow;
+};
+//-----------------------------------------------------------------------------
+class NET_CONFIGURATOR: public BASE_EXT_CONFIGURATOR
+{
+public:
+ NET_CONFIGURATOR();
+ virtual ~NET_CONFIGURATOR();
+ virtual void SetStgConfigurator(BASE_INT_CONFIGURATOR *);
+ virtual int UserGetAll(string * login,
+ USER_CONF_RES * conf,
+ USER_STAT_RES * stat,
+ time_t lastUpdate);
+ virtual int TatiffGetAll(TARIFF_CONF * conf);
+ virtual int AdminGetAll(ADMIN_CONF * conf);
+ virtual const string & GetStrError();
+ virtual void Start();
+ virtual void Stop();
+ virtual void Restart();
+ virtual CONF_STATUS Status();
+ virtual BASE_SETTINGS * GetConfiguratorSettings();
+ virtual void SetAdmins(const ADMINS * a);
+
+private:
+ HOSTALLOW * hostAllow;
+ BASE_INT_CONFIGURATOR * stgConfigurator;
+ NET_CONFIGURATOR_SETTINGS settings;
+ string strError;
+ CONFIGPROTO cp;
+};
+//-----------------------------------------------------------------------------
+#endif //NET_CONFIGURATOR_H
+
--- /dev/null
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+#include <sys/utsname.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sstream>
+
+#include "parser.h"
+#include "version.h"
+
+#define UNAME_LEN (256)
+//-----------------------------------------------------------------------------
+// GET SERVER INFO
+//-----------------------------------------------------------------------------
+int PARSER_GET_SERVER_INFO::ParseStart(void *, const char *el, const char **)
+{
+answerList->erase(answerList->begin(), answerList->end());
+if (strcasecmp(el, "GetServerInfo") == 0)
+ {
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int PARSER_GET_SERVER_INFO::ParseEnd(void *, const char *el)
+{
+if (strcasecmp(el, "GetServerInfo") == 0)
+ {
+ CreateAnswer();
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+void PARSER_GET_SERVER_INFO::CreateAnswer()
+{
+char s[UNAME_LEN + 128];
+char un[UNAME_LEN];
+struct utsname utsn;
+
+int tariff_type;
+
+tariff_type = 2;
+
+uname(&utsn);
+un[0] = 0;
+
+strcat(un, utsn.sysname);
+strcat(un, " ");
+strcat(un, utsn.release);
+strcat(un, " ");
+strcat(un, utsn.machine);
+strcat(un, " ");
+strcat(un, utsn.nodename);
+
+//answerList->clear();
+answerList->erase(answerList->begin(), answerList->end());
+answerList->push_back("<ServerInfo>");
+
+sprintf(s, "<version value=\"%s\"/>", SERVER_VERSION);
+answerList->push_back(s);
+
+sprintf(s, "<tariff_num value=\"%d\"/>", tariffs->GetTariffsNum());
+answerList->push_back(s);
+
+sprintf(s, "<tariff value=\"%d\"/>", 2);
+answerList->push_back(s);
+
+sprintf(s, "<users_num value=\"%d\"/>", users->GetUserNum());
+answerList->push_back(s);
+
+sprintf(s, "<uname value=\"%s\"/>", un);
+answerList->push_back(s);
+
+sprintf(s, "<dir_num value=\"%d\"/>", DIR_NUM);
+answerList->push_back(s);
+
+sprintf(s, "<day_fee value=\"%d\"/>", settings->GetDayFee());
+answerList->push_back(s);
+
+for (int i = 0; i< DIR_NUM; i++)
+ {
+ string dn2e;
+ Encode12str(dn2e, settings->GetDirName(i));
+ sprintf(s, "<dir_name_%d value=\"%s\"/>", i, dn2e.c_str());
+ answerList->push_back(s);
+ }
+
+answerList->push_back("</ServerInfo>");
+}
+//-----------------------------------------------------------------------------
+// GET USER
+//-----------------------------------------------------------------------------
+PARSER_GET_USER::PARSER_GET_USER()
+{
+
+}
+//-----------------------------------------------------------------------------
+int PARSER_GET_USER::ParseStart(void *, const char *el, const char **attr)
+{
+if (strcasecmp(el, "GetUser") == 0)
+ {
+ if (attr[0] && attr[1])
+ login = attr[1];
+ else
+ {
+ //login.clear();
+ login.erase(login.begin(), login.end());
+ return -1;
+ }
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int PARSER_GET_USER::ParseEnd(void *, const char *el)
+{
+if (strcasecmp(el, "GetUser") == 0)
+ {
+ CreateAnswer();
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+void PARSER_GET_USER::CreateAnswer()
+{
+string s;
+string enc;
+
+user_iter u;
+
+answerList->erase(answerList->begin(), answerList->end());
+
+if (users->FindByName(login, &u))
+ {
+ s = "<user result=\"error\"/>";
+ answerList->push_back(s);
+ return;
+ }
+
+s = "<user result=\"ok\">";
+answerList->push_back(s);
+
+s = "<login value=\"" + u->GetLogin() + "\"/>";
+answerList->push_back(s);
+
+if (currAdmin->GetPriv()->userConf || currAdmin->GetPriv()->userPasswd)
+ s = "<password value=\"" + u->property.password.Get() + "\" />";
+else
+ s = "<password value=\"++++++\"/>";
+answerList->push_back(s);
+
+strprintf(&s, "<cash value=\"%f\" />", u->property.cash.Get());
+answerList->push_back(s);
+
+strprintf(&s, "<freemb value=\"%f\" />", u->property.freeMb.Get());
+answerList->push_back(s);
+
+strprintf(&s, "<credit value=\"%f\" />", u->property.credit.Get());
+answerList->push_back(s);
+
+if (u->property.nextTariff.Get() != "")
+ {
+ strprintf(&s, "<tariff value=\"%s/%s\" />",
+ u->property.tariffName.Get().c_str(),
+ u->property.nextTariff.Get().c_str());
+ }
+else
+ {
+ strprintf(&s, "<tariff value=\"%s\" />",
+ u->property.tariffName.Get().c_str());
+ }
+
+answerList->push_back(s);
+
+Encode12str(enc, u->property.note);
+s = "<note value=\"" + enc + "\" />";
+answerList->push_back(s);
+
+Encode12str(enc, u->property.phone);
+s = "<phone value=\"" + enc + "\" />";
+answerList->push_back(s);
+
+Encode12str(enc, u->property.address);
+s = "<address value=\"" + enc + "\" />";
+answerList->push_back(s);
+
+Encode12str(enc, u->property.email);
+s = "<email value=\"" + enc + "\" />";
+answerList->push_back(s);
+
+
+vector<USER_PROPERTY_LOGGED<string> *> userdata;
+userdata.push_back(u->property.userdata0.GetPointer());
+userdata.push_back(u->property.userdata1.GetPointer());
+userdata.push_back(u->property.userdata2.GetPointer());
+userdata.push_back(u->property.userdata3.GetPointer());
+userdata.push_back(u->property.userdata4.GetPointer());
+userdata.push_back(u->property.userdata5.GetPointer());
+userdata.push_back(u->property.userdata6.GetPointer());
+userdata.push_back(u->property.userdata7.GetPointer());
+userdata.push_back(u->property.userdata8.GetPointer());
+userdata.push_back(u->property.userdata9.GetPointer());
+
+string tmpI;
+for (unsigned i = 0; i < userdata.size(); i++)
+ {
+ Encode12str(enc, userdata[i]->Get());
+ s = "<UserData" + x2str(i, tmpI) + " value=\"" + enc + "\" />";
+ answerList->push_back(s);
+ }
+
+Encode12str(enc, u->property.realName);
+s = "<name value=\"" + enc + "\" />";
+answerList->push_back(s);
+
+Encode12str(enc, u->property.group);
+s = "<GROUP value=\"" + enc + "\" />";
+answerList->push_back(s);
+
+strprintf(&s, "<status value=\"%d\" />", u->GetConnected());
+answerList->push_back(s);
+
+strprintf(&s, "<aonline value=\"%d\" />", u->property.alwaysOnline.Get());
+answerList->push_back(s);
+
+strprintf(&s, "<currip value=\"%s\" />", inet_ntostring(u->GetCurrIP()).c_str());
+answerList->push_back(s);
+
+strprintf(&s, "<PingTime value=\"%lu\" />", u->GetPingTime());
+answerList->push_back(s);
+
+stringstream sstr;
+sstr << u->property.ips.Get();
+strprintf(&s, "<ip value=\"%s\" />", sstr.str().c_str());
+answerList->push_back(s);
+
+char * ss;
+ss = new char[DIR_NUM*25*4 + 50];
+char st[50];
+sprintf(ss, "<traff");
+DIR_TRAFF upload;
+DIR_TRAFF download;
+download = u->property.down.Get();
+upload = u->property.up.Get();
+
+for (int j = 0; j < DIR_NUM; j++)
+ {
+ string s;
+ x2str(upload[j], s);
+ sprintf(st, " MU%d=\"%s\"", j, s.c_str());
+ strcat(ss, st);
+
+ x2str(download[j], s);
+ sprintf(st, " MD%d=\"%s\"", j, s.c_str());
+ strcat(ss, st);
+
+ sprintf(st, " SU%d=\"0\"", j);
+ strcat(ss, st);
+
+ sprintf(st, " SD%d=\"0\"", j);
+ strcat(ss, st);
+ }
+strcat(ss, " />");
+answerList->push_back(ss);
+delete[] ss;
+
+strprintf(&s, "<down value=\"%d\" />", u->property.disabled.Get());
+answerList->push_back(s);
+
+strprintf(&s, "<DisableDetailStat value=\"%d\" />", u->property.disabledDetailStat.Get());
+answerList->push_back(s);
+
+strprintf(&s, "<passive value=\"%d\" />", u->property.passive.Get());
+answerList->push_back(s);
+
+strprintf(&s, "<LastCash value=\"%f\" />", u->property.lastCashAdd.Get());
+answerList->push_back(s);
+
+strprintf(&s, "<LastTimeCash value=\"%ld\" />", u->property.lastCashAddTime.Get());
+answerList->push_back(s);
+
+strprintf(&s, "<LastActivityTime value=\"%ld\" />", u->property.lastActivityTime.Get());
+answerList->push_back(s);
+
+strprintf(&s, "<CreditExpire value=\"%ld\" />", u->property.creditExpire.Get());
+answerList->push_back(s);
+
+strprintf(&s, "</user>");
+answerList->push_back(s);
+}
+//-----------------------------------------------------------------------------
+// GET USERS
+//-----------------------------------------------------------------------------
+PARSER_GET_USERS::PARSER_GET_USERS()
+{
+lastUserUpdateTime = 0;
+}
+//-----------------------------------------------------------------------------
+int PARSER_GET_USERS::ParseStart(void *, const char *el, const char ** attr)
+{
+/*if (attr && *attr && *(attr+1))
+ {
+ printfd(__FILE__, "attr=%s %s\n", *attr, *(attr+1));
+ }
+else
+ {
+ printfd(__FILE__, "attr = NULL\n");
+ }*/
+
+lastUpdateFound = false;
+if (strcasecmp(el, "GetUsers") == 0)
+ {
+ while (attr && *attr && *(attr+1))
+ {
+ if (strcasecmp(*attr, "LastUpdate") == 0)
+ {
+ if (str2x(*(attr+1), lastUserUpdateTime) == 0)
+ {
+ //printfd(__FILE__, "lastUserUpdateTime=%d\n", lastUserUpdateTime);
+ lastUpdateFound = true;
+ }
+ else
+ {
+ //printfd(__FILE__, "NO lastUserUpdateTime\n");
+ }
+ }
+ ++attr;
+ }
+
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int PARSER_GET_USERS::ParseEnd(void *, const char *el)
+{
+if (strcasecmp(el, "GetUsers") == 0)
+ {
+ CreateAnswer();
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+void PARSER_GET_USERS::CreateAnswer()
+{
+answerList->erase(answerList->begin(), answerList->end());
+
+string s;
+string userStart;
+string traffStart;
+string traffMiddle;
+string traffFinish;
+string middle;
+string userFinish;
+
+
+string enc;
+
+user_iter u;
+
+int h = users->OpenSearch();
+if (!h)
+ {
+ printfd(__FILE__, "users->OpenSearch() error\n");
+ users->CloseSearch(h);
+ return;
+ }
+string updateTime;
+x2str(time(NULL), updateTime);
+
+if (lastUpdateFound)
+ answerList->push_back("<Users LastUpdate=\"" + updateTime + "\">");
+else
+ answerList->push_back("<Users>");
+
+while (1)
+ {
+ if (users->SearchNext(h, &u))
+ {
+ break;
+ }
+ userStart = "<user login=\"" + u->GetLogin() + "\">";
+ middle = "";
+
+ if (u->property.password.ModificationTime() > lastUserUpdateTime)
+ {
+ if (currAdmin->GetPriv()->userConf || currAdmin->GetPriv()->userPasswd)
+ s = "<password value=\"" + u->property.password.Get() + "\" />";
+ else
+ s = "<password value=\"++++++\"/>";
+ middle += s;
+ }
+
+
+ if (u->property.cash.ModificationTime() > lastUserUpdateTime)
+ {
+ strprintf(&s, "<cash value=\"%f\" />", u->property.cash.Get());
+ middle += s;
+ //printfd(__FILE__, "cash value=\"%f\"\n", u->property.cash.Get());
+ }
+
+
+ if (u->property.freeMb.ModificationTime() > lastUserUpdateTime)
+ {
+ strprintf(&s, "<freemb value=\"%f\" />", u->property.freeMb.Get());
+ middle += s;
+ }
+
+ if (u->property.credit.ModificationTime() > lastUserUpdateTime)
+ {
+ strprintf(&s, "<credit value=\"%f\" />", u->property.credit.Get());
+ middle += s;
+ }
+
+ if (u->property.nextTariff.Get() != "")
+ {
+ if (u->property.tariffName.ModificationTime() > lastUserUpdateTime
+ || u->property.nextTariff.ModificationTime() > lastUserUpdateTime)
+ {
+ strprintf(&s, "<tariff value=\"%s/%s\" />",
+ u->property.tariffName.Get().c_str(),
+ u->property.nextTariff.Get().c_str());
+ middle += s;
+ }
+ }
+ else
+ {
+ if (u->property.tariffName.ModificationTime() > lastUserUpdateTime)
+ {
+ strprintf(&s, "<tariff value=\"%s\" />",
+ u->property.tariffName.Get().c_str());
+ middle += s;
+ }
+ }
+
+ if (u->property.note.ModificationTime() > lastUserUpdateTime)
+ {
+ Encode12str(enc, u->property.note);
+ strprintf(&s, "<note value=\"%s\" />", enc.c_str());
+ middle += s;
+ }
+
+ if (u->property.phone.ModificationTime() > lastUserUpdateTime)
+ {
+ Encode12str(enc, u->property.phone);
+ strprintf(&s, "<phone value=\"%s\" />", enc.c_str());
+ middle += s;
+ }
+
+ if (u->property.address.ModificationTime() > lastUserUpdateTime)
+ {
+ Encode12str(enc, u->property.address);
+ strprintf(&s, "<address value=\"%s\" />", enc.c_str());
+ middle += s;
+ }
+
+ if (u->property.email.ModificationTime() > lastUserUpdateTime)
+ {
+ Encode12str(enc, u->property.email);
+ strprintf(&s, "<email value=\"%s\" />", enc.c_str());
+ middle += s;
+ }
+
+ vector<USER_PROPERTY_LOGGED<string> *> userdata;
+ userdata.push_back(u->property.userdata0.GetPointer());
+ userdata.push_back(u->property.userdata1.GetPointer());
+ userdata.push_back(u->property.userdata2.GetPointer());
+ userdata.push_back(u->property.userdata3.GetPointer());
+ userdata.push_back(u->property.userdata4.GetPointer());
+ userdata.push_back(u->property.userdata5.GetPointer());
+ userdata.push_back(u->property.userdata6.GetPointer());
+ userdata.push_back(u->property.userdata7.GetPointer());
+ userdata.push_back(u->property.userdata8.GetPointer());
+ userdata.push_back(u->property.userdata9.GetPointer());
+
+ string tmpI;
+ for (unsigned i = 0; i < userdata.size(); i++)
+ {
+ if (userdata[i]->ModificationTime() > lastUserUpdateTime)
+ {
+ Encode12str(enc, userdata[i]->Get());
+ s = "<UserData" + x2str(i, tmpI) + " value=\"" + enc + "\" />";
+ middle += s;
+ }
+ }
+
+ if (u->property.realName.ModificationTime() > lastUserUpdateTime)
+ {
+ Encode12str(enc, u->property.realName);
+ strprintf(&s, "<name value=\"%s\" />", enc.c_str());
+ middle += s;
+ }
+
+ if (u->property.group.ModificationTime() > lastUserUpdateTime)
+ {
+ Encode12str(enc, u->property.group);
+ strprintf(&s, "<GROUP value=\"%s\" />", enc.c_str());
+ middle += s;
+ }
+
+ if (u->property.alwaysOnline.ModificationTime() > lastUserUpdateTime)
+ {
+ strprintf(&s, "<aonline value=\"%d\" />", u->property.alwaysOnline.Get());
+ middle += s;
+ }
+
+ if (u->GetCurrIPModificationTime() > lastUserUpdateTime)
+ {
+ strprintf(&s, "<currip value=\"%s\" />", inet_ntostring(u->GetCurrIP()).c_str());
+ middle += s;
+ }
+
+
+ if (u->GetConnectedModificationTime() > lastUserUpdateTime)
+ {
+ strprintf(&s, "<status value=\"%d\" />", u->GetConnected());
+ middle += s;
+ }
+
+ if (u->GetPingTime() > lastUserUpdateTime)
+ {
+ strprintf(&s, "<PingTime value=\"%lu\" />", u->GetPingTime());
+ middle += s;
+ }
+
+ if (u->property.ips.ModificationTime() > lastUserUpdateTime)
+ {
+ stringstream sstr;
+ sstr << u->property.ips.Get();
+ strprintf(&s, "<ip value=\"%s\" />", sstr.str().c_str());
+ middle += s;
+ }
+
+ char st[50];
+ traffStart = "<traff";
+ DIR_TRAFF upload;
+ DIR_TRAFF download;
+ download = u->property.down.Get();
+ upload = u->property.up.Get();
+ traffMiddle = "";
+
+ if (u->property.up.ModificationTime() > lastUserUpdateTime)
+ {
+ for (int j = 0; j < DIR_NUM; j++)
+ {
+ string s;
+ x2str(upload[j], s);
+ sprintf(st, " MU%d=\"%s\" ", j, s.c_str());
+ traffMiddle += st;
+ }
+ }
+
+ if (u->property.down.ModificationTime() > lastUserUpdateTime)
+ {
+ for (int j = 0; j < DIR_NUM; j++)
+ {
+ x2str(download[j], s);
+ sprintf(st, " MD%d=\"%s\" ", j, s.c_str());
+ traffMiddle += st;
+ }
+ }
+
+ traffFinish = " />";
+ if (traffMiddle.length() > 0)
+ {
+ middle += traffStart;
+ middle += traffMiddle;
+ middle += traffFinish;
+ }
+
+ if (u->property.disabled.ModificationTime() > lastUserUpdateTime)
+ {
+ strprintf(&s, "<down value=\"%d\" />", u->property.disabled.Get());
+ middle += s;
+ }
+
+ if (u->property.disabledDetailStat.ModificationTime() > lastUserUpdateTime)
+ {
+ strprintf(&s, "<DisableDetailStat value=\"%d\" />", u->property.disabledDetailStat.Get());
+ middle += s;
+ }
+
+ //printfd(__FILE__, ">>>>> %s\n", s.c_str());
+
+ if (u->property.passive.ModificationTime() > lastUserUpdateTime)
+ {
+ strprintf(&s, "<passive value=\"%d\" />", u->property.passive.Get());
+ middle += s;
+ }
+
+ if (u->property.lastCashAdd.ModificationTime() > lastUserUpdateTime)
+ {
+ strprintf(&s, "<LastCash value=\"%f\" />", u->property.lastCashAdd.Get());
+ middle += s;
+ }
+
+ if (u->property.lastCashAddTime.ModificationTime() > lastUserUpdateTime)
+ {
+ strprintf(&s, "<LastTimeCash value=\"%ld\" />", u->property.lastCashAddTime.Get());
+ middle += s;
+ }
+
+
+ if (u->property.lastActivityTime.ModificationTime() > lastUserUpdateTime)
+ {
+ strprintf(&s, "<LastActivityTime value=\"%ld\" />", u->property.lastActivityTime.Get());
+ middle += s;
+ }
+
+ if (u->property.creditExpire.ModificationTime() > lastUserUpdateTime)
+ {
+ strprintf(&s, "<CreditExpire value=\"%ld\" />", u->property.creditExpire.Get());
+ middle += s;
+ }
+
+
+ userFinish = "</user>";
+
+ if (middle.length() > 0)
+ {
+ /*printfd(__FILE__, "login: %s\n", u->GetLogin().c_str());
+ printfd(__FILE__, "middle: %s\n", middle.c_str());*/
+
+ answerList->push_back(userStart);
+ answerList->push_back(middle);
+ answerList->push_back(userFinish);
+ }
+ }
+
+users->CloseSearch(h);
+
+//answerList->push_back("</Users>");
+
+answerList->push_back("</Users>");
+}
+//-----------------------------------------------------------------------------
+// ADD USER
+//-----------------------------------------------------------------------------
+PARSER_ADD_USER::PARSER_ADD_USER()
+{
+depth = 0;
+}
+//-----------------------------------------------------------------------------
+int PARSER_ADD_USER::ParseStart(void *, const char *el, const char **attr)
+{
+depth++;
+
+if (depth == 1)
+ {
+ if (strcasecmp(el, "AddUser") == 0)
+ {
+ return 0;
+ }
+ }
+else
+ {
+ if (strcasecmp(el, "login") == 0)
+ {
+ login = attr[1];
+ return 0;
+ }
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int PARSER_ADD_USER::ParseEnd(void *, const char *el)
+{
+if (depth == 1)
+ {
+ if (strcasecmp(el, "AddUser") == 0)
+ {
+ CreateAnswer();
+ depth--;
+ return 0;
+ }
+ }
+
+depth--;
+return -1;
+}
+//-----------------------------------------------------------------------------
+void PARSER_ADD_USER::Reset()
+{
+BASE_PARSER::Reset();
+depth = 0;
+}
+//-----------------------------------------------------------------------------
+void PARSER_ADD_USER::CreateAnswer()
+{
+//answerList->clear();
+answerList->erase(answerList->begin(), answerList->end());
+
+if (CheckUserData() == 0)
+ {
+ answerList->push_back("<AddUser result=\"ok\"/>");
+ }
+else
+ {
+ answerList->push_back("<AddUser result=\"error\" reason=\"Access denied\"/>");
+ }
+}
+//-----------------------------------------------------------------------------
+int PARSER_ADD_USER::CheckUserData()
+{
+user_iter u;
+if (users->FindByName(login, &u))
+ {
+ return users->Add(login, *currAdmin);
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+// PARSER CHG USER
+//-----------------------------------------------------------------------------
+PARSER_CHG_USER::PARSER_CHG_USER()
+{
+usr = NULL;
+ucr = NULL;
+upr = NULL;
+downr = NULL;
+
+Reset();
+}
+//-----------------------------------------------------------------------------
+PARSER_CHG_USER::~PARSER_CHG_USER()
+{
+delete usr;
+delete ucr;
+delete[] upr;
+delete[] downr;
+}
+//-----------------------------------------------------------------------------
+void PARSER_CHG_USER::Reset()
+{
+depth = 0;
+delete usr;
+
+delete ucr;
+
+delete[] upr;
+
+delete[] downr;
+
+usr = new USER_STAT_RES;
+ucr = new USER_CONF_RES;
+
+upr = new RESETABLE<uint64_t>[DIR_NUM];
+downr = new RESETABLE<uint64_t>[DIR_NUM];
+};
+//-----------------------------------------------------------------------------
+string PARSER_CHG_USER::EncChar2String(const char * strEnc)
+{
+string str;
+Decode21str(str, strEnc);
+return str;
+}
+//-----------------------------------------------------------------------------
+int PARSER_CHG_USER::ParseStart(void *, const char *el, const char **attr)
+{
+depth++;
+
+if (depth == 1)
+ {
+ if (strcasecmp(el, "SetUser") == 0)
+ {
+ return 0;
+ }
+ }
+else
+ {
+ //printfd(__FILE__, "el=%s\n", el);
+ if (strcasecmp(el, "login") == 0)
+ {
+ login = attr[1];
+ return 0;
+ }
+
+ if (strcasecmp(el, "ip") == 0)
+ {
+ try
+ {
+ ucr->ips = StrToIPS(attr[1]);
+ }
+ catch (...)
+ {
+ printfd(__FILE__, "StrToIPS Error!\n");
+ }
+ }
+
+ if (strcasecmp(el, "password") == 0)
+ {
+ ucr->password = attr[1];
+ return 0;
+ }
+
+ if (strcasecmp(el, "address") == 0)
+ {
+ ucr->address = EncChar2String(attr[1]);
+ return 0;
+ }
+
+ if (strcasecmp(el, "aonline") == 0)
+ {
+ ucr->alwaysOnline = (*(attr[1]) != '0');
+ return 0;
+ }
+
+ if (strcasecmp(el, "cash") == 0)
+ {
+ if (attr[2] && (strcasecmp(attr[2], "msg") == 0))
+ {
+ cashMsg = EncChar2String(attr[3]);
+ }
+
+ double cash;
+ if (strtodouble2(attr[1], cash) == 0)
+ usr->cash = cash;
+
+ if (strcasecmp(attr[0], "set") == 0)
+ cashMustBeAdded = false;
+
+ if (strcasecmp(attr[0], "add") == 0)
+ cashMustBeAdded = true;
+
+ return 0;
+ }
+
+ if (strcasecmp(el, "CreditExpire") == 0)
+ {
+ long int creditExpire = 0;
+ if (str2x(attr[1], creditExpire) == 0)
+ ucr->creditExpire = (time_t)creditExpire;
+
+ return 0;
+ }
+
+ if (strcasecmp(el, "credit") == 0)
+ {
+ double credit;
+ if (strtodouble2(attr[1], credit) == 0)
+ ucr->credit = credit;
+ return 0;
+ }
+
+ if (strcasecmp(el, "freemb") == 0)
+ {
+ double freeMb;
+ if (strtodouble2(attr[1], freeMb) == 0)
+ usr->freeMb = freeMb;
+ return 0;
+ }
+
+ if (strcasecmp(el, "down") == 0)
+ {
+ int down = 0;
+ if (str2x(attr[1], down) == 0)
+ ucr->disabled = down;
+ return 0;
+ }
+
+ if (strcasecmp(el, "DisableDetailStat") == 0)
+ {
+ int disabledDetailStat = 0;
+ if (str2x(attr[1], disabledDetailStat) == 0)
+ ucr->disabledDetailStat = disabledDetailStat;
+ return 0;
+ }
+
+ if (strcasecmp(el, "email") == 0)
+ {
+ ucr->email = EncChar2String(attr[1]);
+ return 0;
+ }
+
+ for (int i = 0; i < USERDATA_NUM; i++)
+ {
+ char name[15];
+ sprintf(name, "userdata%d", i);
+ if (strcasecmp(el, name) == 0)
+ {
+ ucr->userdata[i] = EncChar2String(attr[1]);
+ return 0;
+ }
+ }
+
+ if (strcasecmp(el, "group") == 0)
+ {
+ ucr->group = EncChar2String(attr[1]);
+ return 0;
+ }
+
+ if (strcasecmp(el, "note") == 0)
+ {
+ ucr->note = EncChar2String(attr[1]);
+ return 0;
+ }
+
+ if (strcasecmp(el, "passive") == 0)
+ {
+ int passive = 0;
+ if (str2x(attr[1], passive) == 0)
+ ucr->passive = passive;
+ return 0;
+ }
+
+ if (strcasecmp(el, "phone") == 0)
+ {
+ ucr->phone = EncChar2String(attr[1]);
+ return 0;
+ }
+
+ if (strcasecmp(el, "Name") == 0)
+ {
+ ucr->realName = EncChar2String(attr[1]);
+ return 0;
+ }
+
+ if (strcasecmp(el, "traff") == 0)
+ {
+ int j = 0;
+ int dir;
+ DIR_TRAFF dtu;
+ DIR_TRAFF dtd;
+ unsigned long long t = 0;
+ while (attr[j])
+ {
+ dir = attr[j][2] - '0';
+
+ if (strncasecmp(attr[j], "md", 2) == 0)
+ {
+ str2x(attr[j+1], t);
+ dtd[dir] = t;
+ downr[dir] = t;
+ }
+ if (strncasecmp(attr[j], "mu", 2) == 0)
+ {
+ str2x(attr[j+1], t);
+ dtu[dir] = t;
+ upr[dir] = t;
+ }
+ j+=2;
+ }
+ usr->down = dtd;
+ usr->up = dtu;
+ return 0;
+ }
+
+ if (strcasecmp(el, "tariff") == 0)
+ {
+ if (strcasecmp(attr[0], "now") == 0)
+ ucr->tariffName = attr[1];
+
+ if (strcasecmp(attr[0], "delayed") == 0)
+ ucr->nextTariff = attr[1];
+
+ return 0;
+ }
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int PARSER_CHG_USER::ParseEnd(void *, const char *el)
+{
+if (depth == 1)
+ {
+ if (strcasecmp(el, "SetUser") == 0)
+ {
+ AplayChanges();
+ CreateAnswer();
+ depth--;
+ return 0;
+ }
+ }
+
+depth--;
+return -1;
+}
+//-----------------------------------------------------------------------------
+void PARSER_CHG_USER::CreateAnswer()
+{
+//answerList->clear();
+answerList->erase(answerList->begin(), answerList->end());
+
+switch (res)
+ {
+ case 0:
+ answerList->push_back("<SetUser result=\"ok\"/>");
+ break;
+ case -1:
+ answerList->push_back("<SetUser result=\"error\"/>");
+ break;
+ case -2:
+ answerList->push_back("<SetUser result=\"error\"/>");
+ break;
+ default:
+ answerList->push_back("<SetUser result=\"error\"/>");
+ break;
+ }
+
+}
+//-----------------------------------------------------------------------------
+int PARSER_CHG_USER::CheckUserData()
+{
+return true;
+}
+//-----------------------------------------------------------------------------
+int PARSER_CHG_USER::AplayChanges()
+{
+user_iter u;
+
+res = 0;
+if (users->FindByName(login, &u))
+ {
+ res = -1;
+ return -1;
+ }
+
+if (!ucr->ips.res_empty())
+ if (!u->property.ips.Set(ucr->ips.const_data(), currAdmin, login, store))
+ res = -1;
+
+if (!ucr->address.res_empty())
+ if (!u->property.address.Set(ucr->address.const_data(), currAdmin, login, store))
+ res = -1;
+
+if (!ucr->alwaysOnline.res_empty())
+ if (!u->property.alwaysOnline.Set(ucr->alwaysOnline.const_data(),
+ currAdmin, login, store))
+ res = -1;
+
+if (!ucr->creditExpire.res_empty())
+ if (!u->property.creditExpire.Set(ucr->creditExpire.const_data(),
+ currAdmin, login, store))
+ res = -1;
+
+if (!ucr->credit.res_empty())
+ if (!u->property.credit.Set(ucr->credit.const_data(), currAdmin, login, store))
+ res = -1;
+
+if (!usr->freeMb.res_empty())
+ if (!u->property.freeMb.Set(usr->freeMb.const_data(), currAdmin, login, store))
+ res = -1;
+
+if (!ucr->disabled.res_empty())
+ if (!u->property.disabled.Set(ucr->disabled.const_data(), currAdmin, login, store))
+ res = -1;
+
+if (!ucr->disabledDetailStat.res_empty())
+ if (!u->property.disabledDetailStat.Set(ucr->disabledDetailStat.const_data(), currAdmin, login, store))
+ res = -1;
+
+if (!ucr->email.res_empty())
+ if (!u->property.email.Set(ucr->email.const_data(), currAdmin, login, store))
+ res = -1;
+
+if (!ucr->group.res_empty())
+ if (!u->property.group.Set(ucr->group.const_data(), currAdmin, login, store))
+ res = -1;
+
+if (!ucr->note.res_empty())
+ if (!u->property.note.Set(ucr->note.const_data(), currAdmin, login, store))
+ res = -1;
+
+vector<USER_PROPERTY_LOGGED<string> *> userdata;
+userdata.push_back(u->property.userdata0.GetPointer());
+userdata.push_back(u->property.userdata1.GetPointer());
+userdata.push_back(u->property.userdata2.GetPointer());
+userdata.push_back(u->property.userdata3.GetPointer());
+userdata.push_back(u->property.userdata4.GetPointer());
+userdata.push_back(u->property.userdata5.GetPointer());
+userdata.push_back(u->property.userdata6.GetPointer());
+userdata.push_back(u->property.userdata7.GetPointer());
+userdata.push_back(u->property.userdata8.GetPointer());
+userdata.push_back(u->property.userdata9.GetPointer());
+
+for (int i = 0; i < (int)userdata.size(); i++)
+ {
+ if (!ucr->userdata[i].res_empty())
+ {
+ if(!userdata[i]->Set(ucr->userdata[i].const_data(), currAdmin, login, store))
+ res = -1;
+ }
+ }
+
+if (!ucr->passive.res_empty())
+ if (!u->property.passive.Set(ucr->passive.const_data(), currAdmin, login, store))
+ res = -1;
+
+if (!ucr->password.res_empty())
+ if (!u->property.password.Set(ucr->password.const_data(), currAdmin, login, store))
+ res = -1;
+
+if (!ucr->phone.res_empty())
+ if (!u->property.phone.Set(ucr->phone.const_data(), currAdmin, login, store))
+ res = -1;
+
+if (!ucr->realName.res_empty())
+ if (!u->property.realName.Set(ucr->realName.const_data(), currAdmin, login, store))
+ res = -1;
+
+
+if (!usr->cash.res_empty())
+ {
+ //if (currAdmin->GetPriv()->userCash)
+ {
+ if (cashMustBeAdded)
+ {
+ if (!u->property.cash.Set(usr->cash.const_data() + u->property.cash,
+ currAdmin,
+ login,
+ store,
+ cashMsg))
+ res = -1;
+ }
+ else
+ {
+ if (!u->property.cash.Set(usr->cash.const_data(), currAdmin, login, store, cashMsg))
+ res = -1;
+ }
+ }
+ }
+
+
+if (!ucr->tariffName.res_empty())
+ {
+ if (tariffs->FindByName(ucr->tariffName.const_data()))
+ {
+ if (!u->property.tariffName.Set(ucr->tariffName.const_data(), currAdmin, login, store))
+ res = -1;
+ u->ResetNextTariff();
+ }
+ else
+ {
+ //WriteServLog("SetUser: Tariff %s not found", ud.conf.tariffName.c_str());
+ res = -1;
+ }
+ }
+
+if (!ucr->nextTariff.res_empty())
+ {
+ if (tariffs->FindByName(ucr->nextTariff.const_data()))
+ {
+ if (!u->property.nextTariff.Set(ucr->nextTariff.const_data(), currAdmin, login, store))
+ res = -1;
+ }
+ else
+ {
+ //WriteServLog("SetUser: Tariff %s not found", ud.conf.tariffName.c_str());
+ res = -1;
+ }
+ }
+
+DIR_TRAFF up = u->property.up;
+DIR_TRAFF down = u->property.down;
+int upCount = 0;
+int downCount = 0;
+for (int i = 0; i < DIR_NUM; i++)
+ {
+ if (!upr[i].res_empty())
+ {
+ up[i] = upr[i];
+ upCount++;
+ }
+ if (!downr[i].res_empty())
+ {
+ down[i] = downr[i];
+ downCount++;
+ }
+ }
+
+if (upCount)
+ if (!u->property.up.Set(up, currAdmin, login, store))
+ res = -1;
+
+if (downCount)
+ if (!u->property.down.Set(down, currAdmin, login, store))
+ res = -1;
+
+/*if (!usr->down.res_empty())
+ {
+ u->property.down.Set(usr->down.const_data(), currAdmin, login, store);
+ }
+if (!usr->up.res_empty())
+ {
+ u->property.up.Set(usr->up.const_data(), currAdmin, login, store);
+ }*/
+
+u->WriteConf();
+u->WriteStat();
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+// SEND MESSAGE
+//-----------------------------------------------------------------------------
+int PARSER_SEND_MESSAGE::ParseStart(void *, const char *el, const char **attr)
+{
+if (strcasecmp(el, "Message") == 0)
+ {
+ for (int i = 0; i < 14; i++)
+ {
+ if (attr[i] == NULL)
+ {
+ result = res_params_error;
+ CreateAnswer();
+ printfd(__FILE__, "To few parameters\n");
+ return 0;
+ }
+ }
+
+ for (int i = 0; i < 14; i+=2)
+ {
+ if (strcasecmp(attr[i], "login") == 0)
+ {
+ ParseLogins(attr[i+1]);
+ /*if (users->FindByName(login, &u))
+ {
+ result = res_unknown;
+ break;
+ }*/
+ }
+
+ if (strcasecmp(attr[i], "MsgVer") == 0)
+ {
+ str2x(attr[i+1], msg.header.ver);
+ if (msg.header.ver != 1)
+ result = res_params_error;
+ }
+
+ if (strcasecmp(attr[i], "MsgType") == 0)
+ {
+ str2x(attr[i+1], msg.header.type);
+ if (msg.header.type != 1)
+ result = res_params_error;
+ }
+
+ if (strcasecmp(attr[i], "Repeat") == 0)
+ {
+ str2x(attr[i+1], msg.header.repeat);
+ if (msg.header.repeat < 0)
+ result = res_params_error;
+ }
+
+ if (strcasecmp(attr[i], "RepeatPeriod") == 0)
+ {
+ str2x(attr[i+1], msg.header.repeatPeriod);
+ }
+
+ if (strcasecmp(attr[i], "ShowTime") == 0)
+ {
+ str2x(attr[i+1], msg.header.showTime);
+ }
+
+ if (strcasecmp(attr[i], "Text") == 0)
+ {
+ Decode21str(msg.text, attr[i+1]);
+ result = res_ok;
+ }
+ }
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int PARSER_SEND_MESSAGE::ParseEnd(void *, const char *el)
+{
+//MSG msg;
+if (strcasecmp(el, "Message") == 0)
+ {
+ result = res_unknown;
+ for (unsigned i = 0; i < logins.size(); i++)
+ {
+ if (users->FindByName(logins[i], &u))
+ {
+ printfd(__FILE__, "User not found. %s\n", logins[i].c_str());
+ continue;
+ }
+ msg.header.creationTime = stgTime;
+ u->AddMessage(&msg);
+ result = res_ok;
+ }
+ /*if (result == res_ok)
+ {
+ if (strcmp(login, "*") == 0)
+ {
+ msg.text = text;
+ msg.prio = pri;
+ printfd(__FILE__, "SendMsg text: %s\n", text);
+ users->GetAllUsers(SendMessageAllUsers, &msg);
+ }
+ else
+ {
+ u->AddMessage(pri, text);
+ }
+ }*/
+ CreateAnswer();
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int PARSER_SEND_MESSAGE::ParseLogins(const char * login)
+{
+char * p;
+char * l = new char[strlen(login) + 1];
+strcpy(l, login);
+p = strtok(l, ":");
+logins.clear();
+while(p)
+ {
+ logins.push_back(p);
+ p = strtok(NULL, ":");
+ }
+
+delete[] l;
+return 0;
+}
+//-----------------------------------------------------------------------------
+void PARSER_SEND_MESSAGE::CreateAnswer()
+{
+//answerList->clear();
+answerList->erase(answerList->begin(), answerList->end());
+//answerList->push_back("<SendMessageResult value=\"ok\"/>");
+//
+switch (result)
+ {
+ case res_ok:
+ answerList->push_back("<SendMessageResult value=\"ok\"/>");
+ break;
+ case res_params_error:
+ printfd(__FILE__, "res_params_error\n");
+ answerList->push_back("<SendMessageResult value=\"Parameters error\"/>");
+ break;
+ case res_unknown:
+ printfd(__FILE__, "res_unknown\n");
+ answerList->push_back("<SendMessageResult value=\"Unknown user\"/>");
+ break;
+ default:
+ printfd(__FILE__, "res_default\n");
+ }
+
+}
+//-----------------------------------------------------------------------------
+// DEL USER
+//-----------------------------------------------------------------------------
+int PARSER_DEL_USER::ParseStart(void *, const char *el, const char **attr)
+{
+res = 0;
+if (strcasecmp(el, "DelUser") == 0)
+ {
+ if (attr[0] == NULL || attr[1] == NULL)
+ {
+ //CreateAnswer("Parameters error!");
+ CreateAnswer();
+ return 0;
+ }
+
+ if (users->FindByName(attr[1], &u))
+ {
+ res = 1;
+ CreateAnswer();
+ return 0;
+ }
+ CreateAnswer();
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int PARSER_DEL_USER::ParseEnd(void *, const char *el)
+{
+if (strcasecmp(el, "DelUser") == 0)
+ {
+ if (!res)
+ users->Del(u->GetLogin(), *currAdmin);
+
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+void PARSER_DEL_USER::CreateAnswer()
+{
+if (res)
+ answerList->push_back("<DelUser value=\"error\" reason=\"User not found\"/>");
+else
+ answerList->push_back("<DelUser value=\"ok\"/>");
+}
+//-----------------------------------------------------------------------------
+/*void PARSERDELUSER::CreateAnswer(char * mes)
+{
+//answerList->clear();
+answerList->erase(answerList->begin(), answerList->end());
+
+char str[255];
+sprintf(str, "<DelUser value=\"%s\"/>", mes);
+answerList->push_back(str);
+}*/
+//-----------------------------------------------------------------------------
+// CHECK USER
+// <checkuser login="vasya" password=\"123456\"/>
+//-----------------------------------------------------------------------------
+int PARSER_CHECK_USER::ParseStart(void *, const char *el, const char **attr)
+{
+result = false;
+
+if (strcasecmp(el, "CheckUser") == 0)
+ {
+ if (attr[0] == NULL || attr[1] == NULL
+ || attr[2] == NULL || attr[3] == NULL)
+ {
+ result = false;
+ CreateAnswer();
+ printfd(__FILE__, "PARSER_CHECK_USER - attr err\n");
+ return 0;
+ }
+
+ user_iter user;
+ if (users->FindByName(attr[1], &user))
+ {
+ result = false;
+ CreateAnswer();
+ printfd(__FILE__, "PARSER_CHECK_USER - login err\n");
+ return 0;
+ }
+
+ if (strcmp(user->property.password.Get().c_str(), attr[3]))
+ {
+ result = false;
+ CreateAnswer();
+ printfd(__FILE__, "PARSER_CHECK_USER - passwd err\n");
+ return 0;
+ }
+
+ result = true;
+ CreateAnswer();
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int PARSER_CHECK_USER::ParseEnd(void *, const char *el)
+{
+if (strcasecmp(el, "CheckUser") == 0)
+ {
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+void PARSER_CHECK_USER::CreateAnswer()
+{
+if (result)
+ answerList->push_back("<CheckUser value=\"Ok\"/>");
+else
+ answerList->push_back("<CheckUser value=\"Err\"/>");
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
--- /dev/null
+ /*
+ $Revision: 1.18 $
+ $Date: 2009/07/30 18:57:37 $
+ $Author: nobunaga $
+ */
+
+#ifndef PARSER_H
+#define PARSER_H
+
+#include <list>
+#include <string>
+
+using namespace std;
+
+#include "resetable.h"
+#include "stg_const.h"
+#include "base_store.h"
+#include "../../../admins.h"
+#include "../../../users.h"
+#include "stg_message.h"
+
+//-----------------------------------------------------------------------------
+class BASE_PARSER
+{
+public:
+ BASE_PARSER()
+ : admins(NULL),
+ users(NULL),
+ tariffs(NULL),
+ store(NULL),
+ settings(NULL),
+ currAdmin(NULL),
+ depth(0)
+ { };
+ 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 CreateAnswer() = 0;
+ virtual void SetAnswerList(list<string> * ansList){answerList = ansList;};
+
+ virtual void SetUsers(USERS * u){users = u;};
+ virtual void SetAdmins(ADMINS * a){admins = a;};
+ virtual void SetTariffs(TARIFFS * t){tariffs = t;};
+ virtual void SetStore(BASE_STORE * s){store = s;};
+ virtual void SetStgSettings(const SETTINGS * s){settings = s;};
+
+ virtual void SetCurrAdmin(const ADMIN * cua){currAdmin = cua;};
+ virtual string & GetStrError(){return strError;};
+ virtual void Reset(){ answerList->clear(); depth = 0; };
+protected:
+ string strError;
+ ADMINS * admins;
+ USERS * users;
+ TARIFFS * tariffs;
+ BASE_STORE * store;
+ const SETTINGS * settings;
+ const ADMIN * currAdmin;
+ int depth;
+ list<string> * answerList;
+};
+//-----------------------------------------------------------------------------
+class PARSER_GET_ADMINS: public BASE_PARSER
+{
+public:
+ int ParseStart(void *data, const char *el, const char **attr);
+ int ParseEnd(void *data, const char *el);
+ void CreateAnswer();
+};
+//-----------------------------------------------------------------------------
+class PARSER_ADD_ADMIN: public BASE_PARSER
+{
+public:
+ int ParseStart(void *data, const char *el, const char **attr);
+ int ParseEnd(void *data, const char *el);
+ void CreateAnswer();
+private:
+ string adminToAdd;
+};
+//-----------------------------------------------------------------------------
+class PARSER_DEL_ADMIN: public BASE_PARSER
+{
+public:
+ int ParseStart(void *data, const char *el, const char **attr);
+ int ParseEnd(void *data, const char *el);
+ void CreateAnswer();
+private:
+ int CheckAttr(const char **attr);
+ string adminToDel;
+};
+//-----------------------------------------------------------------------------
+class PARSER_CHG_ADMIN: public BASE_PARSER
+{
+public:
+ int ParseStart(void *data, const char *el, const char **attr);
+ int ParseEnd(void *data, const char *el);
+ void CreateAnswer();
+private:
+ RESETABLE<string> login;
+ RESETABLE<string> password;
+ RESETABLE<string> privAsString;
+};
+//-----------------------------------------------------------------------------
+class PARSER_GET_SERVER_INFO: public BASE_PARSER
+{
+public:
+ int ParseStart(void *data, const char *el, const char **attr);
+ int ParseEnd(void *data, const char *el);
+ void CreateAnswer();
+};
+
+//-----------------------------------------------------------------------------
+class PARSER_GET_USER: public BASE_PARSER
+{
+public:
+ PARSER_GET_USER();
+ ~PARSER_GET_USER(){};
+ int ParseStart(void *data, const char *el, const char **attr);
+ int ParseEnd(void *data, const char *el);
+ void CreateAnswer();
+private:
+ string login;
+};
+//-----------------------------------------------------------------------------
+class PARSER_GET_USERS: public BASE_PARSER
+{
+public:
+ PARSER_GET_USERS();
+ int ParseStart(void *data, const char *el, const char **attr);
+ int ParseEnd(void *data, const char *el);
+ void CreateAnswer();
+private:
+ time_t lastUserUpdateTime;
+ bool lastUpdateFound;
+};
+//-----------------------------------------------------------------------------
+class PARSER_GET_TARIFFS: public BASE_PARSER
+{
+public:
+ int ParseStart(void *data, const char *el, const char **attr);
+ int ParseEnd(void *data, const char *el);
+ void CreateAnswer();
+};
+//-----------------------------------------------------------------------------
+class PARSER_ADD_TARIFF: public BASE_PARSER
+{
+public:
+ int ParseStart(void *data, const char *el, const char **attr);
+ int ParseEnd(void *data, const char *el);
+ void CreateAnswer();
+private:
+ string tariffToAdd;
+};
+//-----------------------------------------------------------------------------
+class PARSER_DEL_TARIFF: public BASE_PARSER
+{
+public:
+ int ParseStart(void *data, const char *el, const char **attr);
+ int ParseEnd(void *data, const char *el);
+ void CreateAnswer();
+private:
+ string tariffToDel;
+};
+//-----------------------------------------------------------------------------
+class PARSER_CHG_TARIFF: public BASE_PARSER
+{
+public:
+ int ParseStart(void *data, const char *el, const char **attr);
+ int ParseEnd(void *data, const char *el);
+ void CreateAnswer();
+private:
+ int ParseSlashedIntParams(int paramsNum, const string & s, int * params);
+ int ParseSlashedDoubleParams(int paramsNum, const string & s, double * params);
+ int CheckTariffData();
+ int AplayChanges();
+
+ TARIFF_DATA_RES td;
+};
+//-----------------------------------------------------------------------------/
+class PARSER_ADD_USER: public BASE_PARSER
+{
+public:
+ PARSER_ADD_USER();
+ virtual ~PARSER_ADD_USER(){};
+ int ParseStart(void *data, const char *el, const char **attr);
+ int ParseEnd(void *data, const char *el);
+ void CreateAnswer();
+ void Reset();
+private:
+ int CheckUserData();
+ string login;
+};
+//-----------------------------------------------------------------------------
+class PARSER_CHG_USER: public BASE_PARSER
+{
+public:
+ PARSER_CHG_USER();
+ ~PARSER_CHG_USER();
+ int ParseStart(void *data, const char *el, const char **attr);
+ int ParseEnd(void *data, const char *el);
+ void CreateAnswer();
+ void Reset();
+private:
+ string EncChar2String(const char *);
+
+ USER_STAT_RES * usr;
+ USER_CONF_RES * ucr;
+ RESETABLE<uint64_t> * upr;
+ RESETABLE<uint64_t> * downr;
+ string cashMsg;
+ string login;
+
+ int CheckUserData();
+ int AplayChanges();
+ bool cashMustBeAdded;
+ int res;
+};
+//-----------------------------------------------------------------------------
+class PARSER_DEL_USER: public BASE_PARSER
+{
+public:
+ int ParseStart(void *data, const char *el, const char **attr);
+ int ParseEnd(void *data, const char *el);
+ void CreateAnswer();
+
+private:
+ int res;
+ user_iter u;
+};
+//-----------------------------------------------------------------------------
+class PARSER_CHECK_USER: public BASE_PARSER
+{
+public:
+ int ParseStart(void *data, const char *el, const char **attr);
+ int ParseEnd(void *data, const char *el);
+ void CreateAnswer();
+private:
+ bool result;
+};
+//-----------------------------------------------------------------------------
+class PARSER_SEND_MESSAGE: public BASE_PARSER
+{
+public:
+ int ParseStart(void *data, const char *el, const char **attr);
+ int ParseEnd(void *data, const char *el);
+ void CreateAnswer();
+private:
+ enum {res_ok, res_params_error, res_unknown};
+ vector<string> logins;
+ int ParseLogins(const char * logins);
+ int result;
+ STG_MSG msg;
+ user_iter u;
+};
+//-----------------------------------------------------------------------------
+#endif //PARSER_H
+
+
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+
+#include "parser.h"
+
+//-----------------------------------------------------------------------------
+// GET ADMINS
+//-----------------------------------------------------------------------------
+int PARSER_GET_ADMINS::ParseStart(void *, const char *el, const char **)
+{
+if (strcasecmp(el, "GetAdmins") == 0)
+ {
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int PARSER_GET_ADMINS::ParseEnd(void *, const char *el)
+{
+if (strcasecmp(el, "GetAdmins") == 0)
+ {
+ CreateAnswer();
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+void PARSER_GET_ADMINS::CreateAnswer()
+{
+const PRIV * priv = currAdmin->GetPriv();
+if (!priv->adminChg)
+ {
+ //answerList->clear();
+ answerList->erase(answerList->begin(), answerList->end());
+
+ answerList->push_back("<Error Result=\"Error. Access denied.\"/>");
+ return;
+ }
+
+string s;
+//answerList->clear();
+answerList->erase(answerList->begin(), answerList->end());
+
+answerList->push_back("<Admins>");
+ADMIN_CONF ac;
+int h = admins->OpenSearch();
+
+unsigned int p;
+while (admins->SearchNext(h, &ac) == 0)
+ {
+ //memcpy(&p, &ac.priv, sizeof(unsigned int));
+ p = (ac.priv.userStat << 0) +
+ (ac.priv.userConf << 2) +
+ (ac.priv.userCash << 4) +
+ (ac.priv.userPasswd << 6) +
+ (ac.priv.userAddDel << 8) +
+ (ac.priv.adminChg << 10) +
+ (ac.priv.tariffChg << 12);
+ strprintf(&s, "<admin login=\"%s\" priv=\"%d\"/>", ac.login.c_str(), p);
+ answerList->push_back(s);
+ }
+admins->CloseSearch(h);
+answerList->push_back("</Admins>");
+}
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// DEL ADMIN
+//-----------------------------------------------------------------------------
+int PARSER_DEL_ADMIN::ParseStart(void *, const char *el, const char **attr)
+{
+strError = "";
+if (strcasecmp(el, "DelAdmin") == 0)
+ {
+ adminToDel = attr[1];
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int PARSER_DEL_ADMIN::ParseEnd(void *, const char *el)
+{
+if (strcasecmp(el, "DelAdmin") == 0)
+ {
+ CreateAnswer();
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+void PARSER_DEL_ADMIN::CreateAnswer()
+{
+//answerList->clear();
+answerList->erase(answerList->begin(), answerList->end());
+
+if (admins->Del(adminToDel, *currAdmin) == 0)
+ {
+ answerList->push_back("<DelAdmin Result=\"Ok\"/>");
+ }
+else
+ {
+ string s;
+ strprintf(&s, "<DelAdmin Result=\"Error. %s\"/>", admins->GetStrError().c_str());
+ answerList->push_back(s);
+ }
+}
+//-----------------------------------------------------------------------------
+int PARSER_DEL_ADMIN::CheckAttr(const char **attr)
+{
+/* <DelAdmin login=\"admin\">
+ * attr[0] = "login" (word login)
+ * attr[1] = login, value of login
+ * attr[2] = NULL */
+
+if (strcasecmp(attr[0], "login") == 0 && attr[1] && !attr[2])
+ {
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+// ADD ADMIN
+//-----------------------------------------------------------------------------
+int PARSER_ADD_ADMIN::ParseStart(void *, const char *el, const char **attr)
+{
+if (strcasecmp(el, "AddAdmin") == 0)
+ {
+ adminToAdd = attr[1];
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int PARSER_ADD_ADMIN::ParseEnd(void *, const char *el)
+{
+//answerList->clear();
+answerList->erase(answerList->begin(), answerList->end());
+
+if (strcasecmp(el, "AddAdmin") == 0)
+ {
+ CreateAnswer();
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+void PARSER_ADD_ADMIN::CreateAnswer()
+{
+//answerList->clear();
+answerList->erase(answerList->begin(), answerList->end());
+
+if (admins->Add(adminToAdd, *currAdmin) == 0)
+ {
+ answerList->push_back("<AddAdmin Result=\"Ok\"/>");
+ }
+else
+ {
+ string s;
+ strprintf(&s, "<AddAdmin Result=\"Error. %s\"/>", admins->GetStrError().c_str());
+ answerList->push_back(s);
+ }
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// CHG ADMIN
+//-----------------------------------------------------------------------------
+int PARSER_CHG_ADMIN::ParseStart(void *, const char *el, const char **attr)
+{
+if (strcasecmp(el, "ChgAdmin") == 0)
+ {
+ for (int i = 0; i < 6; i+=2)
+ {
+ printfd(__FILE__, "PARSER_CHG_ADMIN::attr[%d] = %s\n", i, attr[i]);
+ if (attr[i] == NULL)
+ break;
+
+ if (strcasecmp(attr[i], "Login") == 0)
+ {
+ login = attr[i + 1];
+ continue;
+ }
+
+ if (strcasecmp(attr[i], "Priv") == 0)
+ {
+ privAsString = attr[i + 1];
+ continue;
+ }
+
+ if (strcasecmp(attr[i], "Password") == 0)
+ {
+ password = attr[i + 1];
+ continue;
+ }
+ }
+
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int PARSER_CHG_ADMIN::ParseEnd(void *, const char *el)
+{
+if (strcasecmp(el, "ChgAdmin") == 0)
+ {
+ CreateAnswer();
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+void PARSER_CHG_ADMIN::CreateAnswer()
+{
+answerList->erase(answerList->begin(), answerList->end());
+
+ADMIN_CONF conf;
+conf.login = login;
+if (!login.res_empty())
+ {
+ string s;
+ //if (admins->FindAdmin(login.data()) != NULL)
+ // {
+ if (!password.res_empty())
+ conf.password = password.data();
+
+ if (!privAsString.res_empty())
+ {
+ int p = 0;
+ if (str2x(privAsString.data().c_str(), p) < 0)
+ {
+ strprintf(&s, "<ChgAdmin Result = \"Incorrect parameter Priv.\"/>" );
+ answerList->push_back(s);
+ return;
+ }
+ //memcpy(&conf.priv, &p, sizeof(conf.priv));
+ conf.priv.userStat = (p & 0x0003) >> 0x00; // 1+2
+ conf.priv.userConf = (p & 0x000C) >> 0x02; // 4+8
+ conf.priv.userCash = (p & 0x0030) >> 0x04; // 10+20
+ conf.priv.userPasswd = (p & 0x00C0) >> 0x06; // 40+80
+ conf.priv.userAddDel = (p & 0x0300) >> 0x08; // 100+200
+ conf.priv.adminChg = (p & 0x0C00) >> 0x0A; // 400+800
+ conf.priv.tariffChg = (p & 0x3000) >> 0x0C; // 1000+2000
+ }
+
+ if (admins->Change(conf, *currAdmin) != 0)
+ {
+ strprintf(&s, "<ChgAdmin Result = \"%s\"/>", admins->GetStrError().c_str());
+ answerList->push_back(s);
+ }
+ else
+ {
+ answerList->push_back("<ChgAdmin Result = \"Ok\"/>");
+ }
+ return;
+ // }
+ //strprintf(&s, "<ChgAdmin Result = \"%s\"/>", admins->GetStrError().c_str());
+ //answerList->push_back(s);
+ //return;
+ }
+else
+ {
+ answerList->push_back("<ChgAdmin Result = \"Incorrect parameter login.\"/>");
+ }
+}
+//-----------------------------------------------------------------------------*/
+
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+
+#include "parser.h"
+//#include "admins.h"
+//#include "tariff2.h"
+const int pt_mega = 1024 * 1024;
+//-----------------------------------------------------------------------------
+// GET TARIFFS
+//-----------------------------------------------------------------------------
+int PARSER_GET_TARIFFS::ParseStart(void *, const char *el, const char **)
+{
+if (strcasecmp(el, "GetTariffs") == 0)
+ {
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int PARSER_GET_TARIFFS::ParseEnd(void *, const char *el)
+{
+if (strcasecmp(el, "GetTariffs") == 0)
+ {
+ CreateAnswer();
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+void PARSER_GET_TARIFFS::CreateAnswer()
+{
+string s;
+char vs[100];
+int hd, hn, md, mn;
+
+//answerList->clear();
+answerList->erase(answerList->begin(), answerList->end());
+
+answerList->push_back("<Tariffs>");
+int h = tariffs->OpenSearch();
+
+TARIFF_DATA td;
+while (tariffs->SearchNext(h, &td) == 0)
+ {
+ s = "<tariff name=\"" + td.tariffConf.name + "\">";
+ //printfd(__FILE__, "%s\n", s.c_str());
+ answerList->push_back(s);
+
+ for (int j = 0; j < DIR_NUM; j++)
+ {
+ hd = td.dirPrice[j].hDay;
+ md = td.dirPrice[j].mDay;
+
+ hn = td.dirPrice[j].hNight;
+ mn = td.dirPrice[j].mNight;
+
+ strprintf(&s, "<Time%d value=\"%d:%d-%d:%d\"/>", j, hd, md, hn, mn);
+ answerList->push_back(s);
+ }
+
+ strprintf(&s, " <PriceDayA value=\"");
+ for (int i = 0; i < DIR_NUM; i++)
+ {
+ snprintf(vs, 100, "%.5f%s", td.dirPrice[i].priceDayA * pt_mega, i+1 == DIR_NUM?"":"/");
+ s += vs;
+ }
+ s += "\"/>";
+ answerList->push_back(s);
+
+ strprintf(&s, " <PriceDayB value=\"");
+ for (int i = 0; i < DIR_NUM; i++)
+ {
+ snprintf(vs, 100, "%.5f%s", td.dirPrice[i].priceDayB * pt_mega, i+1 == DIR_NUM?"":"/");
+ s += vs;
+ }
+ s += "\"/>";
+ answerList->push_back(s);
+
+ strprintf(&s, " <PriceNightA value=\"");
+ for (int i = 0; i < DIR_NUM; i++)
+ {
+ snprintf(vs, 100, "%.5f%s", td.dirPrice[i].priceNightA * pt_mega, i+1 == DIR_NUM?"":"/");
+ s += vs;
+ }
+ s += "\"/>";
+ answerList->push_back(s);
+
+ strprintf(&s, " <PriceNightB value=\"");
+ for (int i = 0; i < DIR_NUM; i++)
+ {
+ snprintf(vs, 100, "%.5f%s", td.dirPrice[i].priceNightB * pt_mega, i+1 == DIR_NUM?"":"/");
+ s += vs;
+ }
+ s += "\"/>";
+ answerList->push_back(s);
+
+ strprintf(&s, " <Threshold value=\"");
+ for (int i = 0; i < DIR_NUM; i++)
+ {
+ snprintf(vs, 100, "%d%s", td.dirPrice[i].threshold, i+1 == DIR_NUM?"":"/");
+ s += vs;
+ }
+ s += "\"/>";
+ answerList->push_back(s);
+
+ strprintf(&s, " <SinglePrice value=\"");
+ for (int i = 0; i < DIR_NUM; i++)
+ {
+ snprintf(vs, 100, "%d%s", td.dirPrice[i].singlePrice, i+1 == DIR_NUM?"":"/");
+ s += vs;
+ }
+ s += "\"/>";
+ answerList->push_back(s);
+
+ strprintf(&s, " <NoDiscount value=\"");
+ for (int i = 0; i < DIR_NUM; i++)
+ {
+ snprintf(vs, 100, "%d%s", td.dirPrice[i].noDiscount, i+1 == DIR_NUM?"":"/");
+ s += vs;
+ }
+ s += "\"/>";
+ answerList->push_back(s);
+
+ strprintf(&s, " <Fee value=\"%.5f\"/>", td.tariffConf.fee);
+ answerList->push_back(s);
+ //printfd(__FILE__, "%s\n", s.c_str());
+
+ strprintf(&s, " <PassiveCost value=\"%.5f\"/>", td.tariffConf.passiveCost);
+ answerList->push_back(s);
+
+ strprintf(&s, " <Free value=\"%.5f\"/>", td.tariffConf.free);
+ answerList->push_back(s);
+
+ switch (td.tariffConf.traffType)
+ {
+ case TRAFF_UP:
+ answerList->push_back("<TraffType value=\"up\"/>");
+ break;
+ case TRAFF_DOWN:
+ answerList->push_back("<TraffType value=\"down\"/>");
+ break;
+ case TRAFF_UP_DOWN:
+ answerList->push_back("<TraffType value=\"up+down\"/>");
+ break;
+ case TRAFF_MAX:
+ answerList->push_back("<TraffType value=\"max\"/>");
+ break;
+ }
+
+ answerList->push_back("</tariff>");
+ }
+tariffs->CloseSearch(h);
+answerList->push_back("</Tariffs>");
+}
+//-----------------------------------------------------------------------------
+// ADD TARIFF
+//-----------------------------------------------------------------------------
+int PARSER_ADD_TARIFF::ParseStart(void *, const char *el, const char **attr)
+{
+if (strcasecmp(el, "AddTariff") == 0)
+ {
+ if (attr[1])
+ {
+ tariffToAdd = attr[1];
+ }
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int PARSER_ADD_TARIFF::ParseEnd(void *, const char *el)
+{
+if (strcasecmp(el, "AddTariff") == 0)
+ {
+ CreateAnswer();
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+void PARSER_ADD_TARIFF::CreateAnswer()
+{
+//answerList->clear();
+answerList->erase(answerList->begin(), answerList->end());
+
+if (tariffs->Add(tariffToAdd, *currAdmin) == 0)
+ {
+ answerList->push_back("<AddTariff Result=\"Ok\"/>");
+ }
+else
+ {
+ string s;
+ strprintf(&s, "<AddTariff Result=\"Error. %s\"/>", tariffs->GetStrError().c_str());
+ answerList->push_back(s);
+ }
+}
+//-----------------------------------------------------------------------------
+// DEL TARIFF
+//-----------------------------------------------------------------------------
+int PARSER_DEL_TARIFF::ParseStart(void *, const char *el, const char **attr)
+{
+strError = "";
+if (strcasecmp(el, "DelTariff") == 0)
+ {
+ tariffToDel = attr[1];
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int PARSER_DEL_TARIFF::ParseEnd(void *, const char *el)
+{
+if (strcasecmp(el, "DelTariff") == 0)
+ {
+ CreateAnswer();
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+void PARSER_DEL_TARIFF::CreateAnswer()
+{
+//answerList->clear();
+answerList->erase(answerList->begin(), answerList->end());
+
+if (tariffs->Del(tariffToDel, *currAdmin) == 0)
+ {
+ answerList->push_back("<DelTariff Result=\"Ok\"/>");
+ }
+else
+ {
+ string s;
+ strprintf(&s, "<DelTariff Result=\"Error. %s\"/>", tariffs->GetStrError().c_str());
+ answerList->push_back(s);
+ }
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// CHG TARIFF
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+int PARSER_CHG_TARIFF::ParseSlashedIntParams(int paramsNum, const string & s, int * params)
+{
+char * str = new char[s.size() + 1];
+char * p;
+strcpy(str, s.c_str());
+p = strtok(str, "/");
+
+for (int i = 0; i < paramsNum; i++)
+ {
+ if (p == NULL)
+ {
+ delete[] str;
+ return -1;
+ }
+
+ if (str2x(p, params[i]) != 0)
+ {
+ delete[] str;
+ return -1;
+ }
+
+ p = strtok(NULL, "/");
+ }
+
+delete[] str;
+return 0;
+}
+//-----------------------------------------------------------------------------
+int PARSER_CHG_TARIFF::ParseSlashedDoubleParams(int paramsNum, const string & s, double * params)
+{
+char * str = new char[s.size() + 1];
+char * p;
+strcpy(str, s.c_str());
+p = strtok(str, "/");
+
+for (int i = 0; i < paramsNum; i++)
+ {
+ if (p == NULL)
+ {
+ delete[] str;
+ return -1;
+ }
+
+ if (strtodouble2(p, params[i]) != 0)
+ {
+ delete[] str;
+ return -1;
+ }
+
+ p = strtok(NULL, "/");
+ }
+
+delete[] str;
+return 0;
+}
+//-----------------------------------------------------------------------------
+int PARSER_CHG_TARIFF::ParseStart(void *, const char *el, const char **attr)
+{
+char st[50];
+double price[DIR_NUM];
+int t[DIR_NUM];
+depth++;
+
+if (depth == 1)
+ {
+ if (strcasecmp(el, "SetTariff") == 0)
+ {
+ td.tariffConf.name = attr[1];
+ return 0;
+ }
+ }
+else
+ {
+ string s;
+
+ if (strcasecmp(el, "PriceDayA") == 0)
+ {
+ s = attr[1];
+ if (ParseSlashedDoubleParams(DIR_NUM, s, price) == 0)
+ for (int j = 0; j < DIR_NUM; j++)
+ td.dirPrice[j].priceDayA = price[j] / pt_mega;
+ return 0;
+ }
+
+ if (strcasecmp(el, "PriceDayB") == 0)
+ {
+ s = attr[1];
+ if (ParseSlashedDoubleParams(DIR_NUM, s, price) == 0)
+ for (int j = 0; j < DIR_NUM; j++)
+ td.dirPrice[j].priceDayB = price[j] / pt_mega;
+ return 0;
+ }
+
+
+ if (strcasecmp(el, "PriceNightA") == 0)
+ {
+ s = attr[1];
+ if (ParseSlashedDoubleParams(DIR_NUM, s, price) == 0)
+ for (int j = 0; j < DIR_NUM; j++)
+ td.dirPrice[j].priceNightA = price[j] / pt_mega;
+ return 0;
+ }
+
+ if (strcasecmp(el, "PriceNightB") == 0)
+ {
+ s = attr[1];
+ if (ParseSlashedDoubleParams(DIR_NUM, s, price) == 0)
+ for (int j = 0; j < DIR_NUM; j++)
+ td.dirPrice[j].priceNightB = price[j] / pt_mega;
+ return 0;
+ }
+
+ if (strcasecmp(el, "Threshold") == 0)
+ {
+ s = attr[1];
+ if (ParseSlashedIntParams(DIR_NUM, s, t) == 0)
+ for (int j = 0; j < DIR_NUM; j++)
+ td.dirPrice[j].threshold = t[j];
+ return 0;
+ }
+
+ if (strcasecmp(el, "SinglePrice") == 0)
+ {
+ s = attr[1];
+ if (ParseSlashedIntParams(DIR_NUM, s, t) == 0)
+ for (int j = 0; j < DIR_NUM; j++)
+ td.dirPrice[j].singlePrice = t[j];
+ return 0;
+ }
+
+ if (strcasecmp(el, "NoDiscount") == 0)
+ {
+ s = attr[1];
+ if (ParseSlashedIntParams(DIR_NUM, s, t) == 0)
+ for (int j = 0; j < DIR_NUM; j++)
+ td.dirPrice[j].noDiscount = t[j];
+ return 0;
+ }
+
+ for (int j = 0; j < DIR_NUM; j++)
+ {
+ snprintf(st, 50, "Time%d", j);
+ if (strcasecmp(el, st) == 0)
+ {
+ int h1, m1, h2, m2;
+ if (ParseTariffTimeStr(attr[1], h1, m1, h2, m2) == 0)
+ {
+ td.dirPrice[j].hDay = h1;
+ td.dirPrice[j].mDay = m1;
+ td.dirPrice[j].hNight = h2;
+ td.dirPrice[j].mNight = m2;
+ }
+ return 0;
+ }
+ }
+
+ if (strcasecmp(el, "Fee") == 0)
+ {
+ double fee;
+ if (strtodouble2(attr[1], fee) == 0)
+ td.tariffConf.fee = fee;
+ return 0;
+ }
+
+ if (strcasecmp(el, "PassiveCost") == 0)
+ {
+ double pc;
+ if (strtodouble2(attr[1], pc) == 0)
+ td.tariffConf.passiveCost = pc;
+ return 0;
+ }
+ if (strcasecmp(el, "Free") == 0)
+ {
+ double free;
+ if (strtodouble2(attr[1], free) == 0)
+ td.tariffConf.free = free;
+ return 0;
+ }
+
+ if (strcasecmp(el, "TraffType") == 0)
+ {
+ if (strcasecmp(attr[1], "up") == 0)
+ {
+ td.tariffConf.traffType = TRAFF_UP;
+ return 0;
+ }
+
+ if (strcasecmp(attr[1], "down") == 0)
+ {
+ td.tariffConf.traffType = TRAFF_DOWN;
+ return 0;
+ }
+ if (strcasecmp(attr[1], "up+down") == 0)
+ {
+ td.tariffConf.traffType = TRAFF_UP_DOWN;
+ return 0;
+ }
+ if (strcasecmp(attr[1], "max") == 0)
+ {
+ td.tariffConf.traffType = TRAFF_MAX;
+ return 0;
+ }
+ return 0;
+ }
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int PARSER_CHG_TARIFF::ParseEnd(void *, const char *el)
+{
+if (depth == 1)
+ {
+ if (strcasecmp(el, "SetTariff") == 0)
+ {
+ CreateAnswer();
+ depth--;
+ return 0;
+ }
+ }
+
+depth--;
+return -1;
+}
+//-----------------------------------------------------------------------------
+void PARSER_CHG_TARIFF::CreateAnswer()
+{
+answerList->erase(answerList->begin(), answerList->end());
+
+if (!td.tariffConf.name.data().empty())
+ {
+ TARIFF_DATA tariffData = td.GetData();
+ if (tariffs->Chg(tariffData, *currAdmin) == 0)
+ {
+ answerList->push_back("<SetTariff Result=\"ok\"/>");
+ return;
+ }
+ else
+ {
+ string s;
+ strprintf(&s, "<SetTariff Result=\"Change tariff error! %s\"/>", tariffs->GetStrError().c_str());
+ answerList->push_back(s);
+ return;
+ }
+ }
+answerList->push_back("<SetTariff Result=\"Change tariff error!\"/>");
+}
+//-----------------------------------------------------------------------------
+
--- /dev/null
+#ifndef __PROTO_H__
+#define __PROTO_H__
+
+namespace SGCONF2 {
+
+/*
+ * --- Protocol structure (binary part) ---
+ *
+ * Request:
+ * |---------------|
+ * |PROTOHEADER |
+ * |REQUESTHEADER |
+ * |---------------|
+ * | cryptodata |
+ * ~~~~~~~~~~~~~~~~~
+ * |---------------|
+ *
+ * Response:
+ * |---------------|
+ * |PROTOHEADER |
+ * |RESPONSEHEADER |
+ * | error message |
+ * | cryptodata |
+ * ~~~~~~~~~~~~~~~~~
+ * |---------------|
+ *
+ */
+
+ static char magic[8] = "STGCONF2";
+
+ enum RESPONSECODES {
+ E_OK = 0, // No error
+ E_NET_ERROR, // Network error (i.e. - timeout)
+ E_PROTO_ERROR, // Protocol error (invalid magic, unsupported version, etc.)
+ E_INVALID_LOGIN,// Invalid login
+ E_PERMISSIONS // Operation not permitted
+ };
+
+ struct PROTOHEADER {
+ char magic[8];
+ uint32_t version;
+ };
+
+ struct REQUESTHEADER {
+ char login[32];
+ };
+
+ struct CRYPTOHEADER {
+ char login[32];
+ uint32_t dataSize; // Can't be 0
+ };
+
+ struct RESPONSEHEADER {
+ uint32_t code;
+ uint32_t errorMessageSize; // May be 0
+ uint32_t dataSize; // May be 0
+ };
+
+}
+
+#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
+ */
+
+/*******************************************************************
+*
+* DESCRIPTION: æÁÊÌ Ó ÏÓÎÏ×ÎÙÍÉ ÆÕÎËÃÉÑÍÉ ÄÌÑ ÓÅÔÅ×ÏÇÏ ÏÂÍÅÎÁ ÄÁÎÎÙÍÉ
+* Ó ÍÅÎÅÄÖÅÒÏÍ ËÌÉÅÎÔÏ×. ðÒÉÅÍ, ÐÅÒÅÄÁÞÁ É ÛÉÆÒÏ×ÁÎÉÅ ÓÏÏÂÝÅÎÉÊ.
+*
+* AUTHOR: Boris Mikhailenko <stg34@stargazer.dp.ua>
+*
+* $Revision: 1.20 $
+* $Date: 2009/10/31 15:44:02 $
+*
+*******************************************************************/
+
+#include <unistd.h>
+#include <stdio.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netinet/tcp.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <pthread.h>
+
+#ifdef LINUX
+#include <error.h>
+#endif
+
+#ifdef FREE_BSD
+#include <sys/errno.h>
+#endif
+
+#ifdef FREE_BSD5
+#include <sys/errno.h>
+#endif
+
+extern int errno;
+
+#include "configproto.h"
+
+enum CONF_STATE
+ {
+ confHdr,
+ confLogin,
+ confLoginCipher,
+ confData
+ };
+
+enum
+ {
+ ans_ok = 0,
+ ans_err
+ };
+
+//-----------------------------------------------------------------------------
+int CONFIGPROTO::Prepare()
+{
+list<string> ansList; //óÀÄÁ ÂÕÄÅÔ ÐÏÍÅÝÅÎ ÏÔ×ÅÔ ÄÌÑ ÍÅÎÅÄÖÅÒÁ ËÌÉÅÎÔÏ×
+int res;
+struct sockaddr_in listenAddr;
+
+sigset_t sigmask, oldmask;
+sigemptyset(&sigmask);
+sigaddset(&sigmask, SIGINT);
+sigaddset(&sigmask, SIGTERM);
+sigaddset(&sigmask, SIGUSR1);
+sigaddset(&sigmask, SIGHUP);
+pthread_sigmask(SIG_BLOCK, &sigmask, &oldmask);
+
+listenSocket = socket(PF_INET, SOCK_STREAM, 0);
+
+if (listenSocket < 0)
+ {
+ errorStr = "Create NET_CONFIGURATOR socket failed.";
+ return -1;
+ }
+
+listenAddr.sin_family = PF_INET;
+listenAddr.sin_port = htons(port);
+listenAddr.sin_addr.s_addr = inet_addr("0.0.0.0");
+
+int lng = 1;
+
+if (0 != setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, &lng, 4))
+ {
+ errorStr = "Setsockopt failed. " + string(strerror(errno));
+ return -1;
+ }
+
+res = bind(listenSocket, (struct sockaddr*)&listenAddr, sizeof(listenAddr));
+
+if (res == -1)
+ {
+ errorStr = "Bind admin socket failed";
+ return -1;
+ }
+
+res = listen(listenSocket, 0);
+if (res == -1)
+ {
+ errorStr = "Listen admin socket failed";
+ return -1;
+ }
+outerAddrLen = sizeof(outerAddr);
+
+/*if (0 != fcntl(listenSocket, F_SETFL, O_NONBLOCK))
+ {
+ errorStr = "fcntl error!";
+ return -1;
+ }*/
+
+errorStr = "";
+nonstop = true;
+return 0;
+}
+//-----------------------------------------------------------------------------
+int CONFIGPROTO::Stop()
+{
+nonstop = false;
+close(listenSocket);
+//TODO: Idiotism
+int sock;
+struct sockaddr_in addr;
+socklen_t addrLen;
+addr.sin_family = PF_INET;
+addr.sin_port = htons(port);
+addr.sin_addr.s_addr = inet_addr("127.0.0.1");
+
+addrLen = sizeof(outerAddr);
+sock = socket(PF_INET, SOCK_STREAM, 0);
+connect(sock, (sockaddr*)&addr, addrLen);
+close(sock);
+//Idiotism end
+return 0;
+}
+//-----------------------------------------------------------------------------
+// æÕÎËÃÉÑ ÏÂÝÅÎÉÑ Ó ËÏÎÆÉÇÕÒÁÔÏÒÏÍ
+void * CONFIGPROTO::Run(void * a)
+{
+/*
+ * Function Name:ReciveSendConf
+ * Parameters: void * a ÕËÁÚÁÔÅÌØ ÎÁ ÜËÚÅÍÐÌÑÒ ËÌÁÓÓÁ CONFIGPROTO
+ * Description: üÔÁ ÆÕÎËÃÉÑ ÏÂÅÓÐÅÞÉ×ÁÅÔ ÓÅÔÅ×ÏÅ ×ÚÁÉÍÏÄÅÊÓÔ×ÉÅ
+ * Ó íÅÎÅÄÖÅÒÏÍ ëÌÉÅÎÔÏ×. ÷ ÅÅ ÚÁÄÁÞÉ ×ÈÏÄÉÔ: ÐÒÉÅÍ ÚÁÐÒÏÓÏ× ÐÏ TCP/IP
+ * ÉÈ ÒÁÓÛÉÆÒÏ×ËÁ, ÐÅÒÅÄÁÞÁ ÐÒÉÎÑÔÙÈ ÄÁÎÎÙÈ ÁÎÁÌÉÚÁÔÏÒÕ É ÏÔÐÒÁ×ËÁ ÏÔ×ÅÔÁ ÎÁÚÁÄ.
+ * Returns: ×ÏÚ×ÒÁÝÁÅÔ NULL
+ */
+
+CONFIGPROTO * cp = (CONFIGPROTO*)a;
+cp->state = confHdr;
+
+while (cp->nonstop)
+ {
+ cp->state = confHdr;
+ cp->outerSocket = accept(cp->listenSocket,
+ (struct sockaddr*)(&cp->outerAddr),
+ &cp->outerAddrLen);
+
+ if (!cp->nonstop)
+ {
+ continue;
+ }
+
+ if (cp->outerSocket == -1)
+ {
+ printfd(__FILE__, "accept failed\n");
+ usleep(100000);
+ continue;
+ }
+
+ cp->adminIP = *(unsigned int*)&(cp->outerAddr.sin_addr);
+
+ /* TODO
+ if (!cp->hostAllow->HostAllowed(cp->adminIP))
+ {
+ close(outerSocket);
+ continue;
+ }*/
+
+ printfd(__FILE__, "Connection accepted from %s\n", inet_ntostring(cp->outerAddr.sin_addr.s_addr).c_str());
+
+ if (cp->state == confHdr)
+ {
+ if (cp->RecvHdr(cp->outerSocket) < 0)
+ {
+ close(cp->outerSocket);
+ continue;
+ }
+ if (cp->state == confLogin)
+ {
+ if (cp->SendHdrAnswer(cp->outerSocket, ans_ok) < 0)
+ {
+ close(cp->outerSocket);
+ continue;
+ }
+
+ if (cp->RecvLogin(cp->outerSocket) < 0)
+ {
+ close(cp->outerSocket);
+ continue;
+ }
+
+ if (cp->state == confLoginCipher)
+ {
+ if (cp->SendLoginAnswer(cp->outerSocket, ans_ok) < 0)
+ {
+ close(cp->outerSocket);
+ continue;
+ }
+ if (cp->RecvLoginS(cp->outerSocket) < 0)
+ {
+ close(cp->outerSocket);
+ continue;
+ }
+
+ if (cp->state == confData)
+ {
+ if (cp->SendLoginSAnswer(cp->outerSocket, ans_ok) < 0)
+ {
+ close(cp->outerSocket);
+ continue;
+ }
+ if (cp->RecvData(cp->outerSocket) < 0)
+ {
+ close(cp->outerSocket);
+ continue;
+ }
+ cp->state = confHdr;
+ }
+ else
+ {
+ if (cp->SendLoginSAnswer(cp->outerSocket, ans_err) < 0)
+ {
+ close(cp->outerSocket);
+ continue;
+ }
+ cp->WriteLogAccessFailed(cp->adminIP);
+ }
+ }
+ else
+ {
+ cp->WriteLogAccessFailed(cp->adminIP);
+ }
+ }
+ else
+ {
+ cp->WriteLogAccessFailed(cp->adminIP);
+ if (cp->SendHdrAnswer(cp->outerSocket, ans_err) < 0)
+ {
+ close(cp->outerSocket);
+ continue;
+ }
+ }
+ }
+ else
+ {
+ cp->WriteLogAccessFailed(cp->adminIP);
+ }
+ close(cp->outerSocket);
+ }
+
+return NULL;
+}
+//-----------------------------------------------------------------------------
+int CONFIGPROTO::RecvHdr(int sock)
+{
+char buf[sizeof(STG_HEADER)];
+memset(buf, 0, sizeof(STG_HEADER));
+int ret;
+int stgHdrLen = strlen(STG_HEADER);
+for (int i = 0; i < stgHdrLen; i++)
+ {
+ ret = recv(sock, &buf[i], 1, 0);
+ if (ret <= 0)
+ {
+ state = confHdr;
+ return -1;
+ }
+ }
+
+if (0 == strncmp(buf, STG_HEADER, strlen(STG_HEADER)))
+ {
+ state = confLogin;
+ return 0;
+ }
+else
+ {
+ SendError("Bad request");
+ }
+
+state = confHdr;
+return -1;
+}
+//-----------------------------------------------------------------------------
+int CONFIGPROTO::SendHdrAnswer(int sock, int err)
+{
+int ret;
+
+if (err)
+ {
+ ret = send(sock, ERR_HEADER, sizeof(ERR_HEADER)-1, 0);
+ if (ret < 0)
+ {
+ WriteServLog("send ERR_HEADER error in SendHdrAnswer.");
+ return -1;
+ }
+ }
+else
+ {
+ ret = send(sock, OK_HEADER, sizeof(OK_HEADER)-1, 0);
+ if (ret < 0)
+ {
+ WriteServLog("send OK_HEADER error in SendHdrAnswer.");
+ return -1;
+ }
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int CONFIGPROTO::RecvLogin(int sock)
+{
+char login[ADM_LOGIN_LEN+1];
+int ret;
+
+memset(login, 0, ADM_LOGIN_LEN + 1);
+
+//printfd(__FILE__, "RecvLogin\n");
+
+/*for (int i = 0; i < ADM_LOGIN_LEN; i++)
+ {
+ ret = recv(sock, &login[i], 1, 0);
+
+ if (ret <= 0)
+ {
+ close(sock);
+ state = confHdr;
+ return ENODATA;
+ }
+ }*/
+
+ret = recv(sock, login, ADM_LOGIN_LEN, 0);
+
+if (ret < 0)
+ {
+ // Error in network
+ close(sock);
+ state = confHdr;
+ return ENODATA;
+ }
+
+if (ret < ADM_LOGIN_LEN)
+ {
+ // Error in protocol
+ close(sock);
+ state = confHdr;
+ return ENODATA;
+ }
+
+currAdmin = admins->FindAdmin(login);
+adminLogin = login;
+state = confLoginCipher;
+return 0;
+}
+//-----------------------------------------------------------------------------
+int CONFIGPROTO::SendLoginAnswer(int sock, int)
+{
+int ret;
+
+ret = send(sock, OK_LOGIN, sizeof(OK_LOGIN)-1, 0);
+if (ret < 0)
+ {
+ WriteServLog("Send OK_LOGIN error in SendLoginAnswer.");
+ return -1;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int CONFIGPROTO::RecvLoginS(int sock)
+{
+char loginS[ADM_LOGIN_LEN + 1];
+char login[ADM_LOGIN_LEN + 1];
+int ret;
+BLOWFISH_CTX ctx;
+memset(loginS, 0, ADM_LOGIN_LEN + 1);
+
+//printfd(__FILE__, "RecvLoginS\n");
+
+/*for (int i = 0; i < ADM_LOGIN_LEN; i++)
+ {
+ ret = recv(sock, &loginS[i], 1, 0);
+
+ if (ret <= 0)
+ {
+ //printfd(__FILE__, "RecvLoginS close\n");
+ close(sock);
+ state = confHdr;
+ return ENODATA;
+ }
+ }*/
+
+int total = 0;
+
+while (total < ADM_LOGIN_LEN)
+ {
+ ret = recv(sock, &loginS[total], ADM_LOGIN_LEN - total, 0);
+
+ if (ret < 0)
+ {
+ // Network error
+ printfd(__FILE__, "recv error: '%s'\n", strerror(errno));
+ close(sock);
+ state = confHdr;
+ return ENODATA;
+ }
+
+ total += ret;
+ }
+
+// TODO: implement select on socket
+/*if (total < ADM_LOGIN_LEN)
+ {
+ // Protocol error
+ printfd(__FILE__, "Protocol error. Need %d bytes of cryptologin. Got %d bytes.\n", ADM_LOGIN_LEN, ret);
+ close(sock);
+ state = confHdr;
+ return ENODATA;
+ }*/
+
+if (currAdmin == NULL)
+ {
+ state = confHdr;
+ return ENODATA;
+ }
+
+EnDecodeInit(currAdmin->GetPassword().c_str(), ADM_PASSWD_LEN, &ctx);
+
+for (int i = 0; i < ADM_LOGIN_LEN/8; i++)
+ {
+ DecodeString(login + i*8, loginS + i*8, &ctx);
+ }
+
+if (currAdmin == admins->GetNoAdmin())
+ {
+ // If there are no admins registered in the system - give access with any password
+ state = confData;
+ return 0;
+ }
+
+if (strncmp(currAdmin->GetLogin().c_str(), login, ADM_LOGIN_LEN) != 0)
+ {
+ state = confHdr;
+ return ENODATA;
+ }
+
+state = confData;
+return 0;
+}
+//-----------------------------------------------------------------------------
+int CONFIGPROTO::SendLoginSAnswer(int sock, int err)
+{
+int ret;
+
+if (err)
+ {
+ ret = send(sock, ERR_LOGINS, sizeof(ERR_LOGINS)-1, 0);
+ if (ret < 0)
+ {
+ WriteServLog("send ERR_LOGIN error in SendLoginAnswer.");
+ return -1;
+ }
+ }
+else
+ {
+ ret = send(sock, OK_LOGINS, sizeof(OK_LOGINS)-1, 0);
+ if (ret < 0)
+ {
+ WriteServLog("send OK_LOGINS error in SendLoginSAnswer.");
+ return -1;
+ }
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int CONFIGPROTO::RecvData(int sock)
+{
+//printfd(__FILE__, "RecvData\n");
+int n = 0;
+int ret;
+char bufferS[8];
+char buffer[9];
+
+buffer[8] = 0;
+
+requestList.clear();
+BLOWFISH_CTX ctx;
+
+EnDecodeInit(currAdmin->GetPassword().c_str(), ADM_PASSWD_LEN, &ctx);
+
+while (1)
+ {
+ /*ret = recv(sock, &bufferS[n++], 1, 0);
+ if (ret <= 0)
+ {
+ //printfd(__FILE__, "RecvData close\n");
+ close(sock);
+ return 0;
+ }*/
+ int total = 0;
+ bool done = false;
+ while (total < 8)
+ {
+ ret = recv(sock, &bufferS[total], 8 - total, 0);
+ if (ret < 0)
+ {
+ // Network error
+ close(sock);
+ return 0;
+ }
+
+ if (ret < 8)
+ {
+ if (memchr(buffer, 0, ret) != NULL)
+ {
+ done = true;
+ break;
+ }
+ }
+
+ total += ret;
+ }
+
+ DecodeString(buffer, bufferS, &ctx);
+ requestList.push_back(std::string(buffer, total));
+
+ if (done || memchr(buffer, 0, total) != NULL)
+ {
+ // ëÏÎÅà ÐÏÓÙÌËÉ
+ if (ParseCommand())
+ {
+ SendError("Bad command");
+ }
+ return SendDataAnswer(sock);
+ }
+
+ /*if (n == 8)
+ {
+ n = 0;
+ DecodeString(buffer, bufferS, &ctx);
+ requestList.push_back(std::string(buffer, 8));
+ for (int j = 0; j < 8; j++)
+ {
+ if (buffer[j] == 0)
+ {
+ // ëÏÎÅà ÐÏÓÙÌËÉ
+ if (ParseCommand())
+ {
+ SendError("Bad command");
+ }
+ return SendDataAnswer(sock);
+ }
+ }
+ }*/
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int CONFIGPROTO::SendDataAnswer(int sock)
+{
+list<string>::iterator li;
+li = answerList.begin();
+
+BLOWFISH_CTX ctx;
+
+char buff[8];
+char buffS[8];
+int n = 0;
+int k = 0;
+int ret = 0;
+
+EnDecodeInit(currAdmin->GetPassword().c_str(), ADM_PASSWD_LEN, &ctx);
+
+while (li != answerList.end())
+ {
+ while ((*li).c_str()[k])
+ {
+ buff[n%8] = (*li).c_str()[k];
+ n++;
+ k++;
+
+ if (n%8 == 0)
+ {
+ EncodeString(buffS, buff, &ctx);
+ ret = send(sock, buffS, 8, 0);
+ if (ret < 0)
+ {
+ return -1;
+ }
+ }
+ }
+ k = 0;// new node
+ li++;
+ }
+
+if (answerList.empty()) {
+ return 0;
+}
+
+buff[n%8] = 0;
+EncodeString(buffS, buff, &ctx);
+
+answerList.clear();
+
+return send(sock, buffS, 8, 0);
+}
+//-----------------------------------------------------------------------------
+void CONFIGPROTO::SendError(const char * text)
+{
+char s[255];
+answerList.clear();
+sprintf(s, "<Error value=\"%s\"/>", text);
+answerList.push_back(s);
+}
+//-----------------------------------------------------------------------------
+void CONFIGPROTO::WriteLogAccessFailed(uint32_t ip)
+{
+WriteServLog("Admin's connect failed. IP %s", inet_ntostring(ip).c_str());
+}
+//-----------------------------------------------------------------------------
+
+
+
--- /dev/null
+#include <cstdio>
+#include <cunistd>
+#include <csignal>
+#include <functional>
+#include <algorithm>
+
+#include "stgconfig.h"
+#include "../../../tariffs.h"
+#include "../../../admins.h"
+#include "../../../users.h"
+
+class STGCONFIG_CREATOR
+{
+private:
+ STG_CONFIG * stgconfig;
+
+public:
+ STGCONFIG_CREATOR()
+ : stgconfig(new STG_CONFIG())
+ {
+ };
+ ~STGCONFIG_CREATOR()
+ {
+ delete stgconfig;
+ };
+
+ STG_CONFIG * GetPlugin()
+ {
+ return stgconfig;
+ };
+};
+
+STGCONFIG_CREATOR stgc;
+
+BASE_PLUGIN * GetPlugin()
+{
+return stgc.GetPlugin();
+}
+
+STG_CONFIG_SETTINGS::STG_CONFIG_SETTINGS()
+ : port(0)
+{
+}
+
+const string& STG_CONFIG_SETTINGS::GetStrError() const
+{
+return errorStr;
+}
+
+int STG_CONFIG_SETTINGS::ParseIntInRange(const string & str, int min, int max, int * val)
+{
+if (str2x(str.c_str(), *val))
+ {
+ errorStr = "Incorrect value \'" + str + "\'.";
+ return -1;
+ }
+if (*val < min || *val > max)
+ {
+ errorStr = "Value \'" + str + "\' out of range.";
+ return -1;
+ }
+return 0;
+}
+
+int STG_CONFIG_SETTINGS::ParseSettings(const MODULE_SETTINGS & s)
+{
+int p;
+PARAM_VALUE pv;
+vector<PARAM_VALUE>::const_iterator pvi;
+///////////////////////////
+pv.param = "Port";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end())
+ {
+ errorStr = "Parameter \'Port\' not found.";
+ printfd(__FILE__, "Parameter 'Port' not found\n");
+ return -1;
+ }
+if (ParseIntInRange(pvi->value[0], 2, 65535, &p))
+ {
+ errorStr = "Cannot parse parameter \'Port\': " + errorStr;
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+port = p;
+
+return 0;
+}
+
+uint16_t STG_CONFIG_SETTINGS::GetPort()
+{
+return port;
+}
+
+STG_CONFIG::STG_CONFIG()
+ : running(false),
+ stopped(true)
+{
+}
+
+string STG_CONFIG::GetVersion() const
+{
+return "Stg configurator v.2.00";
+}
+
+int STG_CONFIG::ParseSettings()
+{
+int ret = stgConfigSettings.ParseSettings(settings);
+if (ret)
+ errorStr = stgConfigSettings.GetStrError();
+return ret;
+}
+
+int STG_CONFIG::Start()
+{
+if (running)
+ return false;
+
+if (PrepareNetwork())
+ return true;
+
+stopped = false;
+
+config.SetPort(stgConfigSettings.GetPort());
+config.SetAdmins(admins);
+config.SetUsers(users);
+config.SetTariffs(tariffs);
+config.SetStgSettings(stgSettings);
+config.SetStore(store);
+
+if (config.Prepare())
+ {
+ errorStr = config.GetStrError();
+ return true;
+ }
+
+if (pthread_create(&thread, NULL, Run, this))
+ {
+ errorStr = "Cannot create thread.";
+ printfd(__FILE__, "Cannot create thread\n");
+ return true;
+ }
+
+errorStr = "";
+return false;
+}
+
+int STG_CONFIG::Stop()
+{
+if (!running)
+ return false;
+
+running = false;
+
+config.Stop();
+
+//5 seconds to thread stops itself
+int i;
+for (i = 0; i < 25 && !stopped; i++)
+ {
+ usleep(200000);
+ }
+
+//after 5 seconds waiting thread still running. now killing it
+if (!stopped)
+ {
+ //TODO pthread_cancel()
+ if (pthread_kill(thread, SIGINT))
+ {
+ errorStr = "Cannot kill thread.";
+ printfd(__FILE__, "Cannot kill thread\n");
+ return FinalizeNetwork();
+ }
+ printfd(__FILE__, "STG_CONFIG killed\n");
+ }
+
+return FinalizeNetwork();
+}
+
+void * STG_CONFIG::Run(void * d)
+{
+STG_CONFIG * stgConf = static_cast<STG_CONFIG *>(d);
+stgConf->running = true;
+
+stgConf->RealRun();
+
+stgConf->stopped = true;
+return NULL;
+}
+
+uint16_t STG_CONFIG::GetStartPosition() const
+{
+return 220;
+}
+
+uint16_t STG_CONFIG::GetStopPosition() const
+{
+return 220;
+}
+
+bool PrepareNetwork()
+{
+struct sockaddr_in local;
+
+local.sin_family = AF_INET;
+local.sin_port = htons(port);
+local.sin_addr.s_addr = INADDR_ANY;
+
+sd = socket(AF_INET, SOCK_STREAM, 0);
+if (sd < 0)
+ {
+ errorStr = "Error creating socket: '";
+ errorStr += strerror(errno);
+ errorStr += "'";
+ return true;
+ }
+
+if (bind(sd, static_cast<struct sockaddr *>(&local), sizeof(local)) < 0)
+ {
+ errorStr = "Error binding socket: '";
+ errorStr += strerror(errno);
+ errorStr += "'";
+ return true;
+ }
+
+return false;
+}
+
+bool FinalizeNetwork()
+{
+if (close(sd) < 0)
+ {
+ errorStr = "Error closing socket: '";
+ errorStr += strerror(errno);
+ errorStr += "'";
+ return true;
+ }
+return false;
+}
+
+void STG_CONFIG::RealRun()
+{
+if (listen(sd, 64) < 0)
+ {
+ errorStr = "Error listening socket: '";
+ errorStr += strerror(errno);
+ errorStr += "'";
+ return;
+ }
+
+fd_set rfds;
+
+FD_ZERO(&rfds);
+FD_SET(sd, &rfds);
+
+running = true;
+while (running)
+ {
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = 500000;
+
+ int res = select(sd + 1, &rfds, NULL, NULL, &tv);
+
+ if (res < 0)
+ {
+ // Error logging
+ }
+ else if (res == 0)
+ {
+ // Timeout
+ }
+ else
+ {
+ if (FD_ISSET(sd, &rfds))
+ {
+ AcceptConnection();
+ }
+ }
+
+ // Reorder: right part is done
+ std::list<ConnectionThread *>::iterator done(
+ std::remove_if(
+ connections.begin(),
+ connections.end(),
+ std::not1(std::mem_fun(&ConnectionThread::isDone))
+ )
+ );
+ // Destruct done
+ std::for_each(
+ done,
+ connections.end(),
+ DeleteConnection());
+ // Erase done
+ std::erase(done, connections.end());
+
+ }
+stopped = true;
+}
+
+void STG_CONFIG::AcceptConnection()
+{
+struct sockaddr_in remoteAddr;
+socklen_t len = sizeof(struct sockaddr_in);
+int rsd = accept(sd, &remoteAddr, &len);
+
+if (rsd < 0)
+ {
+ // Error logging
+ }
+
+connections.push_back(new ConnectionThread(this, rsd, remoteAddr, users, admins, tariffs, store, stgSettings));
+}
--- /dev/null
+#include <pthread.h>
+
+#include <string>
+#include <list>
+
+#include "base_plugin.h"
+#include "base_store.h"
+#include "configproto.h"
+
+using namespace std;
+
+extern "C" BASE_PLUGIN * GetPlugin();
+
+class STG_CONFIG;
+
+//-----------------------------------------------------------------------------
+class STG_CONFIG_SETTINGS
+{
+public:
+ STG_CONFIG_SETTINGS();
+ virtual ~STG_CONFIG_SETTINGS(){};
+ const string & GetStrError() const;
+ int ParseSettings(const MODULE_SETTINGS & s);
+ uint16_t GetPort();
+private:
+ int ParseIntInRange(const string & str, int min, int max, int * val);
+ string errorStr;
+ int port;
+};
+//-----------------------------------------------------------------------------
+class STG_CONFIG: public BASE_PLUGIN
+{
+public:
+ STG_CONFIG();
+ virtual ~STG_CONFIG(){};
+
+ void SetUsers(USERS * u) { users = u; };
+ void SetTariffs(TARIFFS * t) { tariffs = t; };
+ void SetAdmins(ADMINS * a) { admins = a; };
+ void SetStore(BASE_STORE * s) { store = s; };
+ void SetTraffcounter(TRAFFCOUNTER *) {};
+ void SetStgSettings(const SETTINGS * s) { stgConfigSettings = s; };
+ void SetSettings(const MODULE_SETTINGS & s) { settings = s; };
+ int ParseSettings();
+
+ int Start();
+ int Stop();
+ int Reload() { return 0; };
+ bool IsRunning() { return running; };
+
+ const string & GetStrError() const { return errorStr; };
+ string GetVersion() const;
+ uint16_t GetStartPosition() const;
+ uint16_t GetStopPosition() const;
+
+private:
+ static void * Run(void *);
+ void RealRun();
+ bool PrepareNetwork();
+ bool FinalizeNetwork();
+ void AcceptConnection();
+
+ mutable string errorStr;
+ STG_CONFIG_SETTINGS stgConfigSettings;
+ pthread_t thread;
+ bool running;
+ bool stopped;
+ CONFIGPROTO config;
+ USERS * users;
+ ADMINS * admins;
+ TARIFFS * tariffs;
+ BASE_STORE * store;
+ MODULE_SETTINGS settings;
+ const SETTINGS * stgSettings;
+
+ std::list<ConnectionThread *> connections;
+
+ int sd;
+};
+//-----------------------------------------------------------------------------
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.3 2009/03/03 15:49:35 faust Exp $
+###############################################################################
+DEFS = -DLINUX
+
+ifeq ($(OS),bsd)
+DEFS = -DFREE_BSD
+endif
+
+ifeq ($(OS),bsd5)
+DEFS = -DFREE_BSD5
+endif
+
+
+DIR_INCLUDE = ../../../../../include
+DIR_LIB = ../../../../../lib
+
+PROG = mod_conf_xr.so
+
+SRCS = ./xrconfig.cpp
+
+
+LIBS = $(LIB_THREAD)
+
+SEARCH_DIRS = -I $(DIR_INCLUDE)
+
+OBJS = $(notdir $(patsubst %.cpp, %.o, $(patsubst %.c, %.o, $(SRCS))))
+
+CXXFLAGS = -g3 -Wall -fPIC
+LDFLAGS = -g3 -shared
+
+
+vpath %.a $(DIR_LIB)
+
+
+all: $(PROG)
+
+$(PROG): $(OBJS) $(LIBS)
+ $(CC) $^ $(LDFLAGS) -o $(PROG)
+
+clean:
+ rm -f deps $(PROG) *.o tags *.*~
+
+
+install:
+ echo TODO
+
+uninstall:
+ echo TODO
+
+ifneq ($(MAKECMDGOALS),clean)
+ifneq ($(MAKECMDGOALS),uninstall)
+include deps
+endif
+endif
+
+deps: $(SRCS)
+ @>deps ;\
+ for file in $(SRCS); do\
+ echo "`$(CC) $(CXXFLAGS) $(DEFS) $(SEARCH_DIRS) -MM $$file` Makefile" >> deps ;\
+ echo -e '\t$$(CC) -c $$< $(CXXFLAGS) $(SEARCH_DIRS) $(DEFS)' >> deps ;\
+ done
+
+
--- /dev/null
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include "xrconfig.h"
+#include "../../../tariff2.h"
+#include "../../../admins.h"
+#include "../../../users.h"
+
+class XR_CONFIG_CREATOR
+{
+private:
+ XR_CONFIG * xrconfig;
+
+public:
+ XR_CONFIG_CREATOR()
+ : xrconfig(new XR_CONFIG())
+ {
+ };
+ ~XR_CONFIG_CREATOR()
+ {
+ delete xrconfig;
+ };
+
+ XR_CONFIG * GetPlugin()
+ {
+ return xrconfig;
+ };
+};
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+XRCONFIG_CREATOR xrc;
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+XR_CONFIG_SETTINGS::XR_CONFIG_SETTINGS()
+ : port(0)
+{
+}
+//-----------------------------------------------------------------------------
+const string & XR_CONFIG_SETTINGS::GetStrError() const
+{
+return errorStr;
+}
+//-----------------------------------------------------------------------------
+int XR_CONFIG_SETTINGS::ParseIntInRange(const string & str, int min, int max, int * val)
+{
+if (strtoi2(str.c_str(), *val))
+ {
+ errorStr = "Incorrect value \'" + str + "\'.";
+ return -1;
+ }
+if (*val < min || *val > max)
+ {
+ errorStr = "Value \'" + str + "\' out of range.";
+ return -1;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int XR_CONFIG_SETTINGS::ParseSettings(const MODULE_SETTINGS & s)
+{
+/*int p;
+PARAM_VALUE pv;
+vector<PARAM_VALUE>::const_iterator pvi;
+
+pv.param = "Port";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end())
+ {
+ errorStr = "Parameter \'Port\' not found.";
+ return -1;
+ }
+
+if (ParseIntInRange(pvi->value[0], 2, 65535, &p))
+ {
+ errorStr = "Cannot parse parameter \'Port\': " + errorStr;
+ return -1;
+ }
+port = p;*/
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+uint16_t XR_CONFIG_SETTINGS::GetPort()
+{
+return port;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+BASE_PLUGIN * GetPlugin()
+{
+return xrc.GetPlugin();
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+const string XR_CONFIG::GetVersion() const
+{
+return "XR_configurator v.0.01";
+}
+//-----------------------------------------------------------------------------
+XR_CONFIG::XR_CONFIG()
+{
+isRunning = false;
+nonstop = false;
+}
+//-----------------------------------------------------------------------------
+void XR_CONFIG::SetUsers(USERS * u)
+{
+users = u;
+}
+//-----------------------------------------------------------------------------
+void XR_CONFIG::SetTariffs(TARIFFS * t)
+{
+tariffs = t;
+}
+//-----------------------------------------------------------------------------
+void XR_CONFIG::SetAdmins(ADMINS * a)
+{
+admins = a;
+}
+//-----------------------------------------------------------------------------
+void XR_CONFIG::SetStore(BASE_STORE * s)
+{
+store = s;
+}
+//-----------------------------------------------------------------------------
+void XR_CONFIG::SetStgSettings(const SETTINGS * s)
+{
+stgSettings = s;
+}
+//-----------------------------------------------------------------------------
+void XR_CONFIG::SetSettings(const MODULE_SETTINGS & s)
+{
+settings = s;
+}
+//-----------------------------------------------------------------------------
+int XR_CONFIG::ParseSettings()
+{
+int ret = xrConfigSettings.ParseSettings(settings);
+if (ret)
+ errorStr = xrConfigSettings.GetStrError();
+return ret;
+}
+//-----------------------------------------------------------------------------
+const string & XR_CONFIG::GetStrError() const
+{
+return errorStr;
+}
+//-----------------------------------------------------------------------------
+int XR_CONFIG::Start()
+{
+if (isRunning)
+ return 0;
+
+nonstop = true;
+
+config.SetPort(xrConfigSettings.GetPort());
+config.SetAdmins(admins);
+config.SetUsers(users);
+config.SetTariffs(tariffs);
+config.SetStgSettings(stgSettings);
+config.SetStore(store);
+
+if (config.Prepare())
+ {
+ errorStr = config.GetStrError();
+ return -1;
+ }
+
+if (pthread_create(&thread, NULL, Run, this))
+ {
+ errorStr = "Cannot create thread.";
+ printfd(__FILE__, "Cannot create thread\n");
+ return -1;
+ }
+errorStr = "";
+return 0;
+}
+//-----------------------------------------------------------------------------
+int XR_CONFIG::Stop()
+{
+if (!isRunning)
+ return 0;
+
+config.Stop();
+
+//5 seconds to thread stops itself
+int i;
+for (i = 0; i < 25; i++)
+ {
+ if (!isRunning)
+ break;
+
+ stgUsleep(200000);
+ }
+
+//after 5 seconds waiting thread still running. now killing it
+if (isRunning)
+ {
+ //TODO pthread_cancel()
+ if (pthread_kill(thread, SIGINT))
+ {
+ errorStr = "Cannot kill thread.";
+ printfd(__FILE__, "Cannot kill thread\n");
+ return -1;
+ }
+ printfd(__FILE__, "XR_CONFIG killed\n");
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+bool XR_CONFIG::IsRunning()
+{
+return isRunning;
+}
+//-----------------------------------------------------------------------------
+void * XR_CONFIG::Run(void * d)
+{
+XR_CONFIG * stgConf = (XR_CONFIG *)d;
+stgConf->isRunning = true;
+
+stgConf->config.Run(&stgConf->config);
+
+stgConf->isRunning = false;
+return NULL;
+}
+//-----------------------------------------------------------------------------
+uint16_t XR_CONFIG::GetStartPosition() const
+{
+return 221;
+}
+//-----------------------------------------------------------------------------
+uint16_t XR_CONFIG::GetStopPosition() const
+{
+return 221;
+}
+//-----------------------------------------------------------------------------
+int XR_CONFIG::SetUserCash(const string & admLogin, const string & usrLogin, double cash) const
+{
+return 0;
+}
+//-----------------------------------------------------------------------------
+
--- /dev/null
+#include <string>
+#include <pthread.h>
+#include "base_plugin.h"
+//#include "common_settings.h"
+#include "common.h"
+//#include "configproto.h"
+
+using namespace std;
+
+extern "C" BASE_PLUGIN * GetPlugin();
+
+class STG_CONFIG;
+
+//-----------------------------------------------------------------------------
+class XR_CONFIG_SETTINGS
+{
+public:
+ XR_CONFIG_SETTINGS();
+ virtual ~XR_CONFIG_SETTINGS(){};
+ const string & GetStrError() const;
+ int ParseSettings(const MODULE_SETTINGS & s);
+ uint16_t GetPort();
+
+private:
+ int ParseIntInRange(const string & str, int min, int max, int * val);
+ string errorStr;
+ int port;
+};
+//-----------------------------------------------------------------------------
+class XR_CONFIG :public BASE_PLUGIN
+{
+public:
+ XR_CONFIG();
+ virtual ~XR_CONFIG(){};
+
+ void SetUsers(USERS * u);
+ void SetTariffs(TARIFFS * t);
+ void SetAdmins(ADMINS * a);
+ void SetStore(BASE_STORE * s);
+ void SetTraffcounter(TRAFFCOUNTER * tc){};
+ void SetStgSettings(const SETTINGS * s);
+ void SetSettings(const MODULE_SETTINGS & s);
+ int ParseSettings();
+
+ int Start();
+ int Stop();
+ int Reload() { return 0; };
+ bool IsRunning();
+
+ const string & GetStrError() const;
+ const string GetVersion() const;
+ uint16_t GetStartPosition() const;
+ uint16_t GetStopPosition() const;
+
+private:
+
+
+ int SetUserCash(const string & admLogin, const string & usrLogin, double cash) const;
+
+ static void * Run(void *);
+ mutable string errorStr;
+ XR_CONFIG_SETTINGS xrConfigSettings;
+ pthread_t thread;
+ bool nonstop;
+ bool isRunning;
+
+ //CONFIGPROTO config;
+
+ USERS * users;
+ ADMINS * admins;
+ TARIFFS * tariffs;
+ BASE_STORE * store;
+ MODULE_SETTINGS settings;
+ const SETTINGS * stgSettings;
+};
+//-----------------------------------------------------------------------------
+
+
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.11 2008/12/04 17:21:14 faust Exp $
+###############################################################################
+
+include ../../../../../Makefile.conf
+
+LIBS += $(LIB_THREAD)
+
+PROG = mod_ping.so
+
+SRCS = ./ping.cpp
+
+STGLIBS = -lstg_pinger -lstg_common
+
+include ../../Makefile.in
+
--- /dev/null
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include "ping.h"
+#include "../../../user.h"
+
+class PING_CREATOR
+{
+private:
+ PING * ping;
+
+public:
+ PING_CREATOR()
+ : ping(new PING())
+ {
+ };
+ ~PING_CREATOR()
+ {
+ delete ping;
+ };
+
+ PING * GetPlugin()
+ {
+ return ping;
+ };
+};
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+PING_CREATOR pc;
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// ëÌÁÓÓ ÄÌÑ ÐÏÉÓËÁ ÀÚÅÒÁ × ÓÐÉÓËÅ ÎÏÔÉÆÉËÁÔÏÒÏ×
+template <typename varType>
+class IS_CONTAINS_USER: public binary_function<varType, user_iter, bool>
+{
+public:
+ bool operator()(varType notifier, user_iter user) const
+ {
+ return notifier.GetUser() == user;
+ };
+};
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+BASE_PLUGIN * GetPlugin()
+{
+return pc.GetPlugin();
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+PING_SETTINGS::PING_SETTINGS()
+ : pingDelay(0),
+ errorStr()
+{
+}
+//-----------------------------------------------------------------------------
+int PING_SETTINGS::ParseSettings(const MODULE_SETTINGS & s)
+{
+PARAM_VALUE pv;
+vector<PARAM_VALUE>::const_iterator pvi;
+
+pv.param = "PingDelay";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end())
+ {
+ errorStr = "Parameter \'PingDelay\' not found.";
+ printfd(__FILE__, "Parameter 'PingDelay' not found\n");
+ return -1;
+ }
+if (ParseIntInRange(pvi->value[0], 5, 3600, &pingDelay))
+ {
+ errorStr = "Cannot parse parameter \'PingDelay\': " + errorStr;
+ printfd(__FILE__, "Canot parse parameter 'PingDelay'\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int PING_SETTINGS::ParseIntInRange(const string & str, int min, int max, int * val)
+{
+if (str2x(str.c_str(), *val))
+ {
+ errorStr = "Incorrect value \'" + str + "\'.";
+ return -1;
+ }
+if (*val < min || *val > max)
+ {
+ errorStr = "Value \'" + str + "\' out of range.";
+ return -1;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+PING::PING()
+{
+pthread_mutex_init(&mutex, NULL);
+isRunning = false;
+}
+//-----------------------------------------------------------------------------
+PING::~PING()
+{
+pthread_mutex_destroy(&mutex);
+}
+//-----------------------------------------------------------------------------
+const string PING::GetVersion() const
+{
+return "Pinger v.1.01";
+}
+//-----------------------------------------------------------------------------
+void PING::SetSettings(const MODULE_SETTINGS & s)
+{
+settings = s;
+}
+//-----------------------------------------------------------------------------
+int PING::ParseSettings()
+{
+int ret = pingSettings.ParseSettings(settings);
+if (ret)
+ errorStr = pingSettings.GetStrError();
+return ret;
+}
+//-----------------------------------------------------------------------------
+void PING::SetUsers(USERS * u)
+{
+users = u;
+}
+//-----------------------------------------------------------------------------
+const string & PING::GetStrError() const
+{
+return errorStr;
+}
+//-----------------------------------------------------------------------------
+int PING::Start()
+{
+GetUsers();
+
+onAddUserNotifier.SetPinger(this);
+onDelUserNotifier.SetPinger(this);
+users->AddNotifierUserAdd(&onAddUserNotifier);
+users->AddNotifierUserDel(&onDelUserNotifier);
+
+nonstop = true;
+
+pinger.SetDelayTime(pingSettings.GetPingDelay());
+pinger.Start();
+
+if (pthread_create(&thread, NULL, Run, this))
+ {
+ errorStr = "Cannot start thread.";
+ printfd(__FILE__, "Cannot start thread\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int PING::Stop()
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (!isRunning)
+ return 0;
+
+pinger.Stop();
+nonstop = false;
+//5 seconds to thread stops itself
+for (int i = 0; i < 25; i++)
+ {
+ if (!isRunning)
+ break;
+
+ usleep(200000);
+ }
+
+//after 5 seconds waiting thread still running. now kill it
+if (isRunning)
+ {
+ printfd(__FILE__, "kill PING thread.\n");
+ if (pthread_kill(thread, SIGINT))
+ {
+ errorStr = "Cannot kill PING thread.";
+ printfd(__FILE__, "Cannot kill PING thread.\n");
+ return -1;
+ }
+ printfd(__FILE__, "PING killed\n");
+ }
+
+users->DelNotifierUserAdd(&onAddUserNotifier);
+users->DelNotifierUserDel(&onDelUserNotifier);
+
+list<user_iter>::iterator users_iter;
+users_iter = usersList.begin();
+while (users_iter != usersList.end())
+ {
+ UnSetUserNotifiers(*users_iter);
+ users_iter++;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+bool PING::IsRunning()
+{
+return isRunning;
+}
+//-----------------------------------------------------------------------------
+void * PING::Run(void * d)
+{
+PING * ping = (PING*)d;
+ping->isRunning = true;
+list<user_iter>::iterator iter;
+uint32_t ip;
+time_t t;
+
+while (ping->nonstop)
+ {
+ iter = ping->usersList.begin();
+ {
+ STG_LOCKER lock(&ping->mutex, __FILE__, __LINE__);
+ while (iter != ping->usersList.end())
+ {
+ if ((*iter)->property.ips.ConstData().OnlyOneIP())
+ {
+ ip = (*iter)->property.ips.ConstData()[0].ip;
+ if (ping->pinger.GetIPTime(ip, &t) == 0)
+ {
+ if (t)
+ (*iter)->UpdatePingTime(t);
+ }
+ }
+ else
+ {
+ ip = (*iter)->GetCurrIP();
+ if (ip)
+ {
+ if (ping->pinger.GetIPTime(ip, &t) == 0)
+ {
+ if (t)
+ (*iter)->UpdatePingTime(t);
+ }
+ }
+ }
+ iter++;
+ }
+ }
+ for (int i = 0; i < 100; i++)
+ {
+ if (ping->nonstop)
+ {
+ usleep((10000*ping->pingSettings.GetPingDelay())/3 + 50000);
+ }
+ }
+ }
+ping->isRunning = false;
+return NULL;
+}
+//-----------------------------------------------------------------------------
+uint16_t PING::GetStartPosition() const
+{
+return 100;
+}
+//-----------------------------------------------------------------------------
+uint16_t PING::GetStopPosition() const
+{
+return 100;
+}
+//-----------------------------------------------------------------------------
+void PING::SetUserNotifiers(user_iter u)
+{
+CHG_CURRIP_NOTIFIER_PING ChgCurrIPNotifier;
+CHG_IPS_NOTIFIER_PING ChgIPNotifier;
+
+ChgCurrIPNotifier.SetPinger(this);
+ChgCurrIPNotifier.SetUser(u);
+ChgCurrIPNotifierList.push_front(ChgCurrIPNotifier);
+
+ChgIPNotifier.SetPinger(this);
+ChgIPNotifier.SetUser(u);
+ChgIPNotifierList.push_front(ChgIPNotifier);
+
+u->AddCurrIPAfterNotifier(&(*ChgCurrIPNotifierList.begin()));
+u->property.ips.AddAfterNotifier(&(*ChgIPNotifierList.begin()));
+}
+//-----------------------------------------------------------------------------
+void PING::UnSetUserNotifiers(user_iter u)
+{
+// --- CurrIP ---
+IS_CONTAINS_USER<CHG_CURRIP_NOTIFIER_PING> IsContainsUserCurrIP;
+IS_CONTAINS_USER<CHG_IPS_NOTIFIER_PING> IsContainsUserIP;
+
+list<CHG_CURRIP_NOTIFIER_PING>::iterator currIPter;
+list<CHG_IPS_NOTIFIER_PING>::iterator IPIter;
+
+currIPter = find_if(ChgCurrIPNotifierList.begin(),
+ ChgCurrIPNotifierList.end(),
+ bind2nd(IsContainsUserCurrIP, u));
+
+if (currIPter != ChgCurrIPNotifierList.end())
+ {
+ currIPter->GetUser()->DelCurrIPAfterNotifier(&(*currIPter));
+ ChgCurrIPNotifierList.erase(currIPter);
+ }
+// --- CurrIP end ---
+
+// --- IP ---
+IPIter = find_if(ChgIPNotifierList.begin(),
+ ChgIPNotifierList.end(),
+ bind2nd(IsContainsUserIP, u));
+
+if (IPIter != ChgIPNotifierList.end())
+ {
+ IPIter->GetUser()->property.ips.DelAfterNotifier(&(*IPIter));
+ ChgIPNotifierList.erase(IPIter);
+ }
+// --- IP end ---
+}
+//-----------------------------------------------------------------------------
+void PING::GetUsers()
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+user_iter u;
+int h = users->OpenSearch();
+if (!h)
+ {
+ printfd(__FILE__, "users->OpenSearch() error\n");
+ return;
+ }
+
+while (users->SearchNext(h, &u) == 0)
+ {
+ usersList.push_back(u);
+ SetUserNotifiers(u);
+ if (u->property.ips.ConstData().OnlyOneIP())
+ {
+ pinger.AddIP(u->property.ips.ConstData()[0].ip);
+ }
+ else
+ {
+ uint32_t ip = u->GetCurrIP();
+ if (ip)
+ {
+ pinger.AddIP(ip);
+ }
+ }
+ }
+
+users->CloseSearch(h);
+}
+//-----------------------------------------------------------------------------
+void PING::AddUser(user_iter u)
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+SetUserNotifiers(u);
+usersList.push_back(u);
+}
+//-----------------------------------------------------------------------------
+void PING::DelUser(user_iter u)
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+UnSetUserNotifiers(u);
+
+list<user_iter>::iterator users_iter;
+users_iter = usersList.begin();
+
+while (users_iter != usersList.end())
+ {
+ if (u == *users_iter)
+ {
+ usersList.erase(users_iter);
+ break;
+ }
+ users_iter++;
+ }
+}
+//-----------------------------------------------------------------------------
+void CHG_CURRIP_NOTIFIER_PING::Notify(const uint32_t & oldIP, const uint32_t & newIP)
+{
+ping->pinger.DelIP(oldIP);
+if (newIP)
+ {
+ ping->pinger.AddIP(newIP);
+ }
+}
+//-----------------------------------------------------------------------------
+void CHG_IPS_NOTIFIER_PING::Notify(const USER_IPS & oldIPS, const USER_IPS & newIPS)
+{
+if (oldIPS.OnlyOneIP())
+ {
+ ping->pinger.DelIP(oldIPS[0].ip);
+ }
+
+if (newIPS.OnlyOneIP())
+ {
+ ping->pinger.AddIP(newIPS[0].ip);
+ }
+}
+//-----------------------------------------------------------------------------
+void ADD_USER_NONIFIER_PING::Notify(const user_iter & user)
+{
+ping->AddUser(user);
+}
+//-----------------------------------------------------------------------------
+void DEL_USER_NONIFIER_PING::Notify(const user_iter & user)
+{
+ping->DelUser(user);
+}
+//-----------------------------------------------------------------------------
+
+
+
+
+
+
--- /dev/null
+ /*
+ $Revision: 1.16 $
+ $Date: 2009/06/23 11:32:28 $
+ $Author: faust $
+ */
+
+#ifndef PING_H
+#define PING_H
+
+#include <string>
+#include <pthread.h>
+
+#include "os_int.h"
+#include "base_plugin.h"
+#include "notifer.h"
+#include "user_ips.h"
+#include "pinger.h"
+#include "../../../users.h"
+
+using namespace std;
+
+extern "C" BASE_PLUGIN * GetPlugin();
+
+class PING;
+//-----------------------------------------------------------------------------*/
+class CHG_CURRIP_NOTIFIER_PING: public PROPERTY_NOTIFIER_BASE<uint32_t>
+{
+public:
+ void Notify(const uint32_t & oldIP, const uint32_t & newIP);
+ void SetUser(user_iter u) { user = u; }
+ user_iter GetUser() {return user; }
+ void SetPinger(const PING * p) { ping = p; }
+
+private:
+ user_iter user;
+ const PING * ping;
+};
+//-----------------------------------------------------------------------------
+class CHG_IPS_NOTIFIER_PING: public PROPERTY_NOTIFIER_BASE<USER_IPS>
+{
+public:
+ void Notify(const USER_IPS & oldIPS, const USER_IPS & newIPS);
+ void SetUser(user_iter u) { user = u; }
+ user_iter GetUser() {return user; }
+ void SetPinger(const PING * p) { ping = p; }
+
+private:
+ user_iter user;
+ const PING * ping;
+};
+//-----------------------------------------------------------------------------
+class ADD_USER_NONIFIER_PING: public NOTIFIER_BASE<user_iter>
+{
+public:
+ ADD_USER_NONIFIER_PING(){};
+ virtual ~ADD_USER_NONIFIER_PING(){};
+
+ void SetPinger(PING * p) { ping = p; }
+ void Notify(const user_iter & user);
+
+private:
+ PING * ping;
+};
+//-----------------------------------------------------------------------------
+class DEL_USER_NONIFIER_PING: public NOTIFIER_BASE<user_iter>
+{
+public:
+ DEL_USER_NONIFIER_PING(){};
+ virtual ~DEL_USER_NONIFIER_PING(){};
+
+ void SetPinger(PING * p) { ping = p; }
+ void Notify(const user_iter & user);
+
+private:
+ PING * ping;
+};
+//-----------------------------------------------------------------------------
+class PING_SETTINGS
+{
+public:
+ PING_SETTINGS();
+ virtual ~PING_SETTINGS(){};
+ const string& GetStrError() const { return errorStr; }
+ int ParseSettings(const MODULE_SETTINGS & s);
+ int GetPingDelay(){ return pingDelay; };
+private:
+ int ParseIntInRange(const string & str, int min, int max, int * val);
+ int pingDelay;
+ mutable string errorStr;
+};
+//-----------------------------------------------------------------------------
+class PING: public BASE_PLUGIN
+{
+friend class CHG_CURRIP_NOTIFIER_PING;
+friend class CHG_IPS_NOTIFIER_PING;
+public:
+ PING();
+ virtual ~PING();
+
+ void SetUsers(USERS * u);
+ void SetTariffs(TARIFFS *){};
+ void SetAdmins(ADMINS *){};
+ void SetTraffcounter(TRAFFCOUNTER *){};
+ void SetStore(BASE_STORE *){};
+ void SetStgSettings(const SETTINGS *){};
+ void SetSettings(const MODULE_SETTINGS & s);
+ int ParseSettings();
+
+ int Start();
+ int Stop();
+ int Reload() { return 0; };
+ bool IsRunning();
+
+ const string & GetStrError() const;
+ const string GetVersion() const;
+ uint16_t GetStartPosition() const;
+ uint16_t GetStopPosition() const;
+
+ void AddUser(user_iter u);
+ void DelUser(user_iter u);
+
+private:
+ void GetUsers();
+ void SetUserNotifiers(user_iter u);
+ void UnSetUserNotifiers(user_iter u);
+ static void * Run(void * d);
+ mutable string errorStr;
+ PING_SETTINGS pingSettings;
+ MODULE_SETTINGS settings;
+ USERS * users;
+ list<user_iter> usersList;
+
+ /*
+ ÍÙ ÄÏÌÖÎÙ ÐÅÒÅÐÒÏ×ÅÒÉÔØ ×ÏÚÍÏÖÎÏÓÔØ ÐÉÎÇÏ×ÁÎÉÑ ÀÚÅÒÁ ÐÒÉ ÉÚÍÅÎÅÎÉÉ
+ ÓÌÅÄÕÀÝÉÈ ÅÇÏ ÐÁÒÁÍÅÔÒÏ×:
+ - currIP
+ - ips
+ */
+ pthread_t thread;
+ pthread_mutex_t mutex;
+ bool nonstop;
+ bool isRunning;
+ mutable STG_PINGER pinger;
+
+ list<CHG_CURRIP_NOTIFIER_PING> ChgCurrIPNotifierList;
+ list<CHG_IPS_NOTIFIER_PING> ChgIPNotifierList;
+
+ ADD_USER_NONIFIER_PING onAddUserNotifier;
+ DEL_USER_NONIFIER_PING onDelUserNotifier;
+};
+//-----------------------------------------------------------------------------
+
+#endif
+
+
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.3 2010/04/26 12:44:42 faust Exp $
+###############################################################################
+
+include ../../../../../Makefile.conf
+
+LIBS += $(LIB_THREAD)
+
+PROG = mod_radius.so
+
+SRCS = ./radius.cpp
+
+STGLIBS = -lstg_common -lstg_crypto
+
+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>
+ */
+
+/*
+ * This file contains a realization of radius data access plugin for Stargazer
+ *
+ * $Revision: 1.14 $
+ * $Date: 2009/12/13 14:17:13 $
+ *
+ */
+
+#include <algorithm>
+#include <signal.h>
+
+#include "radius.h"
+#include "common.h"
+
+extern volatile const time_t stgTime;
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+class RAD_CREATOR
+{
+private:
+ RADIUS * rad;
+
+public:
+ RAD_CREATOR()
+ : rad(new RADIUS())
+ {
+ };
+ ~RAD_CREATOR()
+ {
+ delete rad;
+ };
+
+ RADIUS * GetPlugin()
+ {
+ return rad;
+ };
+};
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+RAD_CREATOR radc;
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+BASE_PLUGIN * GetPlugin()
+{
+return radc.GetPlugin();
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+uint16_t RAD_SETTINGS::GetPort() const
+{
+return port;
+}
+//-----------------------------------------------------------------------------
+uint32_t RAD_SETTINGS::GetServerIP() const
+{
+return serverIP;
+}
+//-----------------------------------------------------------------------------
+int RAD_SETTINGS::GetPassword(string * password) const
+{
+*password = RAD_SETTINGS::password;
+return 0;
+}
+//-----------------------------------------------------------------------------
+int RAD_SETTINGS::GetAuthServices(list<string> * svcs) const
+{
+*svcs = authServices;
+return 0;
+}
+//-----------------------------------------------------------------------------
+int RAD_SETTINGS::GetAcctServices(list<string> * svcs) const
+{
+*svcs = acctServices;
+return 0;
+}
+//-----------------------------------------------------------------------------
+int RAD_SETTINGS::ParseIP(const string & str, uint32_t * IP)
+{
+*IP = inet_addr(str.c_str());
+return *IP == INADDR_NONE ? -1 : 0;
+}
+//-----------------------------------------------------------------------------
+int RAD_SETTINGS::ParseIntInRange(const string & str, int min, int max, int * val)
+{
+if (str2x(str.c_str(), *val))
+ {
+ errorStr = "Incorrect value \'" + str + "\'.";
+ return -1;
+ }
+if (*val < min || *val > max)
+ {
+ errorStr = "Value \'" + str + "\' out of range.";
+ return -1;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int RAD_SETTINGS::ParseServices(const vector<string> & str, list<string> * lst)
+{
+ copy(str.begin(), str.end(), back_inserter(*lst));
+ list<string>::iterator it(find(lst->begin(),
+ lst->end(),
+ "empty"));
+ if (it != lst->end())
+ *it = "";
+
+ return 0;
+}
+//-----------------------------------------------------------------------------
+int RAD_SETTINGS::ParseSettings(const MODULE_SETTINGS & s)
+{
+int p;
+PARAM_VALUE pv;
+vector<PARAM_VALUE>::const_iterator pvi;
+///////////////////////////
+pv.param = "Port";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end())
+ {
+ errorStr = "Parameter \'Port\' not found.";
+ printfd(__FILE__, "Parameter 'Port' not found\n");
+ return -1;
+ }
+if (ParseIntInRange(pvi->value[0], 2, 65535, &p))
+ {
+ errorStr = "Cannot parse parameter \'Port\': " + errorStr;
+ printfd(__FILE__, "Cannot parse parameter 'Port'\n");
+ return -1;
+ }
+port = p;
+///////////////////////////
+pv.param = "ServerIP";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end())
+ {
+ serverIP = 0;
+ }
+else
+ {
+ if (ParseIP(pvi->value[0], &serverIP))
+ {
+ serverIP = 0;
+ }
+ }
+///////////////////////////
+pv.param = "Password";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end())
+ {
+ errorStr = "Parameter \'Password\' not found.";
+ printfd(__FILE__, "Parameter 'Password' not found\n");
+ return -1;
+ }
+password = pvi->value[0];
+///////////////////////////
+pv.param = "AuthServices";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi != s.moduleParams.end())
+ {
+ ParseServices(pvi->value, &authServices);
+ }
+///////////////////////////
+pv.param = "AcctServices";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi != s.moduleParams.end())
+ {
+ ParseServices(pvi->value, &acctServices);
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+RADIUS::RADIUS()
+{
+isRunning = false;
+}
+//-----------------------------------------------------------------------------
+void RADIUS::SetUsers(USERS * u)
+{
+users = u;
+}
+//-----------------------------------------------------------------------------
+void RADIUS::SetStgSettings(const SETTINGS * s)
+{
+stgSettings = s;
+}
+//-----------------------------------------------------------------------------
+void RADIUS::SetSettings(const MODULE_SETTINGS & s)
+{
+settings = s;
+}
+//-----------------------------------------------------------------------------
+void RADIUS::SetStore(BASE_STORE * s)
+{
+store = s;
+}
+//-----------------------------------------------------------------------------
+int RADIUS::ParseSettings()
+{
+int ret = radSettings.ParseSettings(settings);
+if (ret)
+ errorStr = radSettings.GetStrError();
+return ret;
+}
+//-----------------------------------------------------------------------------
+bool RADIUS::IsRunning()
+{
+return isRunning;
+}
+//-----------------------------------------------------------------------------
+const string RADIUS::GetVersion() const
+{
+return "RADIUS data access plugin v 0.6";
+}
+//-----------------------------------------------------------------------------
+uint16_t RADIUS::GetStartPosition() const
+{
+// Start before any authorizers!!!
+return 20;
+}
+//-----------------------------------------------------------------------------
+uint16_t RADIUS::GetStopPosition() const
+{
+return 20;
+}
+//-----------------------------------------------------------------------------
+void RADIUS::SetUserNotifier(user_iter)
+{
+}
+//-----------------------------------------------------------------------------
+void RADIUS::UnSetUserNotifier(user_iter)
+{
+}
+//-----------------------------------------------------------------------------
+int RADIUS::PrepareNet()
+{
+sock = socket(AF_INET, SOCK_DGRAM, 0);
+
+if (sock < 0)
+ {
+ errorStr = "Cannot create socket.";
+ printfd(__FILE__, "Cannot create socket\n");
+ return -1;
+ }
+
+inAddr.sin_family = AF_INET;
+inAddr.sin_port = htons(port);
+inAddr.sin_addr.s_addr = inet_addr("0.0.0.0");
+
+if (bind(sock, (struct sockaddr*)&inAddr, sizeof(inAddr)) < 0)
+ {
+ errorStr = "RADIUS: Bind failed.";
+ printfd(__FILE__, "Cannot bind socket\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int RADIUS::FinalizeNet()
+{
+close(sock);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int RADIUS::Start()
+{
+string password;
+
+radSettings.GetPassword(&password);
+port = radSettings.GetPort();
+serverIP = radSettings.GetServerIP();
+radSettings.GetAuthServices(&authServices);
+radSettings.GetAcctServices(&acctServices);
+
+InitEncrypt(&ctx, password);
+
+nonstop = true;
+
+if (PrepareNet())
+ {
+ return -1;
+ }
+
+if (!isRunning)
+ {
+ if (pthread_create(&thread, NULL, Run, this))
+ {
+ errorStr = "Cannot create thread.";
+ printfd(__FILE__, "Cannot create thread\n");
+ return -1;
+ }
+ }
+
+errorStr = "";
+return 0;
+}
+//-----------------------------------------------------------------------------
+int RADIUS::Stop()
+{
+if (!IsRunning())
+ return 0;
+
+nonstop = false;
+
+map<string, RAD_SESSION>::iterator it;
+for (it = sessions.begin(); it != sessions.end(); ++it)
+ {
+ user_iter ui;
+ if (users->FindByName(it->second.userName, &ui))
+ {
+ ui->Unauthorize(this);
+ }
+ }
+sessions.erase(sessions.begin(), sessions.end());
+
+FinalizeNet();
+
+if (isRunning)
+ {
+ //5 seconds to thread stops itself
+ for (int i = 0; i < 25 && isRunning; i++)
+ {
+ usleep(200000);
+ }
+
+ //after 5 seconds waiting thread still running. now killing it
+ if (isRunning)
+ {
+ if (pthread_kill(thread, SIGINT))
+ {
+ errorStr = "Cannot kill thread.";
+ printfd(__FILE__, "Cannot kill thread\n");
+ return -1;
+ }
+ printfd(__FILE__, "RADIUS::Stop killed Run\n");
+ }
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+void * RADIUS::Run(void * d)
+{
+RADIUS * rad = (RADIUS *)d;
+RAD_PACKET packet;
+
+rad->isRunning = true;
+
+while (rad->nonstop)
+ {
+ if (!rad->WaitPackets(rad->sock))
+ {
+ continue;
+ }
+ if (rad->RecvData(&packet))
+ {
+ printfd(__FILE__, "RADIUS::Run Error on RecvData\n");
+ }
+ else
+ {
+ if (rad->ProcessData(&packet))
+ {
+ packet.packetType = RAD_REJECT_PACKET;
+ }
+ rad->Send(packet);
+ }
+ }
+
+rad->isRunning = false;
+
+return NULL;
+}
+//-----------------------------------------------------------------------------
+int RADIUS::RecvData(RAD_PACKET * packet)
+{
+ int8_t buf[RAD_MAX_PACKET_LEN];
+ outerAddrLen = sizeof(struct sockaddr_in);
+ int dataLen = recvfrom(sock, buf, RAD_MAX_PACKET_LEN, 0, (struct sockaddr *)&outerAddr, &outerAddrLen);
+ if (dataLen > 0) {
+ Decrypt(&ctx, (char *)packet, (const char *)buf, dataLen / 8);
+ }
+ if (strncmp((char *)packet->magic, RAD_ID, RAD_MAGIC_LEN))
+ {
+ printfd(__FILE__, "RADIUS::RecvData Error magic. Wanted: '%s', got: '%s'\n", RAD_ID, packet->magic);
+ return -1;
+ }
+ return 0;
+}
+//-----------------------------------------------------------------------------
+int RADIUS::Send(const RAD_PACKET & packet)
+{
+int res, len = sizeof(RAD_PACKET);
+char buf[1032];
+
+Encrypt(&ctx, buf, (char *)&packet, len / 8);
+res = sendto(sock, buf, len, 0, (struct sockaddr *)&outerAddr, outerAddrLen);
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int RADIUS::ProcessData(RAD_PACKET * packet)
+{
+//struct in_addr addr = {packet->ip};
+if (strncmp((const char *)packet->protoVer, "01", 2))
+ {
+ printfd(__FILE__, "RADIUS::ProcessData packet.protoVer incorrect\n");
+ return -1;
+ }
+switch (packet->packetType)
+ {
+ case RAD_AUTZ_PACKET:
+ return ProcessAutzPacket(packet);
+ case RAD_AUTH_PACKET:
+ return ProcessAuthPacket(packet);
+ case RAD_POST_AUTH_PACKET:
+ return ProcessPostAuthPacket(packet);
+ case RAD_ACCT_START_PACKET:
+ return ProcessAcctStartPacket(packet);
+ case RAD_ACCT_STOP_PACKET:
+ return ProcessAcctStopPacket(packet);
+ case RAD_ACCT_UPDATE_PACKET:
+ return ProcessAcctUpdatePacket(packet);
+ case RAD_ACCT_OTHER_PACKET:
+ return ProcessAcctOtherPacket(packet);
+ default:
+ printfd(__FILE__, "RADIUS::ProcessData Unsupported packet type: %d\n", packet->packetType);
+ return -1;
+ };
+return 0;
+}
+//-----------------------------------------------------------------------------
+int RADIUS::ProcessAutzPacket(RAD_PACKET * packet)
+{
+USER_CONF conf;
+
+if (!IsAllowedService((char *)packet->service))
+ {
+ printfd(__FILE__, "RADIUS::ProcessAutzPacket service '%s' is not allowed to authorize\n", packet->service);
+ packet->packetType = RAD_REJECT_PACKET;
+ return 0;
+ }
+
+if (store->RestoreUserConf(&conf, (char *)packet->login))
+ {
+ packet->packetType = RAD_REJECT_PACKET;
+ printfd(__FILE__, "RADIUS::ProcessAutzPacket cannot restore conf for user '%s'\n", packet->login);
+ return 0;
+ }
+
+// At this point service can be authorized at least
+// So we send a plain-text password
+
+packet->packetType = RAD_ACCEPT_PACKET;
+strncpy((char *)packet->password, conf.password.c_str(), RAD_PASSWORD_LEN);
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int RADIUS::ProcessAuthPacket(RAD_PACKET * packet)
+{
+user_iter ui;
+
+if (!CanAcctService((char *)packet->service))
+ {
+
+ // There are no sense to check for allowed service
+ // It has allready checked at previous stage (authorization)
+
+ printfd(__FILE__, "RADIUS::ProcessAuthPacket service '%s' neednot stargazer authentication\n", (char *)packet->service);
+ packet->packetType = RAD_ACCEPT_PACKET;
+ return 0;
+ }
+
+// At this point we have an accountable service
+// All other services got a password if allowed or rejected
+
+if (!FindUser(&ui, (char *)packet->login))
+ {
+ packet->packetType = RAD_REJECT_PACKET;
+ printfd(__FILE__, "RADIUS::ProcessAuthPacket user '%s' not found\n", (char *)packet->login);
+ return 0;
+ }
+
+if (ui->IsInetable())
+ {
+ packet->packetType = RAD_ACCEPT_PACKET;
+ }
+else
+ {
+ packet->packetType = RAD_REJECT_PACKET;
+ }
+
+packet->packetType = RAD_ACCEPT_PACKET;
+return 0;
+}
+//-----------------------------------------------------------------------------
+int RADIUS::ProcessPostAuthPacket(RAD_PACKET * packet)
+{
+user_iter ui;
+
+if (!CanAcctService((char *)packet->service))
+ {
+
+ // There are no sense to check for allowed service
+ // It has allready checked at previous stage (authorization)
+
+ packet->packetType = RAD_ACCEPT_PACKET;
+ return 0;
+ }
+
+if (!FindUser(&ui, (char *)packet->login))
+ {
+ packet->packetType = RAD_REJECT_PACKET;
+ printfd(__FILE__, "RADIUS::ProcessPostAuthPacket user '%s' not found\n", (char *)packet->login);
+ return 0;
+ }
+
+// I think that only Framed-User services has sense to be accountable
+// So we have to supply a Framed-IP
+
+USER_IPS ips = ui->property.ips;
+packet->packetType = RAD_ACCEPT_PACKET;
+
+// Additional checking for Framed-User service
+
+if (!strncmp((char *)packet->service, "Framed-User", RAD_SERVICE_LEN))
+ packet->ip = ips[0].ip;
+else
+ packet->ip = 0;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int RADIUS::ProcessAcctStartPacket(RAD_PACKET * packet)
+{
+user_iter ui;
+
+if (!FindUser(&ui, (char *)packet->login))
+ {
+ packet->packetType = RAD_REJECT_PACKET;
+ printfd(__FILE__, "RADIUS::ProcessAcctStartPacket user '%s' not found\n", (char *)packet->login);
+ return 0;
+ }
+
+// At this point we have to unauthorize user only if it is an accountable service
+
+if (CanAcctService((char *)packet->service))
+ {
+ if (sessions.find((const char *)packet->sessid) != sessions.end())
+ {
+ printfd(__FILE__, "RADIUS::ProcessAcctStartPacket session already started!\n");
+ packet->packetType = RAD_REJECT_PACKET;
+ return -1;
+ }
+ USER_IPS ips = ui->property.ips;
+ if (ui->Authorize(ips[0].ip, "", 0xffFFffFF, this))
+ {
+ printfd(__FILE__, "RADIUS::ProcessAcctStartPacket cannot authorize user '%s'\n", packet->login);
+ packet->packetType = RAD_REJECT_PACKET;
+ return -1;
+ }
+ sessions[(const char *)packet->sessid].userName = (const char *)packet->login;
+ sessions[(const char *)packet->sessid].serviceType = (const char *)packet->service;
+ for_each(sessions.begin(), sessions.end(), SPrinter());
+ }
+else
+ {
+ printfd(__FILE__, "RADIUS::ProcessAcctStartPacket service '%s' can not be accounted\n", (char *)packet->service);
+ }
+
+packet->packetType = RAD_ACCEPT_PACKET;
+return 0;
+}
+//-----------------------------------------------------------------------------
+int RADIUS::ProcessAcctStopPacket(RAD_PACKET * packet)
+{
+map<string, RAD_SESSION>::iterator sid;
+
+if ((sid = sessions.find((const char *)packet->sessid)) == sessions.end())
+ {
+ printfd(__FILE__, "RADIUS::ProcessAcctStopPacket session had not started yet\n");
+ packet->packetType = RAD_REJECT_PACKET;
+ return -1;
+ }
+
+user_iter ui;
+
+if (!FindUser(&ui, sid->second.userName))
+ {
+ packet->packetType = RAD_REJECT_PACKET;
+ printfd(__FILE__, "RADIUS::ProcessPostAuthPacket user '%s' not found\n", sid->second.userName.c_str());
+ return 0;
+ }
+
+sessions.erase(sid);
+
+ui->Unauthorize(this);
+
+packet->packetType = RAD_ACCEPT_PACKET;
+return 0;
+}
+//-----------------------------------------------------------------------------
+int RADIUS::ProcessAcctUpdatePacket(RAD_PACKET * packet)
+{
+// Fake. May be used later
+packet->packetType = RAD_ACCEPT_PACKET;
+return 0;
+}
+//-----------------------------------------------------------------------------
+int RADIUS::ProcessAcctOtherPacket(RAD_PACKET * packet)
+{
+// Fake. May be used later
+packet->packetType = RAD_ACCEPT_PACKET;
+return 0;
+}
+//-----------------------------------------------------------------------------
+void RADIUS::InitEncrypt(BLOWFISH_CTX * ctx, const string & password)
+{
+unsigned char keyL[RAD_PASSWORD_LEN]; // Пароль для шифровки
+memset(keyL, 0, RAD_PASSWORD_LEN);
+strncpy((char *)keyL, password.c_str(), RAD_PASSWORD_LEN);
+Blowfish_Init(ctx, keyL, RAD_PASSWORD_LEN);
+}
+//-----------------------------------------------------------------------------
+void RADIUS::Encrypt(BLOWFISH_CTX * ctx, char * dst, const char * src, int len8)
+{
+// len8 - длина в 8-ми байтовых блоках
+if (dst != src)
+ memcpy(dst, src, len8 * 8);
+
+for (int i = 0; i < len8; i++)
+ Blowfish_Encrypt(ctx, (uint32_t *)(dst + i*8), (uint32_t *)(dst + i*8 + 4));
+}
+//-----------------------------------------------------------------------------
+void RADIUS::Decrypt(BLOWFISH_CTX * ctx, char * dst, const char * src, int len8)
+{
+// len8 - длина в 8-ми байтовых блоках
+if (dst != src)
+ memcpy(dst, src, len8 * 8);
+
+for (int i = 0; i < len8; i++)
+ Blowfish_Decrypt(ctx, (uint32_t *)(dst + i*8), (uint32_t *)(dst + i*8 + 4));
+}
+//-----------------------------------------------------------------------------
+void RADIUS::PrintServices(const list<string> & svcs)
+{
+ for_each(svcs.begin(), svcs.end(), Printer());
+}
+//-----------------------------------------------------------------------------
+bool RADIUS::FindUser(user_iter * ui, const std::string & login) const
+{
+if (users->FindByName(login, ui))
+ {
+ return false;
+ }
+return true;
+}
+//-----------------------------------------------------------------------------
+bool RADIUS::CanAuthService(const std::string & svc) const
+{
+ return find(authServices.begin(), authServices.end(), svc) != authServices.end();
+}
+//-----------------------------------------------------------------------------
+bool RADIUS::CanAcctService(const std::string & svc) const
+{
+ return find(acctServices.begin(), acctServices.end(), svc) != acctServices.end();
+}
+//-----------------------------------------------------------------------------
+bool RADIUS::IsAllowedService(const std::string & svc) const
+{
+ return CanAuthService(svc) || CanAcctService(svc);
+}
+//-----------------------------------------------------------------------------
+bool RADIUS::WaitPackets(int sd) const
+{
+fd_set rfds;
+FD_ZERO(&rfds);
+FD_SET(sd, &rfds);
+
+struct timeval tv;
+tv.tv_sec = 0;
+tv.tv_usec = 500000;
+
+int res = select(sd + 1, &rfds, NULL, NULL, &tv);
+if (res == -1) // Error
+ {
+ if (errno != EINTR)
+ {
+ printfd(__FILE__, "Error on select: '%s'\n", strerror(errno));
+ }
+ return false;
+ }
+
+if (res == 0) // Timeout
+ {
+ return false;
+ }
+
+return true;
+}
--- /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>
+ */
+
+/*
+ * Radius data access plugin for Stargazer
+ *
+ * $Revision: 1.10 $
+ * $Date: 2009/12/13 14:17:13 $
+ *
+ */
+
+#ifndef RADIUS_H
+#define RADIUS_H
+
+#include <string>
+#include <list>
+#include <pthread.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "os_int.h"
+#include "base_auth.h"
+#include "notifer.h"
+#include "user_ips.h"
+#include "../../../user.h"
+#include "../../../users.h"
+#include "blowfish.h"
+#include "rad_packets.h"
+
+using namespace std;
+
+extern "C" BASE_PLUGIN * GetPlugin();
+
+#define RAD_DEBUG (1)
+
+class RADIUS;
+//-----------------------------------------------------------------------------
+class RAD_SETTINGS
+{
+public:
+ virtual ~RAD_SETTINGS(){};
+ const string& GetStrError() const { return errorStr; };
+ int ParseSettings(const MODULE_SETTINGS & s);
+ uint16_t GetPort() const;
+ uint32_t GetServerIP() const;
+ int GetPassword(string * password) const;
+ int GetAuthServices(list<string> * svcs) const;
+ int GetAcctServices(list<string> * svcs) const;
+
+private:
+ int ParseIntInRange(const string & str, int min, int max, int * val);
+ int ParseIP(const string & str, uint32_t * routerIP);
+ int ParseServices(const vector<string> & str, list<string> * lst);
+
+ uint16_t port;
+ string errorStr;
+ string password;
+ uint32_t serverIP;
+ list<string> authServices;
+ list<string> acctServices;
+};
+//-----------------------------------------------------------------------------
+struct RAD_SESSION {
+ std::string userName;
+ std::string serviceType;
+};
+//-----------------------------------------------------------------------------
+class RADIUS :public BASE_AUTH
+{
+public:
+ RADIUS();
+ virtual ~RADIUS(){};
+
+ void SetUsers(USERS * u);
+ void SetTariffs(TARIFFS *){};
+ void SetAdmins(ADMINS *){};
+ void SetTraffcounter(TRAFFCOUNTER *){};
+ void SetStore(BASE_STORE * );
+ void SetStgSettings(const SETTINGS * s);
+ void SetSettings(const MODULE_SETTINGS & s);
+ int ParseSettings();
+
+ int Start();
+ int Stop();
+ int Reload() { return 0; };
+ bool IsRunning();
+
+ const string & GetStrError() const { return errorStr; };
+ const string GetVersion() const;
+ uint16_t GetStartPosition() const;
+ uint16_t GetStopPosition() const;
+
+ int SendMessage(const STG_MSG &, uint32_t) const { return 0; };
+
+private:
+ static void * Run(void *);
+ int PrepareNet();
+ int FinalizeNet();
+
+ void InitEncrypt(BLOWFISH_CTX * ctx, const string & password);
+ void Decrypt(BLOWFISH_CTX * ctx, char * dst, const char * src, int len8);
+ void Encrypt(BLOWFISH_CTX * ctx, char * dst, const char * src, int len8);
+
+ int Send(const RAD_PACKET & packet);
+ int RecvData(RAD_PACKET * packet);
+ int ProcessData(RAD_PACKET * packet);
+
+ int ProcessAutzPacket(RAD_PACKET * packet);
+ int ProcessAuthPacket(RAD_PACKET * packet);
+ int ProcessPostAuthPacket(RAD_PACKET * packet);
+ int ProcessAcctStartPacket(RAD_PACKET * packet);
+ int ProcessAcctStopPacket(RAD_PACKET * packet);
+ int ProcessAcctUpdatePacket(RAD_PACKET * packet);
+ int ProcessAcctOtherPacket(RAD_PACKET * packet);
+
+ bool FindUser(user_iter * ui, const std::string & login) const;
+ bool CanAuthService(const std::string & svc) const;
+ bool CanAcctService(const std::string & svc) const;
+ bool IsAllowedService(const std::string & svc) const;
+
+ void SetUserNotifier(user_iter u);
+ void UnSetUserNotifier(user_iter u);
+
+ bool WaitPackets(int sd) const;
+
+ void PrintServices(const std::list<std::string> & svcs);
+
+ struct Printer : public unary_function<std::string, void>
+ {
+ void operator()(const std::string & line)
+ {
+ printfd("radius.cpp", "'%s'\n", line.c_str());
+ };
+ };
+ struct SPrinter : public unary_function<std::pair<std::string, RAD_SESSION>, void>
+ {
+ void operator()(const std::pair<std::string, RAD_SESSION> & it)
+ {
+ printfd("radius.cpp", "%s - ('%s', '%s')\n", it.first.c_str(), it.second.userName.c_str(), it.second.serviceType.c_str());
+ };
+ };
+
+ BLOWFISH_CTX ctx;
+
+ mutable string errorStr;
+ RAD_SETTINGS radSettings;
+ MODULE_SETTINGS settings;
+ list<string> authServices;
+ list<string> acctServices;
+ map<string, RAD_SESSION> sessions;
+
+ bool nonstop;
+
+ bool isRunning;
+
+ USERS * users;
+ const SETTINGS * stgSettings;
+ const BASE_STORE * store;
+
+ pthread_t thread;
+ pthread_mutex_t mutex;
+
+ int sock;
+ struct sockaddr_in inAddr;
+ socklen_t inAddrLen;
+ uint16_t port;
+ uint32_t serverIP;
+ struct sockaddr_in outerAddr;
+ socklen_t outerAddrLen;
+
+ RAD_PACKET packet;
+
+};
+//-----------------------------------------------------------------------------
+
+#endif
+
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.7 2010/02/16 11:41:00 faust Exp $
+###############################################################################
+
+include ../../../../../Makefile.conf
+
+LIBS += $(LIB_THREAD)
+
+PROG = mod_remote_script.so
+
+SRCS = ./rscript.cpp \
+ ./nrmap_parser.cpp
+
+STGLIBS = -lstg_common -lstg_crypto
+
+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>
+ */
+
+ /*
+ $Revision: 1.8 $
+ $Author: faust $
+ $Date: 2009/10/22 09:58:53 $
+ */
+
+#include <fstream>
+#include <cerrno>
+#include <cstring>
+#include <algorithm>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include "common.h"
+
+#include "nrmap_parser.h"
+
+NRMapParser::NRMapParser()
+{
+}
+
+NRMapParser::~NRMapParser()
+{
+}
+
+bool NRMapParser::ReadFile(const std::string & fileName)
+{
+std::ifstream source(fileName.c_str());
+
+if (!source)
+ {
+ errorStr = "Error opening file ";
+ errorStr += fileName;
+ printfd(__FILE__, "NRMapParser::ReadFile(): %s\n", errorStr.c_str());
+ return true;
+ }
+
+int lineNumber = 0;
+std::string line;
+std::vector<NET_ROUTER> _nrmap;
+
+while (getline(source, line))
+ {
+ ++lineNumber;
+ NET_ROUTER nr;
+
+ if (Trim(line) == "")
+ {
+ continue;
+ }
+
+ if (ParseLine(line, nr))
+ {
+ printfd(__FILE__, "NRMapParser::ReadFile(): Error parsing line %d: '%s'\n", lineNumber, errorStr.c_str());
+ return true;
+ }
+
+ _nrmap.push_back(nr);
+ }
+
+nrmap = _nrmap;
+
+return false;
+}
+
+bool NRMapParser::ParseLine(const std::string & line, NET_ROUTER & nr) const
+{
+// xxx.xxx.xxx.xxx/yy zzz.zzz.zzz.zzz
+size_t pos = line.find_first_of(" \t");
+
+if (pos == std::string::npos)
+ {
+ errorStr = "No space between subnet and router";
+ return true;
+ }
+
+std::string subnet(line.substr(0, pos)); // xxx.xxx.xxx.xxx/yy
+
+uint32_t ip;
+uint32_t mask;
+
+if (ParseNet(subnet, ip, mask))
+ {
+ return true;
+ }
+
+nr.subnetIP = ip;
+nr.subnetMask = mask;
+
+pos = line.find_first_not_of(" \t", pos);
+
+if (pos == std::string::npos)
+ {
+ errorStr = "No router address found";
+ return true;
+ }
+
+size_t pos2 = line.find_first_of(" \t", pos);
+
+std::string router(line.substr(pos, pos2 == std::string::npos ? line.length() - pos2 - 1 : pos2 - pos)); //zzz.zzz.zzz.zzz
+
+uint32_t routerIP;
+
+if (ParseRouter(router, routerIP))
+ {
+ return true;
+ }
+
+std::vector<uint32_t>::iterator it;
+
+it = std::lower_bound(
+ nr.routers.begin(),
+ nr.routers.end(),
+ routerIP
+ );
+nr.routers.insert(it, routerIP);
+
+//nr.routers.push_back(routerIP);
+
+while (pos2 != std::string::npos)
+ {
+ pos = line.find_first_not_of(" \t", pos2);
+
+ if (pos == std::string::npos)
+ {
+ return false;
+ }
+
+ pos2 = line.find_first_of(" \t", pos);
+
+ if (ParseRouter(line.substr(
+ pos,
+ pos2 == std::string::npos ? line.length() - pos2 - 1 : pos2 - pos),
+ routerIP))
+ {
+ return true;
+ }
+
+ it = std::lower_bound(
+ nr.routers.begin(),
+ nr.routers.end(),
+ routerIP
+ );
+ nr.routers.insert(it, routerIP);
+
+ //nr.routers.push_back(routerIP);
+
+ }
+
+return false;
+}
+
+bool NRMapParser::ParseNet(const std::string & line, uint32_t & ip, uint32_t & mask) const
+{
+// xxx.xxx.xxx.xxx/yy
+
+size_t pos = line.find_first_of('/');
+
+if (pos == std::string::npos)
+ {
+ errorStr = "Subnet is not in CIDR notation";
+ return true;
+ }
+
+int res = inet_pton(AF_INET, line.substr(0, pos).c_str(), &ip); //xxx.xxx.xxx.xxx
+
+if (res < 0)
+ {
+ errorStr = strerror(errno);
+ return true;
+ }
+else if (res == 0)
+ {
+ errorStr = "Invalid subnet address";
+ return true;
+ }
+
+if (str2x(line.substr(pos + 1, line.length() - pos - 1), mask)) //yy
+ {
+ errorStr = "Invalid subnet mask";
+ return true;
+ }
+if (mask > 32)
+ {
+ errorStr = "Subnet mask is out of range [0..32]";
+ return true;
+ }
+mask = htonl(0xffFFffFF << (32 - mask)); //bitmask
+
+return false;
+}
+
+bool NRMapParser::ParseRouter(const std::string & line, uint32_t & ip) const
+{
+int res = inet_pton(AF_INET, line.c_str(), &ip); //zzz.zzz.zzz.zzz
+
+if (res < 0)
+ {
+ errorStr = strerror(errno);
+ return true;
+ }
+else if (res == 0)
+ {
+ printfd(__FILE__, "NRMapParser::ParseRouter(): IP '%s' is invalid\n", line.c_str());
+ errorStr = "Invalid router address";
+ return true;
+ }
+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 : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+ /*
+ $Revision: 1.2 $
+ $Author: faust $
+ $Date: 2009/09/23 12:51:42 $
+ */
+
+#ifndef __NRMAP_PARSER_H__
+#define __NRMAP_PARSER_H__
+
+#include <string>
+#include <vector>
+#include "os_int.h"
+
+struct NET_ROUTER
+{
+uint32_t subnetIP;
+uint32_t subnetMask;
+std::vector<uint32_t> routers;
+};
+
+class NRMapParser {
+public:
+ NRMapParser();
+ ~NRMapParser();
+
+ bool ReadFile(const std::string & fileName);
+ const std::vector<NET_ROUTER> & GetMap() const { return nrmap; };
+ const std::string & GetErrorStr() const { return errorStr; };
+private:
+ std::vector<NET_ROUTER> nrmap;
+ mutable std::string errorStr;
+
+ bool ParseLine(const std::string & line, NET_ROUTER & nr) const;
+ bool ParseNet(const std::string & line, uint32_t & ip, uint32_t & mask) const;
+ bool ParseRouter(const std::string & line, uint32_t & ip) const;
+};
+
+#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 : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+/*
+ $Revision: 1.33 $
+ $Date: 2010/04/16 12:30:37 $
+ $Author: faust $
+*/
+
+#include <sys/time.h>
+
+#include <csignal>
+#include <cassert>
+#include <algorithm>
+
+#include "rscript.h"
+#include "common.h"
+#include "ur_functor.h"
+#include "send_functor.h"
+
+extern volatile const time_t stgTime;
+
+#define RS_MAX_ROUTERS (100)
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+class RS_CREATOR
+{
+private:
+ REMOTE_SCRIPT * rs;
+
+public:
+ RS_CREATOR()
+ : rs(new REMOTE_SCRIPT())
+ {
+ };
+ ~RS_CREATOR()
+ {
+ delete rs;
+ };
+
+ REMOTE_SCRIPT * GetPlugin()
+ {
+ return rs;
+ };
+};
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+RS_CREATOR rsc;
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+BASE_PLUGIN * GetPlugin()
+{
+return rsc.GetPlugin();
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+RS_USER::RS_USER()
+ : lastSentTime(0),
+ shortPacketsCount(0)
+{
+}
+//-----------------------------------------------------------------------------
+RS_USER::RS_USER(const std::vector<uint32_t> & r, user_iter it)
+ : lastSentTime(0),
+ user(it),
+ routers(r),
+ shortPacketsCount(0)
+{
+}
+//-----------------------------------------------------------------------------
+RS_SETTINGS::RS_SETTINGS()
+ : sendPeriod(0),
+ port(0)
+{
+}
+//-----------------------------------------------------------------------------
+int RS_SETTINGS::ParseIntInRange(const string & str, int min, int max, int * val)
+{
+if (str2x(str.c_str(), *val))
+ {
+ errorStr = "Incorrect value \'" + str + "\'.";
+ return -1;
+ }
+if (*val < min || *val > max)
+ {
+ errorStr = "Value \'" + str + "\' out of range.";
+ return -1;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int RS_SETTINGS::ParseSettings(const MODULE_SETTINGS & s)
+{
+int p;
+PARAM_VALUE pv;
+vector<PARAM_VALUE>::const_iterator pvi;
+netRouters.clear();
+///////////////////////////
+pv.param = "Port";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end())
+ {
+ errorStr = "Parameter \'Port\' not found.";
+ printfd(__FILE__, "Parameter 'Port' not found\n");
+ return -1;
+ }
+if (ParseIntInRange(pvi->value[0], 2, 65535, &p))
+ {
+ errorStr = "Cannot parse parameter \'Port\': " + errorStr;
+ printfd(__FILE__, "Cannot parse parameter 'Port'\n");
+ return -1;
+ }
+port = p;
+///////////////////////////
+pv.param = "SendPeriod";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end())
+ {
+ errorStr = "Parameter \'SendPeriod\' not found.";
+ printfd(__FILE__, "Parameter 'SendPeriod' not found\n");
+ return -1;
+ }
+
+if (ParseIntInRange(pvi->value[0], 5, 600, &sendPeriod))
+ {
+ errorStr = "Cannot parse parameter \'SendPeriod\': " + errorStr;
+ printfd(__FILE__, "Cannot parse parameter 'SendPeriod'\n");
+ return -1;
+ }
+///////////////////////////
+pv.param = "UserParams";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end())
+ {
+ errorStr = "Parameter \'UserParams\' not found.";
+ printfd(__FILE__, "Parameter 'UserParams' not found\n");
+ return -1;
+ }
+userParams = pvi->value;
+///////////////////////////
+pv.param = "Password";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end())
+ {
+ errorStr = "Parameter \'Password\' not found.";
+ printfd(__FILE__, "Parameter 'Password' not found\n");
+ return -1;
+ }
+password = pvi->value[0];
+///////////////////////////
+pv.param = "SubnetFile";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end())
+ {
+ errorStr = "Parameter \'SubnetFile\' not found.";
+ printfd(__FILE__, "Parameter 'SubnetFile' not found\n");
+ return -1;
+ }
+subnetFile = pvi->value[0];
+
+NRMapParser nrMapParser;
+
+if (nrMapParser.ReadFile(subnetFile))
+ {
+ errorStr = nrMapParser.GetErrorStr();
+ return -1;
+ }
+
+netRouters = nrMapParser.GetMap();
+
+if (netRouters.empty())
+ {
+ errorStr = "Parameter(s) \'Subnet*\' not found.";
+ printfd(__FILE__, "Parameter(s) 'Subnet*' not found\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+REMOTE_SCRIPT::REMOTE_SCRIPT()
+ : sendPeriod(15),
+ halfPeriod(8),
+ nonstop(false),
+ isRunning(false),
+ users(NULL),
+ sock(0)
+{
+pthread_mutex_init(&mutex, NULL);
+}
+//-----------------------------------------------------------------------------
+REMOTE_SCRIPT::~REMOTE_SCRIPT()
+{
+pthread_mutex_destroy(&mutex);
+}
+//-----------------------------------------------------------------------------
+void * REMOTE_SCRIPT::Run(void * d)
+{
+REMOTE_SCRIPT * rs = static_cast<REMOTE_SCRIPT *>(d);
+
+rs->isRunning = true;
+
+while (rs->nonstop)
+ {
+ rs->PeriodicSend();
+ sleep(2);
+ }
+
+rs->isRunning = false;
+return NULL;
+}
+//-----------------------------------------------------------------------------
+int REMOTE_SCRIPT::ParseSettings()
+{
+int ret = rsSettings.ParseSettings(settings);
+if (ret)
+ errorStr = rsSettings.GetStrError();
+
+sendPeriod = rsSettings.GetSendPeriod();
+halfPeriod = sendPeriod / 2;
+
+return ret;
+}
+//-----------------------------------------------------------------------------
+int REMOTE_SCRIPT::Start()
+{
+netRouters = rsSettings.GetSubnetsMap();
+
+InitEncrypt(&ctx, rsSettings.GetPassword());
+
+onAddUserNotifier.SetRemoteScript(this);
+onDelUserNotifier.SetRemoteScript(this);
+
+users->AddNotifierUserAdd(&onAddUserNotifier);
+users->AddNotifierUserDel(&onDelUserNotifier);
+
+nonstop = true;
+
+if (GetUsers())
+ {
+ return -1;
+ }
+
+if (PrepareNet())
+ {
+ return -1;
+ }
+
+if (!isRunning)
+ {
+ if (pthread_create(&thread, NULL, Run, this))
+ {
+ errorStr = "Cannot create thread.";
+ printfd(__FILE__, "Cannot create thread\n");
+ return -1;
+ }
+ }
+
+errorStr = "";
+return 0;
+}
+//-----------------------------------------------------------------------------
+int REMOTE_SCRIPT::Stop()
+{
+if (!IsRunning())
+ return 0;
+
+nonstop = false;
+
+std::for_each(
+ authorizedUsers.begin(),
+ authorizedUsers.end(),
+ DisconnectUser(*this)
+ );
+
+FinalizeNet();
+
+if (isRunning)
+ {
+ //5 seconds to thread stops itself
+ for (int i = 0; i < 25 && isRunning; i++)
+ {
+ usleep(200000);
+ }
+
+ //after 5 seconds waiting thread still running. now killing it
+ if (isRunning)
+ {
+ if (pthread_kill(thread, SIGINT))
+ {
+ errorStr = "Cannot kill thread.";
+ printfd(__FILE__, "Cannot kill thread\n");
+ return -1;
+ }
+ printfd(__FILE__, "REMOTE_SCRIPT killed Run\n");
+ }
+ }
+
+users->DelNotifierUserDel(&onDelUserNotifier);
+users->DelNotifierUserAdd(&onAddUserNotifier);
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int REMOTE_SCRIPT::Reload()
+{
+NRMapParser nrMapParser;
+
+if (nrMapParser.ReadFile(rsSettings.GetMapFileName()))
+ {
+ errorStr = nrMapParser.GetErrorStr();
+ return -1;
+ }
+
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+ printfd(__FILE__, "REMOTE_SCRIPT::Reload()\n");
+
+ netRouters = nrMapParser.GetMap();
+ }
+
+std::for_each(authorizedUsers.begin(),
+ authorizedUsers.end(),
+ UpdateRouter(*this));
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+bool REMOTE_SCRIPT::PrepareNet()
+{
+sock = socket(AF_INET, SOCK_DGRAM, 0);
+
+if (sock < 0)
+ {
+ errorStr = "Cannot create socket.";
+ printfd(__FILE__, "Cannot create socket\n");
+ return true;
+ }
+
+return false;
+}
+//-----------------------------------------------------------------------------
+bool REMOTE_SCRIPT::FinalizeNet()
+{
+close(sock);
+return false;
+}
+//-----------------------------------------------------------------------------
+void REMOTE_SCRIPT::PeriodicSend()
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+map<uint32_t, RS_USER>::iterator it(authorizedUsers.begin());
+while (it != authorizedUsers.end())
+ {
+ if (difftime(stgTime, it->second.lastSentTime) - (rand() % halfPeriod) > sendPeriod)
+ //if (stgTime - it->second.lastSentTime > sendPeriod)
+ {
+ Send(it->first, it->second);
+ }
+ ++it;
+ }
+}
+//-----------------------------------------------------------------------------
+bool REMOTE_SCRIPT::PreparePacket(char * buf, size_t bufSize, uint32_t ip, RS_USER & rsu, bool forceDisconnect) const
+{
+RS_PACKET_HEADER packetHead;
+
+memset(packetHead.padding, 0, sizeof(packetHead.padding));
+strcpy((char*)packetHead.magic, RS_ID);
+packetHead.protoVer[0] = '0';
+packetHead.protoVer[1] = '2';
+if (forceDisconnect)
+ {
+ packetHead.packetType = RS_DISCONNECT_PACKET;
+ }
+else
+ {
+ if (rsu.shortPacketsCount % MAX_SHORT_PCKT == 0)
+ {
+ //SendLong
+ packetHead.packetType = rsu.user->IsInetable() ? RS_CONNECT_PACKET : RS_DISCONNECT_PACKET;
+ }
+ else
+ {
+ //SendShort
+ packetHead.packetType = rsu.user->IsInetable() ? RS_ALIVE_PACKET : RS_DISCONNECT_PACKET;
+ }
+ }
+rsu.shortPacketsCount++;
+rsu.lastSentTime = stgTime;
+
+packetHead.ip = htonl(ip);
+packetHead.id = htonl(rsu.user->GetID());
+strncpy((char*)packetHead.login, rsu.user->GetLogin().c_str(), RS_LOGIN_LEN);
+packetHead.login[RS_LOGIN_LEN - 1] = 0;
+
+memcpy(buf, &packetHead, sizeof(packetHead));
+
+if (packetHead.packetType == RS_ALIVE_PACKET)
+ {
+ return false;
+ }
+
+RS_PACKET_TAIL packetTail;
+
+memset(packetTail.padding, 0, sizeof(packetTail.padding));
+strcpy((char*)packetTail.magic, RS_ID);
+vector<string>::const_iterator it;
+std::string params;
+for(it = rsSettings.GetUserParams().begin();
+ it != rsSettings.GetUserParams().end();
+ ++it)
+ {
+ std::string parameter(GetUserParam(rsu.user, *it));
+ if (params.length() + parameter.length() > RS_PARAMS_LEN - 1)
+ break;
+ params += parameter + " ";
+ }
+strncpy((char *)packetTail.params, params.c_str(), RS_PARAMS_LEN);
+packetTail.params[RS_PARAMS_LEN - 1] = 0;
+
+assert(sizeof(packetHead) + sizeof(packetTail) <= bufSize && "Insufficient buffer space");
+
+Encrypt(&ctx, buf + sizeof(packetHead), (char *)&packetTail, sizeof(packetTail) / 8);
+
+return false;
+}
+//-----------------------------------------------------------------------------
+bool REMOTE_SCRIPT::Send(uint32_t ip, RS_USER & rsu, bool forceDisconnect) const
+{
+char buffer[RS_MAX_PACKET_LEN];
+
+memset(buffer, 0, sizeof(buffer));
+
+if (PreparePacket(buffer, sizeof(buffer), ip, rsu, forceDisconnect))
+ {
+ printfd(__FILE__, "REMOTE_SCRIPT::Send() - Invalid packet length!\n");
+ return true;
+ }
+
+std::for_each(
+ rsu.routers.begin(),
+ rsu.routers.end(),
+ PacketSender(sock, buffer, sizeof(buffer), htons(rsSettings.GetPort()))
+ );
+
+return false;
+}
+//-----------------------------------------------------------------------------
+bool REMOTE_SCRIPT::SendDirect(uint32_t ip, RS_USER & rsu, uint32_t routerIP, bool forceDisconnect) const
+{
+char buffer[RS_MAX_PACKET_LEN];
+
+if (PreparePacket(buffer, sizeof(buffer), ip, rsu, forceDisconnect))
+ {
+ printfd(__FILE__, "REMOTE_SCRIPT::SendDirect() - Invalid packet length!\n");
+ return true;
+ }
+
+struct sockaddr_in sendAddr;
+
+sendAddr.sin_family = AF_INET;
+sendAddr.sin_port = htons(rsSettings.GetPort());
+sendAddr.sin_addr.s_addr = routerIP;
+
+int res = sendto(sock, buffer, sizeof(buffer), 0, (struct sockaddr *)&sendAddr, sizeof(sendAddr));
+
+return (res != sizeof(buffer));
+}
+//-----------------------------------------------------------------------------
+bool REMOTE_SCRIPT::GetUsers()
+{
+user_iter u;
+
+int h = users->OpenSearch();
+if (!h)
+ {
+ errorStr = "users->OpenSearch() error.";
+ printfd(__FILE__, "OpenSearch() error\n");
+ return true;
+ }
+
+while (!users->SearchNext(h, &u))
+ {
+ SetUserNotifier(u);
+ }
+
+users->CloseSearch(h);
+return false;
+}
+//-----------------------------------------------------------------------------
+void REMOTE_SCRIPT::ChangedIP(user_iter u, uint32_t oldIP, uint32_t newIP)
+{
+/*
+ * When ip changes process looks like:
+ * old => 0, 0 => new
+ *
+ */
+if (newIP)
+ {
+ RS_USER rsu(IP2Routers(newIP), u);
+ Send(newIP, rsu);
+
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ authorizedUsers[newIP] = rsu;
+ }
+else
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ const map<uint32_t, RS_USER>::iterator it(
+ authorizedUsers.find(oldIP)
+ );
+ if (it != authorizedUsers.end())
+ {
+ Send(oldIP, it->second, true);
+ authorizedUsers.erase(it);
+ }
+ }
+}
+//-----------------------------------------------------------------------------
+std::vector<uint32_t> REMOTE_SCRIPT::IP2Routers(uint32_t ip)
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+for (size_t i = 0; i < netRouters.size(); ++i)
+ {
+ if ((ip & netRouters[i].subnetMask) == (netRouters[i].subnetIP & netRouters[i].subnetMask))
+ {
+ return netRouters[i].routers;
+ }
+ }
+return std::vector<uint32_t>();
+}
+//-----------------------------------------------------------------------------
+string REMOTE_SCRIPT::GetUserParam(user_iter u, const string & paramName) const
+{
+string value = "";
+if (strcasecmp(paramName.c_str(), "cash") == 0)
+ strprintf(&value, "%f", u->property.cash.Get());
+else
+if (strcasecmp(paramName.c_str(), "freeMb") == 0)
+ strprintf(&value, "%f", u->property.freeMb.Get());
+else
+if (strcasecmp(paramName.c_str(), "passive") == 0)
+ strprintf(&value, "%d", u->property.passive.Get());
+else
+if (strcasecmp(paramName.c_str(), "disabled") == 0)
+ strprintf(&value, "%d", u->property.disabled.Get());
+else
+if (strcasecmp(paramName.c_str(), "alwaysOnline") == 0)
+ strprintf(&value, "%d", u->property.alwaysOnline.Get());
+else
+if (strcasecmp(paramName.c_str(), "tariffName") == 0 ||
+ strcasecmp(paramName.c_str(), "tariff") == 0)
+ value = "\"" + u->property.tariffName.Get() + "\"";
+else
+if (strcasecmp(paramName.c_str(), "nextTariff") == 0)
+ value = "\"" + u->property.nextTariff.Get() + "\"";
+else
+if (strcasecmp(paramName.c_str(), "address") == 0)
+ value = "\"" + u->property.address.Get() + "\"";
+else
+if (strcasecmp(paramName.c_str(), "note") == 0)
+ value = "\"" + u->property.note.Get() + "\"";
+else
+if (strcasecmp(paramName.c_str(), "group") == 0)
+ value = "\"" + u->property.group.Get() + "\"";
+else
+if (strcasecmp(paramName.c_str(), "email") == 0)
+ value = "\"" + u->property.email.Get() + "\"";
+else
+if (strcasecmp(paramName.c_str(), "realName") == 0)
+ value = "\"" + u->property.realName.Get() + "\"";
+else
+if (strcasecmp(paramName.c_str(), "credit") == 0)
+ strprintf(&value, "%f", u->property.credit.Get());
+else
+if (strcasecmp(paramName.c_str(), "userdata0") == 0)
+ value = "\"" + u->property.userdata0.Get() + "\"";
+else
+if (strcasecmp(paramName.c_str(), "userdata1") == 0)
+ value = "\"" + u->property.userdata1.Get() + "\"";
+else
+if (strcasecmp(paramName.c_str(), "userdata2") == 0)
+ value = "\"" + u->property.userdata2.Get() + "\"";
+else
+if (strcasecmp(paramName.c_str(), "userdata3") == 0)
+ value = "\"" + u->property.userdata3.Get() + "\"";
+else
+if (strcasecmp(paramName.c_str(), "userdata4") == 0)
+ value = "\"" + u->property.userdata4.Get() + "\"";
+else
+if (strcasecmp(paramName.c_str(), "userdata5") == 0)
+ value = "\"" + u->property.userdata5.Get() + "\"";
+else
+if (strcasecmp(paramName.c_str(), "userdata6") == 0)
+ value = "\"" + u->property.userdata6.Get() + "\"";
+else
+if (strcasecmp(paramName.c_str(), "userdata7") == 0)
+ value = "\"" + u->property.userdata7.Get() + "\"";
+else
+if (strcasecmp(paramName.c_str(), "userdata8") == 0)
+ value = "\"" + u->property.userdata8.Get() + "\"";
+else
+if (strcasecmp(paramName.c_str(), "userdata9") == 0)
+ value = "\"" + u->property.userdata9.Get() + "\"";
+else
+if (strcasecmp(paramName.c_str(), "enabledDirs") == 0)
+ value = u->GetEnabledDirs();
+else
+ printfd(__FILE__, "Unknown value name: %s\n", paramName.c_str());
+return value;
+}
+//-----------------------------------------------------------------------------
+void REMOTE_SCRIPT::SetUserNotifier(user_iter u)
+{
+RS_CHG_AFTER_NOTIFIER<uint32_t> AfterChgIPNotifier;
+
+AfterChgIPNotifier.SetRemoteScript(this);
+AfterChgIPNotifier.SetUser(u);
+AfterChgIPNotifierList.push_front(AfterChgIPNotifier);
+
+u->AddCurrIPAfterNotifier(&(*AfterChgIPNotifierList.begin()));
+}
+//-----------------------------------------------------------------------------
+void REMOTE_SCRIPT::UnSetUserNotifier(user_iter u)
+{
+list<RS_CHG_AFTER_NOTIFIER<uint32_t> >::iterator ipAIter;
+std::list<list<RS_CHG_AFTER_NOTIFIER<uint32_t> >::iterator> toErase;
+
+for (ipAIter = AfterChgIPNotifierList.begin(); ipAIter != AfterChgIPNotifierList.end(); ++ipAIter)
+ {
+ if (ipAIter->GetUser() == u)
+ {
+ u->DelCurrIPAfterNotifier(&(*ipAIter));
+ toErase.push_back(ipAIter);
+ }
+ }
+
+std::list<list<RS_CHG_AFTER_NOTIFIER<uint32_t> >::iterator>::iterator eIter;
+
+for (eIter = toErase.begin(); eIter != toErase.end(); ++eIter)
+ {
+ AfterChgIPNotifierList.erase(*eIter);
+ }
+}
+//-----------------------------------------------------------------------------
+template <typename varParamType>
+void RS_CHG_AFTER_NOTIFIER<varParamType>::Notify(const varParamType & oldValue, const varParamType & newValue)
+{
+rs->ChangedIP(user, oldValue, newValue);
+}
+//-----------------------------------------------------------------------------
+void REMOTE_SCRIPT::InitEncrypt(BLOWFISH_CTX * ctx, const string & password) const
+{
+unsigned char keyL[PASSWD_LEN]; // Пароль для шифровки
+memset(keyL, 0, PASSWD_LEN);
+strncpy((char *)keyL, password.c_str(), PASSWD_LEN);
+Blowfish_Init(ctx, keyL, PASSWD_LEN);
+}
+//-----------------------------------------------------------------------------
+void REMOTE_SCRIPT::Encrypt(BLOWFISH_CTX * ctx, char * dst, const char * src, size_t len8) const
+{
+if (dst != src)
+ memcpy(dst, src, len8 * 8);
+for (size_t i = 0; i < len8; ++i)
+ Blowfish_Encrypt(ctx, (uint32_t *)(dst + i * 8), (uint32_t *)(dst + i * 8 + 4));
+}
+//-----------------------------------------------------------------------------
--- /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 : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+/*
+ $Revision: 1.16 $
+ $Date: 2010/09/10 06:43:59 $
+ $Author: faust $
+*/
+
+#ifndef RSCRIPT_H
+#define RSCRIPT_H
+
+#include <pthread.h>
+
+#include <cstring>
+#include <string>
+#include <map>
+#include <functional>
+#include <utility>
+
+#include "base_store.h"
+#include "os_int.h"
+#include "notifer.h"
+#include "user_ips.h"
+#include "../../../user.h"
+#include "../../../users.h"
+#include "blowfish.h"
+#include "rs_packets.h"
+#include "nrmap_parser.h"
+
+extern "C" BASE_PLUGIN * GetPlugin();
+
+#define RS_DEBUG (1)
+
+#define MAX_SHORT_PCKT (3)
+
+class REMOTE_SCRIPT;
+//-----------------------------------------------------------------------------
+class RS_ADD_USER_NONIFIER: public NOTIFIER_BASE<user_iter>
+{
+public:
+ RS_ADD_USER_NONIFIER() {};
+ virtual ~RS_ADD_USER_NONIFIER() {};
+
+ void SetRemoteScript(REMOTE_SCRIPT * a) { rs = a; }
+ void Notify(const user_iter & user);
+
+private:
+ REMOTE_SCRIPT * rs;
+};
+//-----------------------------------------------------------------------------
+class RS_DEL_USER_NONIFIER: public NOTIFIER_BASE<user_iter>
+{
+public:
+ RS_DEL_USER_NONIFIER() {};
+ virtual ~RS_DEL_USER_NONIFIER() {};
+
+ void SetRemoteScript(REMOTE_SCRIPT * a) { rs = a; }
+ void Notify(const user_iter & user);
+
+private:
+ REMOTE_SCRIPT * rs;
+};
+//-----------------------------------------------------------------------------
+template <typename varParamType>
+class RS_CHG_AFTER_NOTIFIER: public PROPERTY_NOTIFIER_BASE<varParamType>
+{
+public:
+ void Notify(const varParamType & oldValue, const varParamType & newValue);
+ void SetUser(user_iter u) { user = u; }
+ user_iter GetUser() {return user; }
+ void SetRemoteScript(REMOTE_SCRIPT * a) { rs = a; }
+
+private:
+ user_iter user;
+ REMOTE_SCRIPT * rs;
+};
+//-----------------------------------------------------------------------------
+struct RS_USER
+{
+ RS_USER();
+ RS_USER(const std::vector<uint32_t> & r, user_iter it);
+time_t lastSentTime;
+user_iter user;
+std::vector<uint32_t> routers;
+int shortPacketsCount;
+};
+//-----------------------------------------------------------------------------
+class RS_SETTINGS
+{
+public:
+ RS_SETTINGS();
+ virtual ~RS_SETTINGS() {};
+ const std::string & GetStrError() const { return errorStr; };
+ int ParseSettings(const MODULE_SETTINGS & s);
+ int GetSendPeriod() const { return sendPeriod; };
+ int GetPort() const { return port; };
+ const std::vector<NET_ROUTER> & GetSubnetsMap() const { return netRouters; };
+ const std::vector<std::string> & GetUserParams() const { return userParams; };
+ const std::string & GetPassword() const { return password; };
+ const std::string & GetMapFileName() const { return subnetFile; };
+
+private:
+ int ParseIntInRange(const std::string & str, int min, int max, int * val);
+ int sendPeriod;
+ uint16_t port;
+ string errorStr;
+ std::vector<NET_ROUTER> netRouters;
+ std::vector<string> userParams;
+ string password;
+ string subnetFile;
+};
+//-----------------------------------------------------------------------------
+class REMOTE_SCRIPT : public BASE_PLUGIN
+{
+public:
+ REMOTE_SCRIPT();
+ virtual ~REMOTE_SCRIPT();
+
+ void SetUsers(USERS * u) { users = u; };
+ void SetTariffs(TARIFFS *) {};
+ void SetAdmins(ADMINS *) {};
+ void SetTraffcounter(TRAFFCOUNTER *) {};
+ void SetStore(BASE_STORE *) {};
+ void SetStgSettings(const SETTINGS *) {};
+ void SetSettings(const MODULE_SETTINGS & s) { settings = s; };
+ int ParseSettings();
+
+ int Start();
+ int Stop();
+ int Reload();
+ bool IsRunning() { return isRunning; };
+
+ const std::string & GetStrError() const { return errorStr; };
+ const std::string GetVersion() const { return "Remote script v 0.3"; };
+ uint16_t GetStartPosition() const { return 20; };
+ uint16_t GetStopPosition() const { return 20; };
+
+ void DelUser(user_iter u) { UnSetUserNotifier(u); };
+ void AddUser(user_iter u) { SetUserNotifier(u); };
+
+ void ChangedIP(user_iter u, uint32_t oldIP, uint32_t newIP);
+
+private:
+ static void * Run(void *);
+ bool PrepareNet();
+ bool FinalizeNet();
+
+ bool Send(uint32_t ip, RS_USER & rsu, bool forceDisconnect = false) const;
+ bool SendDirect(uint32_t ip, RS_USER & rsu, uint32_t routerIP, bool forceDisconnect = false) const;
+ bool PreparePacket(char * buf, size_t bufSize, uint32_t ip, RS_USER &rsu, bool forceDisconnect = false) const;
+ void PeriodicSend();
+
+ std::vector<uint32_t> IP2Routers(uint32_t ip);
+ bool GetUsers();
+ std::string GetUserParam(user_iter u, const std::string & paramName) const;
+
+ void SetUserNotifier(user_iter u);
+ void UnSetUserNotifier(user_iter u);
+
+ void InitEncrypt(BLOWFISH_CTX * ctx, const string & password) const;
+ void Encrypt(BLOWFISH_CTX * ctx, char * dst, const char * src, size_t len8) const;
+
+ mutable BLOWFISH_CTX ctx;
+
+ std::list<RS_CHG_AFTER_NOTIFIER<uint32_t> > AfterChgIPNotifierList;
+ std::map<uint32_t, RS_USER> authorizedUsers;
+
+ mutable std::string errorStr;
+ RS_SETTINGS rsSettings;
+ MODULE_SETTINGS settings;
+ int sendPeriod;
+ int halfPeriod;
+
+ bool nonstop;
+ bool isRunning;
+
+ USERS * users;
+
+ std::vector<NET_ROUTER> netRouters;
+
+ pthread_t thread;
+ pthread_mutex_t mutex;
+
+ int sock;
+
+ RS_ADD_USER_NONIFIER onAddUserNotifier;
+ RS_DEL_USER_NONIFIER onDelUserNotifier;
+
+ friend class UpdateRouter;
+ friend class DisconnectUser;
+};
+//-----------------------------------------------------------------------------
+class DisconnectUser : public std::unary_function<std::pair<const uint32_t, RS_USER> &, void>
+{
+ public:
+ DisconnectUser(REMOTE_SCRIPT & rs) : rscript(rs) {};
+ void operator()(std::pair<const uint32_t, RS_USER> & p)
+ {
+ rscript.Send(p.first, p.second, true);
+ }
+ private:
+ REMOTE_SCRIPT & rscript;
+};
+//-----------------------------------------------------------------------------
+inline void RS_ADD_USER_NONIFIER::Notify(const user_iter & user)
+{
+printfd(__FILE__, "ADD_USER_NONIFIER\n");
+rs->AddUser(user);
+}
+//-----------------------------------------------------------------------------
+inline void RS_DEL_USER_NONIFIER::Notify(const user_iter & user)
+{
+printfd(__FILE__, "DEL_USER_NONIFIER\n");
+rs->DelUser(user);
+}
+//-----------------------------------------------------------------------------
+
+#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 : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+/*
+ $Revision: 1.2 $
+ $Date: 2010/03/04 12:11:09 $
+ $Author: faust $
+*/
+
+#ifndef __SEND_FUNCTOR_H__
+#define __SEND_FUNCTOR_H__
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <functional>
+
+#include "os_int.h"
+
+class PacketSender : public std::unary_function<uint32_t, void> {
+ public:
+ PacketSender(int s, char * b, int l, uint16_t p)
+ : sock(s),
+ buffer(b),
+ length(l),
+ port(p) {};
+ void operator() (uint32_t ip)
+ {
+ int res;
+ struct sockaddr_in sendAddr;
+
+ sendAddr.sin_family = AF_INET;
+ sendAddr.sin_port = port;
+ sendAddr.sin_addr.s_addr = ip;
+
+ res = sendto(sock, buffer, length, 0, (struct sockaddr*)&sendAddr, sizeof(sendAddr));
+ }
+ private:
+ int sock;
+ char * buffer;
+ int length;
+ uint16_t port;
+};
+
+#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 : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+/*
+ $Revision: 1.3 $
+ $Date: 2010/03/04 12:07:03 $
+ $Author: faust $
+*/
+
+#ifndef __UR_FUNCTOR_H__
+#define __UR_FUNCTOR_H__
+
+#include <functional>
+#include <algorithm>
+#include <utility>
+
+#include "rscript.h"
+#include "os_int.h"
+
+#include "common.h"
+
+class UpdateRouter : public std::unary_function<std::pair<const uint32_t, RS_USER>, void>
+{
+public:
+ UpdateRouter(REMOTE_SCRIPT & t)
+ : obj(t) {};
+
+ void operator() (std::pair<const uint32_t, RS_USER> & val)
+ {
+ std::vector<uint32_t> newRouters = obj.IP2Routers(val.first);
+ std::vector<uint32_t>::const_iterator oldIt(val.second.routers.begin());
+ std::vector<uint32_t>::const_iterator newIt(newRouters.begin());
+ val.second.shortPacketsCount = 0;
+ while (oldIt != val.second.routers.end() ||
+ newIt != newRouters.end())
+ {
+ if (oldIt == val.second.routers.end())
+ {
+ if (newIt != newRouters.end())
+ {
+ obj.SendDirect(val.first, val.second, *newIt); // Connect on new router
+ ++newIt;
+ }
+ }
+ else if (newIt == newRouters.end())
+ {
+ //if (oldIt != newRouters.end())
+ //{ // Already checked it
+ obj.SendDirect(val.first, val.second, *oldIt, true); // Disconnect on old router
+ ++oldIt;
+ //}
+ }
+ else if (*oldIt < *newIt)
+ {
+ obj.SendDirect(val.first, val.second, *oldIt, true); // Disconnect on old router
+ ++oldIt;
+ }
+ else if (*oldIt > *newIt)
+ {
+ obj.SendDirect(val.first, val.second, *newIt); // Connect on new router
+ ++newIt;
+ }
+ else
+ {
+ if (oldIt != val.second.routers.end())
+ ++oldIt;
+ if (newIt != newRouters.end())
+ ++newIt;
+ }
+ }
+ val.second.routers = newRouters;
+ /*if (val.second.souters != newRouters)
+ {
+ obj.Send(val.first, val.second, true); // Disconnect on old router
+ val.second.routerIP = obj.IP2Router(val.first); // Change router
+ val.second.shortPacketsCount = 0; // Reset packets count (to prevent alive send)
+ obj.Send(val.first, val.second); // Connect on new router
+ }*/
+ }
+private:
+ REMOTE_SCRIPT & obj;
+};
+
+#endif
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.1 2008/07/05 12:35:53 faust Exp $
+###############################################################################
+
+include ../../../../../Makefile.conf
+
+LIBS += -lexpat
+
+ifeq ($(OS),linux)
+LIBS += -lpthread
+endif
+
+ifeq ($(OS),bsd)
+LIBS += -lc_r
+endif
+
+ifeq ($(OS),bsd5)
+LIBS += -lc_r
+endif
+
+PROG = mod_userstat.so
+
+SRCS = ./userstat.cpp
+
+LIBS += -lstg_common \
+ -lstg_crypto
+
+include ../../Makefile.in
+
--- /dev/null
+#include "datathread.h"
+
+bool DataThread::Init()
+{
+ parser = XML_ParserCreate(NULL);
+ if (!parser) {
+ printfd(__FILE__, "Error creating XML parser\n");
+ }
+ XML_SetStartElementHandler(parser, StartHandler);
+ XML_SetEndElementHandler(parser, EndHandler);
+ XML_SetCharacterDataHandler(parser, DataHandler);
+}
+
+DataThread::~DataThread()
+{
+ XML_ParserFree(parser);
+}
+
+void * DataThread::Run(void * val)
+{
+ DataThread * dt = reinterpret_cast<DataThread *>(val);
+
+ running = true;
+ stoppped = false;
+ while (running) {
+ if (sock >= 0) {
+ done = false;
+ dt->Handle();
+ done = true;
+ close(sock);
+ sock = -1;
+ } else {
+ usleep(1000);
+ }
+ }
+ stopped = true;
+ running = false;
+
+ return NULL;
+}
+
+void DataThread::Handle()
+{
+ int32_t size;
+ unsigned char * buf;
+
+ if (!PrepareContext())
+ return;
+
+ res = read(sock, &size, sizeof(size));
+ if (res != sizeof(size))
+ {
+ printfd(__FILE__, "Reading stream size failed! Wanted %d bytes, got %d bytes.\n", sizeof(size), res);
+ return;
+ }
+
+ printfd(__FILE__, "DataThread::Handle() size = %d\n", size);
+
+ if (size < 0) {
+ printfd(__FILE__, "DataThread::Handle() Invalid data size.\n");
+ return;
+ }
+
+ buf = new unsigned char[size];
+ res = read(sock, buf, size);
+ if (res != size)
+ {
+ printfd(__FILE__, "Reading stream failed! Wanted %d bytes, got %d bytes.\n", size, res);
+ return;
+ }
+
+ std::string data;
+ Decode(buf, data, size);
+
+ printfd(__FILE__, "Received XML: %s\n", data.c_str());
+
+ XML_ParserReset(parser, NULL);
+
+ if (XML_Parse(parser, data.c_str(), data.length(), true) == XML_STATUS_OK) {
+ SendReply();
+ } else {
+ SendError();
+ }
+
+ delete[] buf;
+
+ return;
+}
+
+bool DataThread::PrepareContext()
+{
+ int32_t size;
+ char * login;
+
+ int res = read(sock, &size, sizeof(size));
+ if (res != sizeof(size))
+ {
+ printfd(__FILE__, "Reading stream size failed! Wanted %d bytes, got %d bytes.\n", sizeof(size), res);
+ return;
+ }
+
+ printfd(__FILE__, "DataThread::Handle() size = %d\n", size);
+
+ if (size < 0) {
+ printfd(__FILE__, "DataThread::Handle() Invalid data size.\n");
+ return;
+ }
+
+ login = new char[size];
+
+ res = read(sock, login, size);
+ if (res != size)
+ {
+ printfd(__FILE__, "Reading login failed! Wanted %d bytes, got %d bytes.\n", 32, res);
+ return;
+ }
+
+ std::string l;
+ l.assign(login, size);
+ delete[] login;
+
+ user_iter it;
+ if (users->FindByName(l, &it))
+ {
+ printfd(__FILE__, "User '%s' not found.\n", login);
+ return;
+ }
+
+ password = it->property.password;
+
+ printfd(__FILE__, "DataThread::Handle() Requested user: '%s'\n", login);
+ printfd(__FILE__, "DataThread::Handle() Encryption initiated using password: '%s'\n", password.c_str());
+
+ char * key = new char[password.length()];
+ strncpy(key, password.c_str(), password.length());
+
+ Blowfish_Init(&ctx,
+ reinterpret_cast<unsigned char *>(key),
+ password.length());
+ delete[] key;
+
+ return true;
+}
+
+void DataThread::Encode(const std::string & src, char * dst, int size)
+{
+ const char * ptr = src.c_str();
+ for (int i = 0; i < size / 8; ++i) {
+ uint32_t a;
+ uint32_t b;
+ a = n2l(ptr + i * 8);
+ b = n2l(ptr + i * 8 + 4);
+ Blowfish_Encrypt(&ctx,
+ &a,
+ &b);
+ l2n(a, dst + i * 8);
+ l2n(b, dst + i * 8 + 4);
+ }
+}
+
+void DataThread::Decode(char * src, std::string & dst, int size)
+{
+ char tmp[9];
+ tmp[8] = 0;
+ dst = "";
+
+ for (int i = 0; i < size / 8; ++i) {
+ uint32_t a;
+ uint32_t b;
+ a = n2l(src + i * 8);
+ b = n2l(src + i * 8 + 4);
+ Blowfish_Decrypt(&ctx,
+ &a,
+ &b);
+ l2n(a, tmp);
+ l2n(b, tmp + 4);
+
+ dst += tmp;
+ }
+}
+
+void StartHandler(void *data, const char *el, const char **attr)
+{
+ printfd(__FILE__, "Node: %s\n", el);
+}
+
+void EndHandler(void *data, const char *el)
+{
+}
+
+void DataHandler(void *data, const char *el)
+{
+}
--- /dev/null
+#ifndef __DATATHREAD_H__
+#define __DATATHREAD_H__
+
+#include "../../../users.h"
+#include "base_store.h"
+#include <pthread.h>
+#include <expat.h>
+
+class DataThread {
+public:
+ DataThread() : done(false), sock(-1) { Init(); };
+ DataThread(USERS * u, BASE_STORE * s, int sd)
+ : users(u),
+ store(s),
+ sock(sd),
+ done(false)
+ {
+ Init();
+ };
+ ~DataThread();
+
+ void SetUsers(USERS * u) { users = u; };
+ void SetStore(BASE_STORE * s) { store = s; };
+ void SetSocket(int s) { sock = s; };
+
+ bool isDone() const { return done; };
+ bool Init();
+
+ bool Start();
+ bool Stop();
+
+ static void * Run(void *);
+
+
+private:
+ pthread_t thread;
+ USERS * users;
+ BASE_STORE * store;
+ XML_Parser parser;
+ int sock;
+ bool done;
+ bool running;
+ bool stopped;
+ BLOWFISH_CTX ctx;
+ std::string password;
+ std::string reply;
+
+ void Handle();
+ bool PrepareContect();
+ void Encode(const std::string &, char *);
+ void Decode(char *, const std::string &);
+
+ friend void StartHandler(void *data, const char *el, const char **attr);
+ friend void EndHandler(void *data, const char *el);
+ friend void DataHandler(void *data, const char *el);
+};
+
+#endif
--- /dev/null
+#include <algorithm>
+#include <cstring>
+#include <cerrno>
+#include <arpa/inet.h>
+#include <csignal>
+
+#include "common.h"
+#include "../../../users.h"
+
+#include "userstat.h"
+
+BASE_PLUGIN * GetPlugin()
+{
+return new USERSTAT();
+}
+
+USERSTAT::USERSTAT()
+ : maxThreads(16),
+ port(5555)
+{
+xmlParser = XML_ParserCreate(NULL);
+pthread_mutex_init(&mutex, NULL);
+}
+
+USERSTAT::~USERSTAT()
+{
+XML_ParserFree(xmlParser);
+}
+
+int USERSTAT::ParseSettings()
+{
+vector<PARAM_VALUE>::iterator i;
+string s;
+
+for(i = settings.moduleParams.begin(); i != settings.moduleParams.end(); ++i)
+ {
+ s = i->param;
+ transform(s.begin(), s.end(), s.begin(), USERSTAT::ToLower());
+ if (s == "port")
+ {
+ if (str2x<uint16_t>(*(i->value.begin()), port))
+ {
+ errorStr = "'Port' parameter must be a numeric value";
+ return -1;
+ }
+ }
+ if (s == "maxthreads")
+ {
+ if (str2x<unsigned>(*(i->value.begin()), maxThreads))
+ {
+ errorStr = "'MaxThreads' parameter must be a numeric value";
+ return -1;
+ }
+ }
+ }
+
+return 0;
+}
+
+int USERSTAT::Prepare()
+{
+listenSocket = socket(PF_INET, SOCK_STREAM, 0);
+
+if (listenSocket < 0)
+ {
+ errorStr = "Create USERSTAT socket failed.";
+ return -1;
+ }
+
+printfd(__FILE__, "USERSTAT::Prepare() socket - ok\n");
+
+listenAddr.sin_family = PF_INET;
+listenAddr.sin_port = htons(port);
+listenAddr.sin_addr.s_addr = inet_addr("0.0.0.0");
+
+int lng = 1;
+
+if (0 != setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, &lng, 4))
+ {
+ errorStr = "Setsockopt failed. " + string(strerror(errno));
+ return -1;
+ }
+
+printfd(__FILE__, "USERSTAT::Prepare() setsockopt - ok\n");
+
+int res = bind(listenSocket, (struct sockaddr*)&listenAddr, sizeof(listenAddr));
+
+if (res == -1)
+ {
+ errorStr = "Bind USERSTAT socket failed";
+ return -1;
+ }
+
+printfd(__FILE__, "USERSTAT::Prepare() bind - ok port: %d\n", port);
+
+res = listen(listenSocket, 0);
+if (res == -1)
+ {
+ errorStr = "Listen USERSTAT socket failed";
+ return -1;
+ }
+printfd(__FILE__, "USERSTAT::Prepare() listen - ok\n");
+
+errorStr = "";
+return 0;
+}
+
+int USERSTAT::Finalize()
+{
+return close(listenSocket);
+}
+
+int USERSTAT::Start()
+{
+if (Prepare())
+ {
+ return -1;
+ }
+nonstop = true;
+if (pthread_create(&thread, NULL, Run, this))
+ {
+ errorStr = "Cannot create thread";
+ return -1;
+ }
+
+return 0;
+}
+
+int USERSTAT::Stop()
+{
+nonstop = false;
+if (pthread_kill(thread, SIGTERM))
+ {
+ errorStr = "Cannot send signal to thread";
+ return -1;
+ }
+for (int i = 0; i < 25; i++)
+ {
+ if (!isRunning)
+ break;
+
+ usleep(200000);
+ }
+if (isRunning)
+ {
+ errorStr = "Cannot stop thread";
+ return -1;
+ }
+return 0;
+}
+
+void * USERSTAT::Run(void * t)
+{
+USERSTAT * us = reinterpret_cast<USERSTAT *>(t);
+pthread_t thread;
+int outerSocket;
+struct sockaddr_in outerAddr;
+socklen_t outerAddrLen;
+THREAD_INFO info;
+
+us->isRunning = true;
+while (us->nonstop)
+ {
+ outerSocket = accept(us->listenSocket, (struct sockaddr *)&outerAddr, &outerAddrLen);
+ if (outerSocket > 0)
+ {
+ std::vector<THREAD_INFO>::iterator it;
+ us->pool.erase(remove_if(us->pool.begin(), us->pool.end(), USERSTAT::IsDone()), us->pool.end());
+
+ while (us->pool.size() >= us->maxThreads)
+ usleep(200000);
+
+ info.users = us->users;
+ info.store = us->store;
+ info.outerSocket = outerSocket;
+ info.done = false;
+ us->pool.push_back(info);
+ it = us->pool.end();
+ --it;
+
+ if (pthread_create(&thread, NULL, Operate, &(*it)))
+ {
+ us->errorStr = "Cannot create thread";
+ printfd(__FILE__, "Cannot create thread\n");
+ }
+ it->thread = thread;
+ }
+ }
+us->isRunning = false;
+return NULL;
+}
+
+void * USERSTAT::Operate(void * i)
+{
+ THREAD_INFO * info = reinterpret_cast<THREAD_INFO *>(i);
+ unsigned char * buf;
+ int32_t size;
+ char * login;
+
+ int res = read(info->outerSocket, &size, sizeof(size));
+ if (res != sizeof(size))
+ {
+ printfd(__FILE__, "Reading stream size failed! Wanted %d bytes, got %d bytes.\n", sizeof(size), res);
+ info->done = true;
+ return NULL;
+ }
+
+ printfd(__FILE__, "USERSTAT::Operate() size = %d\n", size);
+
+ if (size < 0) {
+ printfd(__FILE__, "USERSTAT::Operate() Invalid data size.\n");
+ info->done = true;
+ return NULL;
+ }
+
+ login = new char[size];
+
+ res = read(info->outerSocket, login, size);
+ if (res != size)
+ {
+ printfd(__FILE__, "Reading login failed! Wanted %d bytes, got %d bytes.\n", 32, res);
+ info->done = true;
+ return NULL;
+ }
+
+ std::string l;
+ l.assign(login, size);
+
+ res = read(info->outerSocket, &size, sizeof(size));
+ if (res != sizeof(size))
+ {
+ printfd(__FILE__, "Reading stream size failed! Wanted %d bytes, got %d bytes.\n", sizeof(size), res);
+ info->done = true;
+ return NULL;
+ }
+
+ printfd(__FILE__, "USERSTAT::Operate() size = %d\n", size);
+
+ if (size < 0) {
+ printfd(__FILE__, "USERSTAT::Operate() Invalid data size.\n");
+ info->done = true;
+ return NULL;
+ }
+
+ buf = new unsigned char[size];
+ res = read(info->outerSocket, buf, size);
+ if (res != size)
+ {
+ printfd(__FILE__, "Reading stream failed! Wanted %d bytes, got %d bytes.\n", size, res);
+ info->done = true;
+ return NULL;
+ }
+
+ printfd(__FILE__, "Received data: %s\n", buf);
+
+ user_iter it;
+ if (info->users->FindByName(l, &it))
+ {
+ printfd(__FILE__, "User '%s' not found.\n", login);
+ info->done = true;
+ return NULL;
+ }
+
+ std::string password = it->property.password;
+
+ printfd(__FILE__, "USERSTAT::Operate() Requested user: '%s'\n", login);
+ printfd(__FILE__, "USERSTAT::Operate() Encription init using password: '%s'\n", password.c_str());
+
+ BLOWFISH_CTX ctx;
+ char * key = new char[password.length()];
+ strncpy(key, password.c_str(), password.length());
+
+ Blowfish_Init(&ctx,
+ reinterpret_cast<unsigned char *>(key),
+ password.length());
+
+ for (int i = 0; i < size / 8; ++i) {
+ uint32_t a;
+ uint32_t b;
+ a = n2l(buf + i * 8);
+ b = n2l(buf + i * 8 + 4);
+ Blowfish_Decrypt(&ctx,
+ &a,
+ &b);
+ l2n(a, buf + i * 8);
+ l2n(b, buf + i * 8 + 4);
+ }
+
+ delete[] key;
+
+ printfd(__FILE__, "Received XML: %s\n", buf);
+
+ info->done = true;
+ delete[] buf;
+ return NULL;
+}
--- /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>
+ */
+
+/*
+ $Revision: 1.1 $
+ $Date: 2008/07/05 12:35:53 $
+ $Author: faust $
+*/
+
+#ifndef __USERSTAT_H__
+#define __USERSTAT_H__
+
+#include <expat.h>
+#include <pthread.h>
+#include <netinet/in.h>
+
+#include "base_plugin.h"
+
+extern "C" BASE_PLUGIN * GetPlugin();
+
+struct THREAD_INFO
+{
+ pthread_t thread;
+ USERS * users;
+ BASE_STORE * store;
+ int outerSocket;
+ bool done;
+};
+
+uint32_t n2l(unsigned char * c)
+{
+ uint32_t t = *c++ << 24;
+ t += *c++ << 16;
+ t += *c++ << 8;
+ t += *c;
+ return t;
+}
+
+void l2n(uint32_t t, unsigned char * c)
+{
+ *c++ = t >> 24 & 0x000000FF;
+ *c++ = t >> 16 & 0x000000FF;
+ *c++ = t >> 8 & 0x000000FF;
+ *c++ = t & 0x000000FF;
+}
+
+class USERSTAT : public BASE_PLUGIN
+{
+public:
+ USERSTAT();
+ ~USERSTAT();
+
+ virtual void SetUsers(USERS * u) { users = u; };
+ virtual void SetTariffs(TARIFFS * t) {};
+ virtual void SetAdmins(ADMINS * a) {};
+ virtual void SetTraffcounter(TRAFFCOUNTER * tc) {};
+ virtual void SetStore(BASE_STORE * st) { store = st; };
+ virtual void SetStgSettings(const SETTINGS * s) {};
+ virtual void SetSettings(const MODULE_SETTINGS & s) { settings = s; };
+ virtual int ParseSettings();
+
+ virtual int Start();
+ virtual int Stop();
+ virtual bool IsRunning() { return isRunning; };
+ virtual const string & GetStrError() const { return errorStr; };
+ virtual const string GetVersion() const { return version; };
+ virtual uint16_t GetStartPosition() const { return 0; };
+ virtual uint16_t GetStopPosition() const { return 0; };
+
+private:
+ struct IsDone : public unary_function<THREAD_INFO, bool>
+ {
+ bool operator()(const THREAD_INFO & info) { return info.done; };
+ };
+ struct ToLower : public unary_function<char, char>
+ {
+ char operator() (char c) const { return std::tolower(c); }
+ };
+ bool isRunning;
+ bool nonstop;
+ std::string errorStr;
+ std::string version;
+ std::vector<THREAD_INFO> pool;
+ int listenSocket;
+ int threads;
+ unsigned maxThreads;
+ uint16_t port;
+ struct sockaddr_in listenAddr;
+ pthread_t thread;
+ pthread_mutex_t mutex;
+ USERS * users;
+ BASE_STORE * store;
+
+ MODULE_SETTINGS settings;
+
+ XML_Parser xmlParser;
+
+ int Prepare();
+ int Finalize();
+ static void * Run(void *);
+ static void * Operate(void *);
+
+ friend void ParseXMLStart(void * data, char * name, char ** attr);
+ friend void ParseXMLEnd(void * data, char * name);
+};
+
+#endif
--- /dev/null
+../pg_driver.la
\ No newline at end of file
--- /dev/null
+SOURCES=$(wildcard *.cpp)
+
+all: test_pg_driver pg_driver.so
+
+test_pg_driver: test_pg_driver.o
+ $(CXX) $^ -ldl -o $@
+
+pg_driver.so: pg_driver.o
+ $(CXX) $^ -shared -lpq -o $@
+
+clean:
+ rm -f *.d *.o *.so test_pg_driver
+
+
+-include $(subst .cpp,.d,$(SOURCES))
+
+%.d: %.cpp
+ @$(CC) -MM $(CXXFLAGS) $< > $@.$$$$; \
+ sed 's,\($*\).o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
+ rm -f $@.$$$$
--- /dev/null
+#include <sstream>
+
+#include "pg_driver.h"
+
+BASE_DB * CreateDriver()
+{
+ return new PG_DRIVER();
+}
+
+void DestroyDriver(BASE_DB * drv)
+{
+ delete drv;
+}
+
+PG_DRIVER::~PG_DRIVER()
+{
+ if (conn != NULL)
+ PQfinish(conn);
+}
+
+bool PG_DRIVER::Connect()
+{
+ std::stringstream params;
+ params << "host=" << host << " "
+ << "dbname=" << database << " "
+ << "user=" << user << " "
+ << "password=" << password;
+ std::string str = params.str();
+ conn = PQconnectdb(str.c_str());
+ errorMsg = PQerrorMessage(conn);
+ return PQstatus(conn) != CONNECTION_OK;
+}
+
+bool PG_DRIVER::Disconnect()
+{
+ if (PQstatus(conn) == CONNECTION_OK) {
+ PQfinish(conn);
+ conn = NULL;
+ }
+
+ return false;
+}
+
+bool PG_DRIVER::Query(const std::string & query)
+{
+ PQclear(result);
+ result = PQexec(conn, query.c_str());
+ errorMsg = PQerrorMessage(conn);
+ tuples = PQntuples(result);
+ columns = PQnfields(result);
+ affected = atoi(PQcmdTuples(result));
+
+ cols.erase(cols.begin(), cols.end());
+ cols.reserve(columns);
+
+ if (tuples) {
+ for (int i = 0; i < columns; ++i) {
+ cols.push_back(PQfname(result, i));
+ }
+ }
+
+ if (!result)
+ return true;
+
+ if (PQresultStatus(result) == PGRES_COMMAND_OK)
+ return false;
+
+ if (PQresultStatus(result) == PGRES_TUPLES_OK)
+ return false;
+
+ return true;
+}
+
+bool PG_DRIVER::Start()
+{
+ return Query("BEGIN");
+}
+
+bool PG_DRIVER::Commit()
+{
+ return Query("COMMIT");
+}
+
+bool PG_DRIVER::Rollback()
+{
+ return Query("ROLLBACK");
+}
+
+BASE_DB::TUPLE PG_DRIVER::GetTuple(int n) const
+{
+ BASE_DB::TUPLE tuple;
+
+ for (int i = 0; i < columns; ++i)
+ tuple[cols[i]] = PQgetvalue(result, n, i);
+
+ return tuple;
+}
+
+BASE_DB::TUPLES PG_DRIVER::GetResult() const
+{
+ BASE_DB::TUPLES tpls;
+
+ for (int i = 0; i < tuples; ++i)
+ tpls.push_back(GetTuple(i));
+
+ return tpls;
+}
--- /dev/null
+#ifndef __PG_DRIVER_H__
+#define __PG_DRIVER_H__
+
+#include <libpq-fe.h>
+
+#include "base_db.h"
+
+class PG_DRIVER : public BASE_DB {
+public:
+ virtual ~PG_DRIVER();
+
+ virtual bool Connect();
+ virtual bool Disconnect();
+ virtual bool Query(const std::string &);
+ virtual bool Start();
+ virtual bool Commit();
+ virtual bool Rollback();
+
+ virtual BASE_DB::TUPLES GetResult() const;
+ virtual BASE_DB::TUPLE GetTuple(int n = 0) const;
+
+private:
+ PGconn * conn;
+ PGresult * result;
+};
+
+#endif
--- /dev/null
+# pg_driver.la - a libtool library file
+# Generated by ltmain.sh - GNU libtool 1.5.26 (1.1220.2.493 2008/02/01 16:58:18)
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname=''
+
+# Names of this library.
+library_names=''
+
+# The name of the static archive.
+old_library='pg_driver.a'
+
+# Libraries that this one depends upon.
+dependency_libs=' -lpq'
+
+# Version information for pg_driver.
+current=
+age=
+revision=
+
+# Is this an already installed library?
+installed=no
+
+# Should we warn about portability when linking against -modules?
+shouldnotlink=yes
+
+# Files to dlopen/dlpreopen
+dlopen=''
+dlpreopen=''
+
+# Directory that this library needs to be installed in:
+libdir=''
--- /dev/null
+# pg_driver.lo - a libtool object file
+# Generated by ltmain.sh - GNU libtool 1.5.26 (1.1220.2.493 2008/02/01 16:58:18)
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# Name of the PIC object.
+pic_object='.libs/pg_driver.o'
+
+# Name of the non-PIC object.
+non_pic_object='pg_driver.o'
+
--- /dev/null
+#include <iostream>
+#include <string>
+#include <sstream>
+
+#include <dlfcn.h>
+
+#include "base_db.h"
+
+int main(int argc, char ** argv)
+{
+ BASE_DB * db;
+
+ void * lh = dlopen("./pg_driver.so", RTLD_NOW | RTLD_GLOBAL);
+
+ if (lh == NULL) {
+ std::cout << "Error loading shared object file pg_driver.so. Reason: '" << dlerror() << "'" << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ CreateDriverFn CreateDriver = reinterpret_cast<CreateDriverFn>(dlsym(lh, "CreateDriver"));
+ if (CreateDriver == NULL) {
+ std::cout << "Error getting symbol 'CreateDriver' address. Reason: '" << dlerror() << "'" << std::endl;
+ dlclose(lh);
+ return EXIT_FAILURE;
+ }
+ DestroyDriverFn DestroyDriver = reinterpret_cast<DestroyDriverFn>(dlsym(lh, "DestroyDriver"));
+ if (DestroyDriver == NULL) {
+ std::cout << "Error getting symbol 'DestroyDriver' address. Reason: '" << dlerror() << "'" << std::endl;
+ dlclose(lh);
+ return EXIT_FAILURE;
+ }
+
+ db = CreateDriver();
+
+ db->SetHost("localhost");
+ db->SetDatabase("stargazer");
+ db->SetUser("stg");
+ db->SetPassword("123456");
+
+ if (db->Connect()) {
+ std::cout << "Error connecting db. Reason: '" << db->GetErrorMsg() << "'" << std::endl;
+ DestroyDriver(db);
+ dlclose(lh);
+ return EXIT_FAILURE;
+ }
+
+ std::stringstream query;
+ query << "SELECT * FROM information_schema.tables";
+
+ if (db->Query(query.str())) {
+ std::cout << "Error querying db. Reason: '" << db->GetErrorMsg() << "'" << std::endl;
+ db->Disconnect();
+ DestroyDriver(db);
+ dlclose(lh);
+ return EXIT_FAILURE;
+ }
+
+ std::cout << "Tuples: " << db->GetTuples() << std::endl;
+ std::cout << "Columns: " << db->GetColumns() << std::endl;
+ BASE_DB::COLUMNS cols;
+ BASE_DB::COLUMNS::iterator it;
+ cols = db->GetColumnsNames();
+ std::cout << "Cols count: " << cols.size() << std::endl;
+ std::cout << "Columns names:" << std::endl;
+ for (it = cols.begin(); it != cols.end(); ++it)
+ std::cout << *it << " ";
+ std::cout << std::endl;
+
+ for (int i = 0; i < db->GetTuples(); ++i) {
+ BASE_DB::TUPLE tuple(db->GetTuple(i));
+ BASE_DB::TUPLE::iterator it;
+ for (it = tuple.begin(); it != tuple.end(); ++it)
+ std::cout << it->second << " ";
+ std::cout << std::endl;
+ }
+
+ query.str("");
+ query << "create table test ( id bigserial, message text )";
+ if (db->Query(query.str())) {
+ std::cout << "Error querying db. Reason: '" << db->GetErrorMsg() << "'" << std::endl;
+ db->Disconnect();
+ DestroyDriver(db);
+ dlclose(lh);
+ return EXIT_FAILURE;
+ }
+
+ query.str("");
+ query << "insert into test (message) values ('abc');";
+ query << "insert into test (message) values ('def');";
+ query << "insert into test (message) values ('zxc');";
+ if (db->Query(query.str())) {
+ std::cout << "Error querying db. Reason: '" << db->GetErrorMsg() << "'" << std::endl;
+ db->Disconnect();
+ DestroyDriver(db);
+ dlclose(lh);
+ return EXIT_FAILURE;
+ }
+
+ query.str("");
+ query << "SELECT * FROM test";
+ if (db->Query(query.str())) {
+ std::cout << "Error querying db. Reason: '" << db->GetErrorMsg() << "'" << std::endl;
+ db->Disconnect();
+ DestroyDriver(db);
+ dlclose(lh);
+ return EXIT_FAILURE;
+ }
+ std::cout << "Tuples: " << db->GetTuples() << std::endl;
+ std::cout << "Columns: " << db->GetColumns() << std::endl;
+ cols = db->GetColumnsNames();
+ std::cout << "Cols count: " << cols.size() << std::endl;
+ std::cout << "Columns names:" << std::endl;
+ for (it = cols.begin(); it != cols.end(); ++it)
+ std::cout << *it << " ";
+ std::cout << std::endl;
+
+ for (int i = 0; i < db->GetTuples(); ++i) {
+ BASE_DB::TUPLE tuple(db->GetTuple(i));
+ BASE_DB::TUPLE::iterator it;
+ for (it = tuple.begin(); it != tuple.end(); ++it)
+ std::cout << it->second << " ";
+ std::cout << std::endl;
+ }
+
+ query.str("");
+ query << "drop table test";
+ if (db->Query(query.str())) {
+ std::cout << "Error querying db. Reason: '" << db->GetErrorMsg() << "'" << std::endl;
+ db->Disconnect();
+ DestroyDriver(db);
+ dlclose(lh);
+ return EXIT_FAILURE;
+ }
+
+ if (db->Disconnect()) {
+ std::cout << "Error connecting db. Reason: '" << db->GetErrorMsg() << "'" << std::endl;
+ DestroyDriver(db);
+ dlclose(lh);
+ return EXIT_FAILURE;
+ }
+
+ DestroyDriver(db);
+
+ dlclose(lh);
+
+ return EXIT_SUCCESS;
+}
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.16 2010/03/04 10:47:45 faust Exp $
+###############################################################################
+
+include ../../../../../Makefile.conf
+
+PROG = mod_store_files.so
+
+SRCS = ./file_store.cpp
+
+STGLIBS = -lconffiles -lstg_common -lstg_locker -lstg_crypto
+
+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 : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+/*
+ $Revision: 1.67 $
+ $Date: 2010/10/07 19:53:11 $
+ $Author: faust $
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <pwd.h>
+#include <grp.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include <dirent.h>
+
+#include <cstdio>
+#include <ctime>
+#include <cerrno>
+#include <cstring>
+#include <sstream>
+#include <algorithm>
+
+#include "common.h"
+#include "user_ips.h"
+#include "user_conf.h"
+#include "user_stat.h"
+#include "stg_const.h"
+#include "file_store.h"
+#include "blowfish.h"
+#include "stg_logger.h"
+#include "stg_locker.h"
+
+#define DELETED_USERS_DIR "deleted_users"
+
+#define adm_enc_passwd "cjeifY8m3"
+
+using namespace std;
+
+const int pt_mega = 1024 * 1024;
+//-----------------------------------------------------------------------------
+class BAK_FILE
+{
+public:
+
+ //-------------------------------------------------------------------------
+ BAK_FILE(const string & fileName, bool removeBak)
+ : f(NULL),
+ removeBak(false)
+ {
+ bakSuccessed = false;
+ BAK_FILE::removeBak = removeBak;
+ fileNameBak = fileName + ".bak";
+ /*struct stat fileStat;
+ if (stat(fileName.c_str(), &fileStat) == 0)
+ {
+ char * buff = new char[fileStat.st_size];
+ f = fopen(fileName.c_str(), "rb");
+ if(f)
+ {
+ fread(buff, 1, fileStat.st_size, f);
+ fclose(f);
+
+ fileNameBak = fileName + ".bak";
+ f = fopen(fileNameBak.c_str(), "wb");
+ if(f)
+ {
+ fwrite(buff, 1, fileStat.st_size, f);
+ fclose(f);
+ }
+ }
+
+ delete[] buff;
+
+ bakSuccessed = true;
+ }*/
+ if (rename(fileName.c_str(), fileNameBak.c_str()))
+ {
+ printfd(__FILE__, "BAK_FILE::BAK_FILE - rename failed. Message: '%s'\n", strerror(errno));
+ }
+ else
+ {
+ bakSuccessed = true;
+ }
+
+ }
+ //-------------------------------------------------------------------------
+ ~BAK_FILE()
+ {
+ if(bakSuccessed && removeBak)
+ {
+ if (unlink(fileNameBak.c_str()))
+ {
+ printfd(__FILE__, "BAK_FILE::~BAK_FILE - unlink failed. Message: '%s'\n", strerror(errno));
+ }
+ }
+ }
+ //-------------------------------------------------------------------------
+
+private:
+ FILE * f;
+ bool bakSuccessed;
+ string fileNameBak;
+ bool removeBak;
+};
+//-----------------------------------------------------------------------------
+class FILES_STORE_CREATOR
+{
+private:
+ FILES_STORE * fs;
+
+public:
+ FILES_STORE_CREATOR()
+ : fs(new FILES_STORE())
+ {
+ };
+ ~FILES_STORE_CREATOR()
+ {
+ delete fs;
+ };
+
+ FILES_STORE * GetStore()
+ {
+ return fs;
+ };
+};
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+FILES_STORE_CREATOR fsc;
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+BASE_STORE * GetStore()
+{
+return fsc.GetStore();
+}
+//-----------------------------------------------------------------------------
+FILES_STORE_SETTINGS::FILES_STORE_SETTINGS()
+ : settings(NULL),
+ removeBak(true),
+ readBak(true)
+{
+}
+//-----------------------------------------------------------------------------
+FILES_STORE_SETTINGS::~FILES_STORE_SETTINGS()
+{
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE_SETTINGS::ParseOwner(const vector<PARAM_VALUE> & moduleParams, const string & owner, uid_t * uid)
+{
+PARAM_VALUE pv;
+pv.param = owner;
+vector<PARAM_VALUE>::const_iterator pvi;
+pvi = find(moduleParams.begin(), moduleParams.end(), pv);
+if (pvi == moduleParams.end())
+ {
+ errorStr = "Parameter \'" + owner + "\' not found.";
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+if (User2UID(pvi->value[0].c_str(), uid) < 0)
+ {
+ errorStr = "Parameter \'" + owner + "\': Unknown user \'" + pvi->value[0] + "\'";
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE_SETTINGS::ParseGroup(const vector<PARAM_VALUE> & moduleParams, const string & group, gid_t * gid)
+{
+PARAM_VALUE pv;
+pv.param = group;
+vector<PARAM_VALUE>::const_iterator pvi;
+pvi = find(moduleParams.begin(), moduleParams.end(), pv);
+if (pvi == moduleParams.end())
+ {
+ errorStr = "Parameter \'" + group + "\' not found.";
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+if (Group2GID(pvi->value[0].c_str(), gid) < 0)
+ {
+ errorStr = "Parameter \'" + group + "\': Unknown group \'" + pvi->value[0] + "\'";
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE_SETTINGS::ParseYesNo(const string & value, bool * val)
+{
+if (0 == strcasecmp(value.c_str(), "yes"))
+ {
+ *val = true;
+ return 0;
+ }
+if (0 == strcasecmp(value.c_str(), "no"))
+ {
+ *val = false;
+ return 0;
+ }
+
+errorStr = "Incorrect value \'" + value + "\'.";
+return -1;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE_SETTINGS::ParseMode(const vector<PARAM_VALUE> & moduleParams, const string & modeStr, mode_t * mode)
+{
+PARAM_VALUE pv;
+pv.param = modeStr;
+vector<PARAM_VALUE>::const_iterator pvi;
+pvi = find(moduleParams.begin(), moduleParams.end(), pv);
+if (pvi == moduleParams.end())
+ {
+ errorStr = "Parameter \'" + modeStr + "\' not found.";
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+if (Str2Mode(pvi->value[0].c_str(), mode) < 0)
+ {
+ errorStr = "Parameter \'" + modeStr + "\': Incorrect mode \'" + pvi->value[0] + "\'";
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE_SETTINGS::ParseSettings(const MODULE_SETTINGS & s)
+{
+if (ParseOwner(s.moduleParams, "StatOwner", &statUID) < 0)
+ return -1;
+if (ParseGroup(s.moduleParams, "StatGroup", &statGID) < 0)
+ return -1;
+if (ParseMode(s.moduleParams, "StatMode", &statMode) < 0)
+ return -1;
+
+if (ParseOwner(s.moduleParams, "ConfOwner", &confUID) < 0)
+ return -1;
+if (ParseGroup(s.moduleParams, "ConfGroup", &confGID) < 0)
+ return -1;
+if (ParseMode(s.moduleParams, "ConfMode", &confMode) < 0)
+ return -1;
+
+if (ParseOwner(s.moduleParams, "UserLogOwner", &userLogUID) < 0)
+ return -1;
+if (ParseGroup(s.moduleParams, "UserLogGroup", &userLogGID) < 0)
+ return -1;
+if (ParseMode(s.moduleParams, "UserLogMode", &userLogMode) < 0)
+ return -1;
+
+vector<PARAM_VALUE>::const_iterator pvi;
+PARAM_VALUE pv;
+pv.param = "RemoveBak";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end())
+ {
+ removeBak = true;
+ }
+else
+ {
+ if (ParseYesNo(pvi->value[0], &removeBak))
+ {
+ printfd(__FILE__, "Cannot parse parameter 'RemoveBak'\n");
+ return -1;
+ }
+ }
+
+pv.param = "ReadBak";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end())
+ {
+ readBak = false;
+ }
+else
+ {
+ if (ParseYesNo(pvi->value[0], &readBak))
+ {
+ printfd(__FILE__, "Cannot parse parameter 'ReadBak'\n");
+ return -1;
+ }
+ }
+
+pv.param = "WorkDir";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end())
+ {
+ errorStr = "Parameter \'WorkDir\' not found.";
+ printfd(__FILE__, "Parameter 'WorkDir' not found\n");
+ return -1;
+ }
+
+workDir = pvi->value[0];
+if (workDir.size() && workDir[workDir.size() - 1] == '/')
+ {
+ workDir.resize(workDir.size() - 1);
+ }
+usersDir = workDir + "/users/";
+tariffsDir = workDir + "/tariffs/";
+adminsDir = workDir + "/admins/";
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+const string & FILES_STORE_SETTINGS::GetStrError() const
+{
+return errorStr;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE_SETTINGS::User2UID(const char * user, uid_t * uid)
+{
+struct passwd * pw;
+pw = getpwnam(user);
+if (!pw)
+ {
+ errorStr = string("User \'") + string(user) + string("\' not found in system.");
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+
+*uid = pw->pw_uid;
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE_SETTINGS::Group2GID(const char * gr, gid_t * gid)
+{
+struct group * grp;
+grp = getgrnam(gr);
+if (!grp)
+ {
+ errorStr = string("Group \'") + string(gr) + string("\' not found in system.");
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+
+*gid = grp->gr_gid;
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE_SETTINGS::Str2Mode(const char * str, mode_t * mode)
+{
+char a;
+char b;
+char c;
+if (strlen(str) > 3)
+ {
+ errorStr = string("Error parsing mode \'") + str + string("\'");
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+
+for (int i = 0; i < 3; i++)
+ if (str[i] > '7' || str[i] < '0')
+ {
+ errorStr = string("Error parsing mode \'") + str + string("\'");
+ printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+
+a = str[0] - '0';
+b = str[1] - '0';
+c = str[2] - '0';
+
+*mode = ((mode_t)c) + ((mode_t)b << 3) + ((mode_t)a << 6);
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+string FILES_STORE_SETTINGS::GetWorkDir() const
+{
+return workDir;
+}
+//-----------------------------------------------------------------------------
+string FILES_STORE_SETTINGS::GetUsersDir() const
+{
+return usersDir;
+}
+//-----------------------------------------------------------------------------
+string FILES_STORE_SETTINGS::GetAdminsDir() const
+{
+return adminsDir;
+}
+//-----------------------------------------------------------------------------
+string FILES_STORE_SETTINGS::GetTariffsDir() const
+{
+return tariffsDir;
+}
+//-----------------------------------------------------------------------------
+mode_t FILES_STORE_SETTINGS::GetStatMode() const
+{
+return statMode;
+}
+//-----------------------------------------------------------------------------
+mode_t FILES_STORE_SETTINGS::GetStatModeDir() const
+{
+mode_t mode = statMode;
+if (statMode & S_IRUSR) mode |= S_IXUSR;
+if (statMode & S_IRGRP) mode |= S_IXGRP;
+if (statMode & S_IROTH) mode |= S_IXOTH;
+return mode;
+}
+//-----------------------------------------------------------------------------
+uid_t FILES_STORE_SETTINGS::GetStatUID() const
+{
+return statUID;
+}
+//-----------------------------------------------------------------------------
+gid_t FILES_STORE_SETTINGS::GetStatGID() const
+{
+return statGID;
+}
+//-----------------------------------------------------------------------------
+mode_t FILES_STORE_SETTINGS::GetConfMode() const
+{
+return confMode;
+}
+//-----------------------------------------------------------------------------
+mode_t FILES_STORE_SETTINGS::GetConfModeDir() const
+{
+mode_t mode = confMode;
+if (statMode & S_IRUSR) mode |= S_IXUSR;
+if (statMode & S_IRGRP) mode |= S_IXGRP;
+if (statMode & S_IROTH) mode |= S_IXOTH;
+return mode;
+}
+//-----------------------------------------------------------------------------
+uid_t FILES_STORE_SETTINGS::GetConfUID() const
+{
+return confUID;
+}
+//-----------------------------------------------------------------------------
+gid_t FILES_STORE_SETTINGS::GetConfGID() const
+{
+return confGID;
+}
+//-----------------------------------------------------------------------------
+mode_t FILES_STORE_SETTINGS::GetLogMode() const
+{
+return userLogMode;
+}
+//-----------------------------------------------------------------------------
+uid_t FILES_STORE_SETTINGS::GetLogUID() const
+{
+return userLogUID;
+}
+//-----------------------------------------------------------------------------
+gid_t FILES_STORE_SETTINGS::GetLogGID() const
+{
+return userLogGID;
+}
+//-----------------------------------------------------------------------------
+bool FILES_STORE_SETTINGS::GetRemoveBak() const
+{
+return removeBak;
+}
+//-----------------------------------------------------------------------------
+bool FILES_STORE_SETTINGS::GetReadBak() const
+{
+return readBak;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+/*BASE_SETTINGS * FILES_STORE::GetStoreSettings()
+{
+return &storeSettings;
+}*/
+//-----------------------------------------------------------------------------
+FILES_STORE::FILES_STORE()
+{
+version = "file_store v.1.04";
+
+pthread_mutexattr_t attr;
+pthread_mutexattr_init(&attr);
+pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+pthread_mutex_init(&mutex, &attr);
+};
+//-----------------------------------------------------------------------------
+FILES_STORE::~FILES_STORE()
+{
+
+};
+//-----------------------------------------------------------------------------
+void FILES_STORE::SetSettings(const MODULE_SETTINGS & s)
+{
+settings = s;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::ParseSettings()
+{
+int ret = storeSettings.ParseSettings(settings);
+if (ret)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = storeSettings.GetStrError();
+ }
+return ret;
+}
+//-----------------------------------------------------------------------------
+const string & FILES_STORE::GetStrError() const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+return errorStr;
+}
+//-----------------------------------------------------------------------------
+const string & FILES_STORE::GetVersion() const
+{
+return version;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::GetFilesList(vector<string> * filesList, const string & directory, mode_t mode, const string & ext) const
+{
+// æÕÎËÃÉÑ ÐÒÏÓÍÁÔÒÉ×ÁÅÔ ÓÏÄÅÒÖÉÍÏÅ ÄÉÒÅËÔÏÒÉÉ
+DIR * d;
+string str;
+struct stat st;
+dirent * dir;
+
+filesList->clear();
+
+d = opendir(directory.c_str());
+
+if (!d)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Directory \'" + directory + "\' cannot be opened.";
+ //printfd(__FILE__, "%s\n", errorStr.c_str());
+ return -1;
+ }
+
+int d_nameLen;
+int extLen = ext.size() ;
+while ((dir = readdir(d)))
+ {
+ if (strcmp(dir->d_name, ".") && strcmp(dir->d_name, ".."))
+ {
+ str = directory + "/" + string(dir->d_name);
+ if (!stat(str.c_str(), &st))
+ {
+ if (st.st_mode & mode) // ïÔÓÅ× ÆÁÊÌÏ× or directories
+ {
+ d_nameLen = strlen(dir->d_name);
+ if (d_nameLen > extLen)
+ {
+ if (strcmp(dir->d_name + (d_nameLen - extLen), ext.c_str()) == 0)
+ {
+ dir->d_name[d_nameLen - extLen] = 0;
+ filesList->push_back(dir->d_name);
+ }
+ }
+ }
+ }
+ }
+ }
+
+closedir(d);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::GetUsersList(vector<string> * usersList) const
+{
+return GetFilesList(usersList, storeSettings.GetUsersDir(), S_IFDIR, "");
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::GetAdminsList(vector<string> * adminsList) const
+{
+return GetFilesList(adminsList, storeSettings.GetAdminsDir(), S_IFREG, ".adm");
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::GetTariffsList(vector<string> * tariffsList) const
+{
+return GetFilesList(tariffsList, storeSettings.GetTariffsDir(), S_IFREG, ".tf");
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::RemoveDir(const char * path) const
+{
+vector<string> filesList;
+
+GetFilesList(&filesList, path, S_IFREG, "");
+
+for (unsigned i = 0; i < filesList.size(); i++)
+ {
+ string file = path + string("/") + filesList[i];
+ if (unlink(file.c_str()))
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "unlink failed. Message: '";
+ errorStr += strerror(errno);
+ errorStr += "'";
+ printfd(__FILE__, "FILES_STORE::RemoveDir - unlink failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+ }
+
+GetFilesList(&filesList, path, S_IFDIR, "");
+
+for (unsigned i = 0; i < filesList.size(); i++)
+ {
+ string dir = string(path) + "/" + filesList[i];
+ RemoveDir(dir.c_str());
+ }
+
+if (rmdir(path))
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "rmdir failed. Message: '";
+ errorStr += strerror(errno);
+ errorStr += "'";
+ printfd(__FILE__, "FILES_STORE::RemoveDir - rmdir failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::AddUser(const string & login) const
+{
+FILE * f;
+string fileName;
+
+strprintf(&fileName, "%s%s", storeSettings.GetUsersDir().c_str(), login.c_str());
+
+if (mkdir(fileName.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == -1)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = string("mkdir failed. Message: '") + strerror(errno) + "'";
+ printfd(__FILE__, "FILES_STORE::AddUser - mkdir failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+
+strprintf(&fileName, "%s%s/conf", storeSettings.GetUsersDir().c_str(), login.c_str());
+f = fopen(fileName.c_str(), "wt");
+if (f)
+ {
+ if (fprintf(f, "\n") < 0)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "fprintf failed. Message: '";
+ errorStr += strerror(errno);
+ errorStr += "'";
+ printfd(__FILE__, "FILES_STORE::AddUser - fprintf failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+ fclose(f);
+ }
+else
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Cannot create file \"" + fileName + "\'";
+ printfd(__FILE__, "FILES_STORE::AddUser - fopen failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+
+strprintf(&fileName, "%s%s/stat", storeSettings.GetUsersDir().c_str(), login.c_str());
+f = fopen(fileName.c_str(), "wt");
+if (f)
+ {
+ if (fprintf(f, "\n") < 0)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "fprintf failed. Message: '";
+ errorStr += strerror(errno);
+ errorStr += "'";
+ printfd(__FILE__, "FILES_STORE::AddUser - fprintf failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+ fclose(f);
+ }
+else
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Cannot create file \"" + fileName + "\'";
+ printfd(__FILE__, "FILES_STORE::AddUser - fopen failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::DelUser(const string & login) const
+{
+string dirName;
+string dirName1;
+
+strprintf(&dirName, "%s/"DELETED_USERS_DIR, storeSettings.GetWorkDir().c_str());
+if (access(dirName.c_str(), F_OK) != 0)
+ {
+ if (mkdir(dirName.c_str(), 0700) != 0)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Directory '" + dirName + "' cannot be created.";
+ printfd(__FILE__, "FILES_STORE::DelUser - mkdir failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+ }
+
+if (access(dirName.c_str(), F_OK) == 0)
+ {
+ strprintf(&dirName, "%s/"DELETED_USERS_DIR"/%s.%lu", storeSettings.GetWorkDir().c_str(), login.c_str(), time(NULL));
+ strprintf(&dirName1, "%s/%s", storeSettings.GetUsersDir().c_str(), login.c_str());
+ if (rename(dirName1.c_str(), dirName.c_str()))
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Error moving dir from " + dirName1 + " to " + dirName;
+ printfd(__FILE__, "FILES_STORE::DelUser - rename failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+ }
+else
+ {
+ strprintf(&dirName, "%s/%s", storeSettings.GetUsersDir().c_str(), login.c_str());
+ if (RemoveDir(dirName.c_str()))
+ {
+ return -1;
+ }
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::RestoreUserConf(USER_CONF * conf, const string & login) const
+{
+string fileName;
+fileName = storeSettings.GetUsersDir() + "/" + login + "/conf";
+if (RestoreUserConf(conf, login, fileName))
+ {
+ if (!storeSettings.GetReadBak())
+ {
+ return -1;
+ }
+ return RestoreUserConf(conf, login, fileName + ".bak");
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::RestoreUserConf(USER_CONF * conf, const string & login, const string & fileName) const
+{
+CONFIGFILE cf(fileName);
+int e = cf.Error();
+string str;
+
+if (e)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "User \'" + login + "\' data not read.";
+ printfd(__FILE__, "FILES_STORE::RestoreUserConf - conf read failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+if (cf.ReadString("Password", &conf->password, "") < 0)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "User \'" + login + "\' data not read. Parameter Password.";
+ printfd(__FILE__, "FILES_STORE::RestoreUserConf - password read failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+if (conf->password.empty())
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "User \'" + login + "\' password is blank.";
+ printfd(__FILE__, "FILES_STORE::RestoreUserConf - password is blank for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+if (cf.ReadString("tariff", &conf->tariffName, "") < 0)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "User \'" + login + "\' data not read. Parameter Tariff.";
+ printfd(__FILE__, "FILES_STORE::RestoreUserConf - tariff read failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+if (conf->tariffName.empty())
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "User \'" + login + "\' tariff is blank.";
+ printfd(__FILE__, "FILES_STORE::RestoreUserConf - tariff is blank for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+string ipStr;
+cf.ReadString("IP", &ipStr, "?");
+USER_IPS i;
+try
+ {
+ i = StrToIPS(ipStr);
+ }
+catch (string s)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "User \'" + login + "\' data not read. Parameter IP address. " + s;
+ printfd(__FILE__, "FILES_STORE::RestoreUserConf - ip read failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+conf->ips = i;
+
+if (cf.ReadInt("alwaysOnline", &conf->alwaysOnline, 0) != 0)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "User \'" + login + "\' data not read. Parameter AlwaysOnline.";
+ printfd(__FILE__, "FILES_STORE::RestoreUserConf - alwaysonline read failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+if (cf.ReadInt("down", &conf->disabled, 0) != 0)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "User \'" + login + "\' data not read. Parameter Down.";
+ printfd(__FILE__, "FILES_STORE::RestoreUserConf - down read failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+if (cf.ReadInt("passive", &conf->passive, 0) != 0)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "User \'" + login + "\' data not read. Parameter Passive.";
+ printfd(__FILE__, "FILES_STORE::RestoreUserConf - passive read failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+cf.ReadInt("DisabledDetailStat", &conf->disabledDetailStat, 0);
+cf.ReadTime("CreditExpire", &conf->creditExpire, 0);
+cf.ReadString("TariffChange", &conf->nextTariff, "");
+cf.ReadString("Group", &conf->group, "");
+cf.ReadString("RealName", &conf->realName, "");
+cf.ReadString("Address", &conf->address, "");
+cf.ReadString("Phone", &conf->phone, "");
+cf.ReadString("Note", &conf->note, "");
+cf.ReadString("email", &conf->email, "");
+
+char userdataName[12];
+for (int i = 0; i < USERDATA_NUM; i++)
+ {
+ snprintf(userdataName, 12, "Userdata%d", i);
+ cf.ReadString(userdataName, &conf->userdata[i], "");
+ }
+
+if (cf.ReadDouble("Credit", &conf->credit, 0) != 0)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "User \'" + login + "\' data not read. Parameter Credit.";
+ printfd(__FILE__, "FILES_STORE::RestoreUserConf - credit read failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::RestoreUserStat(USER_STAT * stat, const string & login) const
+{
+string fileName;
+fileName = storeSettings.GetUsersDir() + "/" + login + "/stat";
+
+if (RestoreUserStat(stat, login, fileName))
+ {
+ if (!storeSettings.GetReadBak())
+ {
+ return -1;
+ }
+ return RestoreUserStat(stat, login, fileName + ".bak");
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::RestoreUserStat(USER_STAT * stat, const string & login, const string & fileName) const
+{
+CONFIGFILE cf(fileName);
+
+int e = cf.Error();
+
+if (e)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "User \'" + login + "\' stat not read. Cannot open file " + fileName + ".";
+ printfd(__FILE__, "FILES_STORE::RestoreUserStat - stat read failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+char s[22];
+
+for (int i = 0; i < DIR_NUM; i++)
+ {
+ uint64_t traff;
+ snprintf(s, 22, "D%d", i);
+ if (cf.ReadULongLongInt(s, &traff, 0) != 0)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "User \'" + login + "\' stat not read. Parameter " + string(s);
+ printfd(__FILE__, "FILES_STORE::RestoreUserStat - download stat read failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+ stat->down[i] = traff;
+
+ snprintf(s, 22, "U%d", i);
+ if (cf.ReadULongLongInt(s, &traff, 0) != 0)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "User \'" + login + "\' stat not read. Parameter " + string(s);
+ printfd(__FILE__, "FILES_STORE::RestoreUserStat - upload stat read failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+ stat->up[i] = traff;
+ }
+
+if (cf.ReadDouble("Cash", &stat->cash, 0) != 0)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "User \'" + login + "\' stat not read. Parameter Cash";
+ printfd(__FILE__, "FILES_STORE::RestoreUserStat - cash read failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+if (cf.ReadDouble("FreeMb", &stat->freeMb, 0) != 0)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "User \'" + login + "\' stat not read. Parameter FreeMb";
+ printfd(__FILE__, "FILES_STORE::RestoreUserStat - freemb read failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+if (cf.ReadTime("LastCashAddTime", &stat->lastCashAddTime, 0) != 0)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "User \'" + login + "\' stat not read. Parameter LastCashAddTime";
+ printfd(__FILE__, "FILES_STORE::RestoreUserStat - lastcashaddtime read failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+if (cf.ReadTime("PassiveTime", &stat->passiveTime, 0) != 0)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "User \'" + login + "\' stat not read. Parameter PassiveTime";
+ printfd(__FILE__, "FILES_STORE::RestoreUserStat - passivetime read failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+if (cf.ReadDouble("LastCashAdd", &stat->lastCashAdd, 0) != 0)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "User \'" + login + "\' stat not read. Parameter LastCashAdd";
+ printfd(__FILE__, "FILES_STORE::RestoreUserStat - lastcashadd read failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+if (cf.ReadTime("LastActivityTime", &stat->lastActivityTime, 0) != 0)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "User \'" + login + "\' stat not read. Parameter LastActivityTime";
+ printfd(__FILE__, "FILES_STORE::RestoreUserStat - lastactivitytime read failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::SaveUserConf(const USER_CONF & conf, const string & login) const
+{
+string fileName;
+fileName = storeSettings.GetUsersDir() + "/" + login + "/conf";
+
+BAK_FILE bakFile(fileName, storeSettings.GetRemoveBak());
+
+if (access(fileName.c_str(), W_OK) != 0)
+ {
+ FILE * f;
+ f = fopen(fileName.c_str(), "wb");
+ if (f)
+ fclose(f);
+ }
+
+CONFIGFILE cfstat(fileName);
+
+int e = cfstat.Error();
+
+if (e)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = string("User \'") + login + "\' conf not written\n";
+ printfd(__FILE__, "FILES_STORE::SaveUserConf - conf write failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+e = chmod(fileName.c_str(), storeSettings.GetConfMode());
+e += chown(fileName.c_str(), storeSettings.GetConfUID(), storeSettings.GetConfGID());
+
+if (e)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ printfd(__FILE__, "FILES_STORE::SaveUserConf - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
+ }
+
+cfstat.WriteString("Password", conf.password);
+cfstat.WriteInt ("Passive", conf.passive);
+cfstat.WriteInt ("Down", conf.disabled);
+cfstat.WriteInt("DisabledDetailStat", conf.disabledDetailStat);
+cfstat.WriteInt ("AlwaysOnline", conf.alwaysOnline);
+cfstat.WriteString("Tariff", conf.tariffName);
+cfstat.WriteString("Address", conf.address);
+cfstat.WriteString("Phone", conf.phone);
+cfstat.WriteString("Email", conf.email);
+cfstat.WriteString("Note", conf.note);
+cfstat.WriteString("RealName", conf.realName);
+cfstat.WriteString("Group", conf.group);
+cfstat.WriteDouble("Credit", conf.credit);
+cfstat.WriteString("TariffChange", conf.nextTariff);
+
+char userdataName[12];
+for (int i = 0; i < USERDATA_NUM; i++)
+ {
+ snprintf(userdataName, 12, "Userdata%d", i);
+ cfstat.WriteString(userdataName, conf.userdata[i]);
+ }
+cfstat.WriteInt("CreditExpire", conf.creditExpire);
+
+stringstream ipStr;
+ipStr << conf.ips;
+cfstat.WriteString("IP", ipStr.str());
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::SaveUserStat(const USER_STAT & stat, const string & login) const
+{
+char s[22];
+string fileName;
+fileName = storeSettings.GetUsersDir() + "/" + login + "/stat";
+
+BAK_FILE bakFile(fileName, storeSettings.GetRemoveBak());
+
+if (access(fileName.c_str(), W_OK) != 0)
+ {
+ FILE * f;
+ f = fopen(fileName.c_str(), "wb");
+ if (f)
+ fclose(f);
+ }
+
+CONFIGFILE cfstat(fileName);
+int e = cfstat.Error();
+
+if (e)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = string("User \'") + login + "\' stat not written\n";
+ printfd(__FILE__, "FILES_STORE::SaveUserStat - stat write failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+for (int i = 0; i < DIR_NUM; i++)
+ {
+ snprintf(s, 22, "D%d", i);
+ cfstat.WriteInt(s, stat.down[i]);
+ snprintf(s, 22, "U%d", i);
+ cfstat.WriteInt(s, stat.up[i]);
+ }
+
+cfstat.WriteDouble("Cash", stat.cash);
+cfstat.WriteDouble("FreeMb", stat.freeMb);
+cfstat.WriteDouble("LastCashAdd", stat.lastCashAdd);
+cfstat.WriteInt("LastCashAddTime", stat.lastCashAddTime);
+cfstat.WriteInt("PassiveTime", stat.passiveTime);
+cfstat.WriteInt("LastActivityTime", stat.lastActivityTime);
+
+e = chmod(fileName.c_str(), storeSettings.GetStatMode());
+e += chown(fileName.c_str(), storeSettings.GetStatUID(), storeSettings.GetStatGID());
+
+if (e)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ printfd(__FILE__, "FILES_STORE::SaveUserStat - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::WriteLogString(const string & str, const string & login) const
+{
+FILE * f;
+time_t tm = time(NULL);
+string fileName;
+fileName = storeSettings.GetUsersDir() + "/" + login + "/log";
+f = fopen(fileName.c_str(), "at");
+
+if (f)
+ {
+ fprintf(f, "%s", LogDate(tm));
+ fprintf(f, " -- ");
+ fprintf(f, "%s", str.c_str());
+ fprintf(f, "\n");
+ fclose(f);
+ }
+else
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Cannot open \'" + fileName + "\'";
+ printfd(__FILE__, "FILES_STORE::WriteLogString - log write failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+int e = chmod(fileName.c_str(), storeSettings.GetLogMode());
+e += chown(fileName.c_str(), storeSettings.GetLogUID(), storeSettings.GetLogGID());
+
+if (e)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ printfd(__FILE__, "FILES_STORE::WriteLogString - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::WriteLog2String(const string & str, const string & login) const
+{
+FILE * f;
+time_t tm = time(NULL);
+string fileName;
+fileName = storeSettings.GetUsersDir() + "/" + login + "/log2";
+f = fopen(fileName.c_str(), "at");
+
+if (f)
+ {
+ fprintf(f, "%s", LogDate(tm));
+ fprintf(f, " -- ");
+ fprintf(f, "%s", str.c_str());
+ fprintf(f, "\n");
+ fclose(f);
+ }
+else
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Cannot open \'" + fileName + "\'";
+ printfd(__FILE__, "FILES_STORE::WriteLogString - log write failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+int e = chmod(fileName.c_str(), storeSettings.GetLogMode());
+e += chown(fileName.c_str(), storeSettings.GetLogUID(), storeSettings.GetLogGID());
+
+if (e)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ printfd(__FILE__, "FILES_STORE::WriteLogString - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::WriteUserChgLog(const string & login,
+ const string & admLogin,
+ uint32_t admIP,
+ const string & paramName,
+ const string & oldValue,
+ const string & newValue,
+ const string & message) const
+{
+string userLogMsg = "Admin \'" + admLogin + "\', " + inet_ntostring(admIP) + ": \'"
+ + paramName + "\' parameter changed from \'" + oldValue +
+ "\' to \'" + newValue + "\'. " + message;
+
+return WriteLogString(userLogMsg, login);
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::WriteUserConnect(const string & login, uint32_t ip) const
+{
+string logStr = "Connect, " + inet_ntostring(ip);
+if (WriteLogString(logStr, login))
+ return -1;
+return WriteLog2String(logStr, login);
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::WriteUserDisconnect(const string & login,
+ const DIR_TRAFF & up,
+ const DIR_TRAFF & down,
+ const DIR_TRAFF & sessionUp,
+ const DIR_TRAFF & sessionDown,
+ double cash,
+ double freeMb,
+ const std::string & reason) const
+{
+stringstream logStr;
+logStr << "Disconnect, ";
+/*stringstream sssu;
+stringstream sssd;
+stringstream ssmu;
+stringstream ssmd;
+stringstream sscash;
+
+ssmu << up;
+ssmd << down;
+
+sssu << sessionUp;
+sssd << sessionDown;
+
+sscash << cash;*/
+
+logStr << " session upload: \'"
+ << sessionUp
+ << "\' session download: \'"
+ << sessionDown
+ << "\' month upload: \'"
+ << up
+ << "\' month download: \'"
+ << down
+ << "\' cash: \'"
+ << cash
+ << "\'";
+
+if (WriteLogString(logStr.str(), login))
+ return -1;
+
+logStr << " freeMb: \'"
+ << freeMb
+ << "\'"
+ << " reason: \'"
+ << reason
+ << "\'";
+
+return WriteLog2String(logStr.str(), login);
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::SaveMonthStat(const USER_STAT & stat, int month, int year, const string & login) const
+{
+string str;
+CONFIGFILE * s;
+int e;
+FILE *f;
+
+strprintf(&str,"%s/%s/stat.%d.%02d",
+ storeSettings.GetUsersDir().c_str(), login.c_str(), year + 1900, month + 1);
+
+if ((f = fopen(str.c_str(), "w")))
+ {
+ fprintf(f, "\n");
+ fclose(f);
+ }
+
+s = new CONFIGFILE(str);
+e = s->Error();
+
+if (e)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Cannot create file " + str;
+ printfd(__FILE__, "FILES_STORE::SaveMonthStat - month stat write failed for user '%s'\n", login.c_str());
+ return -1;
+ }
+
+char dirName[3];
+
+for (int i = 0; i < DIR_NUM; i++)
+ {
+ snprintf(dirName, 3, "U%d", i);
+ s->WriteInt(dirName, stat.up[i]);
+ snprintf(dirName, 3, "D%d", i);
+ s->WriteInt(dirName, stat.down[i]);
+ }
+
+s->WriteDouble("cash", stat.cash);
+
+delete s;
+
+return 0;
+}
+//-----------------------------------------------------------------------------*/
+int FILES_STORE::AddAdmin(const string & login) const
+{
+string fileName;
+strprintf(&fileName, "%s/%s.adm", storeSettings.GetAdminsDir().c_str(), login.c_str());
+FILE * f;
+f = fopen(fileName.c_str(), "wt");
+if (f)
+ {
+ fprintf(f, "\n");
+ fclose(f);
+ return 0;
+ }
+
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+errorStr = "Cannot create file " + fileName;
+printfd(__FILE__, "FILES_STORE::AddAdmin - failed to add admin '%s'\n", login.c_str());
+return -1;
+}
+//-----------------------------------------------------------------------------*/
+int FILES_STORE::DelAdmin(const string & login) const
+{
+string fileName;
+strprintf(&fileName, "%s/%s.adm", storeSettings.GetAdminsDir().c_str(), login.c_str());
+if (unlink(fileName.c_str()))
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "unlink failed. Message: '";
+ errorStr += strerror(errno);
+ errorStr += "'";
+ printfd(__FILE__, "FILES_STORE::DelAdmin - unlink failed. Message: '%s'\n", strerror(errno));
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------*/
+int FILES_STORE::SaveAdmin(const ADMIN_CONF & ac) const
+{
+char passwordE[2 * ADM_PASSWD_LEN + 2];
+char pass[ADM_PASSWD_LEN + 1];
+char adminPass[ADM_PASSWD_LEN + 1];
+
+string fileName;
+
+strprintf(&fileName, "%s/%s.adm", storeSettings.GetAdminsDir().c_str(), ac.login.c_str());
+
+CONFIGFILE cf(fileName);
+
+int e = cf.Error();
+
+if (e)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Cannot write admin " + ac.login + ". " + fileName;
+ printfd(__FILE__, "FILES_STORE::SaveAdmin - failed to save admin '%s'\n", ac.login.c_str());
+ return -1;
+ }
+
+memset(pass, 0, sizeof(pass));
+memset(adminPass, 0, sizeof(adminPass));
+
+BLOWFISH_CTX ctx;
+EnDecodeInit(adm_enc_passwd, strlen(adm_enc_passwd), &ctx);
+
+strncpy(adminPass, ac.password.c_str(), ADM_PASSWD_LEN);
+adminPass[ADM_PASSWD_LEN - 1] = 0;
+
+for (int i = 0; i < ADM_PASSWD_LEN/8; i++)
+ {
+ EncodeString(pass + 8*i, adminPass + 8*i, &ctx);
+ }
+
+pass[ADM_PASSWD_LEN - 1] = 0;
+Encode12(passwordE, pass, ADM_PASSWD_LEN);
+//printfd(__FILE__, "passwordE %s\n", passwordE);
+
+cf.WriteString("password", passwordE);
+cf.WriteInt("ChgConf", ac.priv.userConf);
+cf.WriteInt("ChgPassword", ac.priv.userPasswd);
+cf.WriteInt("ChgStat", ac.priv.userStat);
+cf.WriteInt("ChgCash", ac.priv.userCash);
+cf.WriteInt("UsrAddDel", ac.priv.userAddDel);
+cf.WriteInt("ChgTariff", ac.priv.tariffChg);
+cf.WriteInt("ChgAdmin", ac.priv.adminChg);
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::RestoreAdmin(ADMIN_CONF * ac, const string & login) const
+{
+string fileName;
+strprintf(&fileName, "%s/%s.adm", storeSettings.GetAdminsDir().c_str(), login.c_str());
+CONFIGFILE cf(fileName);
+char pass[ADM_PASSWD_LEN + 1];
+char password[ADM_PASSWD_LEN + 1];
+char passwordE[2*ADM_PASSWD_LEN + 2];
+BLOWFISH_CTX ctx;
+
+string p;
+
+if (cf.Error())
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Cannot open " + fileName;
+ printfd(__FILE__, "FILES_STORE::RestoreAdmin - failed to restore admin '%s'\n", ac->login.c_str());
+ return -1;
+ }
+
+int a;
+
+if (cf.ReadString("password", &p, "*"))
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Error in parameter password";
+ printfd(__FILE__, "FILES_STORE::RestoreAdmin - password read failed for admin '%s'\n", ac->login.c_str());
+ return -1;
+ }
+
+memset(passwordE, 0, sizeof(passwordE));
+strncpy(passwordE, p.c_str(), 2*ADM_PASSWD_LEN);
+
+//printfd(__FILE__, "passwordE %s\n", passwordE);
+
+memset(pass, 0, sizeof(pass));
+
+if (passwordE[0] != 0)
+ {
+ Decode21(pass, passwordE);
+ EnDecodeInit(adm_enc_passwd, strlen(adm_enc_passwd), &ctx);
+
+ for (int i = 0; i < ADM_PASSWD_LEN/8; i++)
+ {
+ DecodeString(password + 8*i, pass + 8*i, &ctx);
+ }
+ }
+else
+ {
+ password[0] = 0;
+ }
+
+ac->password = password;
+
+if (cf.ReadInt("ChgConf", &a, 0) == 0)
+ ac->priv.userConf = a;
+else
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Error in parameter ChgConf";
+ printfd(__FILE__, "FILES_STORE::RestoreAdmin - chgconf read failed for admin '%s'\n", ac->login.c_str());
+ return -1;
+ }
+
+if (cf.ReadInt("ChgPassword", &a, 0) == 0)
+ ac->priv.userPasswd = a;
+else
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Error in parameter ChgPassword";
+ printfd(__FILE__, "FILES_STORE::RestoreAdmin - chgpassword read failed for admin '%s'\n", ac->login.c_str());
+ return -1;
+ }
+
+if (cf.ReadInt("ChgStat", &a, 0) == 0)
+ ac->priv.userStat = a;
+else
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Error in parameter ChgStat";
+ printfd(__FILE__, "FILES_STORE::RestoreAdmin - chgstat read failed for admin '%s'\n", ac->login.c_str());
+ return -1;
+ }
+
+if (cf.ReadInt("ChgCash", &a, 0) == 0)
+ ac->priv.userCash = a;
+else
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Error in parameter ChgCash";
+ printfd(__FILE__, "FILES_STORE::RestoreAdmin - chgcash read failed for admin '%s'\n", ac->login.c_str());
+ return -1;
+ }
+
+if (cf.ReadInt("UsrAddDel", &a, 0) == 0)
+ ac->priv.userAddDel = a;
+else
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Error in parameter UsrAddDel";
+ printfd(__FILE__, "FILES_STORE::RestoreAdmin - usradddel read failed for admin '%s'\n", ac->login.c_str());
+ return -1;
+ }
+
+if (cf.ReadInt("ChgAdmin", &a, 0) == 0)
+ ac->priv.adminChg = a;
+else
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Error in parameter ChgAdmin";
+ printfd(__FILE__, "FILES_STORE::RestoreAdmin - chgadmin read failed for admin '%s'\n", ac->login.c_str());
+ return -1;
+ }
+
+if (cf.ReadInt("ChgTariff", &a, 0) == 0)
+ ac->priv.tariffChg = a;
+else
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Error in parameter ChgTariff";
+ printfd(__FILE__, "FILES_STORE::RestoreAdmin - chgtariff read failed for admin '%s'\n", ac->login.c_str());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::AddTariff(const string & name) const
+{
+string fileName;
+strprintf(&fileName, "%s/%s.tf", storeSettings.GetTariffsDir().c_str(), name.c_str());
+FILE * f;
+f = fopen(fileName.c_str(), "wt");
+if (f)
+ {
+ fprintf(f, "\n");
+ fclose(f);
+ return 0;
+ }
+
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+errorStr = "Cannot create file " + fileName;
+printfd(__FILE__, "FILES_STORE::AddTariff - failed to add tariff '%s'\n", name.c_str());
+return -1;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::DelTariff(const string & name) const
+{
+string fileName;
+strprintf(&fileName, "%s/%s.tf", storeSettings.GetTariffsDir().c_str(), name.c_str());
+if (unlink(fileName.c_str()))
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "unlink failed. Message: '";
+ errorStr += strerror(errno);
+ errorStr += "'";
+ printfd(__FILE__, "FILES_STORE::DelTariff - unlink failed. Message: '%s'\n", strerror(errno));
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::RestoreTariff(TARIFF_DATA * td, const string & tariffName) const
+{
+string tariffFileName = storeSettings.GetTariffsDir() + "/" + tariffName + ".tf";
+CONFIGFILE conf(tariffFileName);
+string str;
+td->tariffConf.name = tariffName;
+
+if (conf.Error() != 0)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Cannot read file " + tariffFileName;
+ printfd(__FILE__, "FILES_STORE::RestoreTariff - failed to read tariff '%s'\n", tariffName.c_str());
+ return -1;
+ }
+
+string param;
+for (int i = 0; i<DIR_NUM; i++)
+ {
+ strprintf(¶m, "Time%d", i);
+ if (conf.ReadString(param, &str, "00:00-00:00") < 0)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ printfd(__FILE__, "FILES_STORE::RestoreTariff - time%d read failed for tariff '%s'\n", i, tariffName.c_str());
+ return -1;
+ }
+
+ ParseTariffTimeStr(str.c_str(),
+ td->dirPrice[i].hDay,
+ td->dirPrice[i].mDay,
+ td->dirPrice[i].hNight,
+ td->dirPrice[i].mNight);
+
+ strprintf(¶m, "PriceDayA%d", i);
+ if (conf.ReadDouble(param, &td->dirPrice[i].priceDayA, 0.0) < 0)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ printfd(__FILE__, "FILES_STORE::RestoreTariff - pricedaya read failed for tariff '%s'\n", tariffName.c_str());
+ return -1;
+ }
+ td->dirPrice[i].priceDayA /= (1024*1024);
+
+ strprintf(¶m, "PriceDayB%d", i);
+ if (conf.ReadDouble(param, &td->dirPrice[i].priceDayB, 0.0) < 0)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ printfd(__FILE__, "FILES_STORE::RestoreTariff - pricedayb read failed for tariff '%s'\n", tariffName.c_str());
+ return -1;
+ }
+ td->dirPrice[i].priceDayB /= (1024*1024);
+
+ strprintf(¶m, "PriceNightA%d", i);
+ if (conf.ReadDouble(param, &td->dirPrice[i].priceNightA, 0.0) < 0)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ printfd(__FILE__, "FILES_STORE::RestoreTariff - pricenighta read failed for tariff '%s'\n", tariffName.c_str());
+ return -1;
+ }
+ td->dirPrice[i].priceNightA /= (1024*1024);
+
+ strprintf(¶m, "PriceNightB%d", i);
+ if (conf.ReadDouble(param, &td->dirPrice[i].priceNightB, 0.0) < 0)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ printfd(__FILE__, "FILES_STORE::RestoreTariff - pricenightb read failed for tariff '%s'\n", tariffName.c_str());
+ return -1;
+ }
+ td->dirPrice[i].priceNightB /= (1024*1024);
+
+ strprintf(¶m, "Threshold%d", i);
+ if (conf.ReadInt(param, &td->dirPrice[i].threshold, 0) < 0)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ printfd(__FILE__, "FILES_STORE::RestoreTariff - threshold read failed for tariff '%s'\n", tariffName.c_str());
+ return -1;
+ }
+
+ strprintf(¶m, "SinglePrice%d", i);
+ if (conf.ReadInt(param, &td->dirPrice[i].singlePrice, 0) < 0)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ printfd(__FILE__, "FILES_STORE::RestoreTariff - singleprice read failed for tariff '%s'\n", tariffName.c_str());
+ return -1;
+ }
+
+ strprintf(¶m, "NoDiscount%d", i);
+ if (conf.ReadInt(param, &td->dirPrice[i].noDiscount, 0) < 0)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ printfd(__FILE__, "FILES_STORE::RestoreTariff - nodiscount read failed for tariff '%s'\n", tariffName.c_str());
+ return -1;
+ }
+ }
+
+if (conf.ReadDouble("Fee", &td->tariffConf.fee, 0) < 0)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter Fee";
+ printfd(__FILE__, "FILES_STORE::RestoreTariff - fee read failed for tariff '%s'\n", tariffName.c_str());
+ return -1;
+ }
+
+if (conf.ReadDouble("Free", &td->tariffConf.free, 0) < 0)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter Free";
+ printfd(__FILE__, "FILES_STORE::RestoreTariff - free read failed for tariff '%s'\n", tariffName.c_str());
+ return -1;
+ }
+
+if (conf.ReadDouble("PassiveCost", &td->tariffConf.passiveCost, 0) < 0)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter PassiveCost";
+ printfd(__FILE__, "FILES_STORE::RestoreTariff - passivecost read failed for tariff '%s'\n", tariffName.c_str());
+ return -1;
+ }
+
+if (conf.ReadString("TraffType", &str, "") < 0)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter TraffType";
+ printfd(__FILE__, "FILES_STORE::RestoreTariff - trafftype read failed for tariff '%s'\n", tariffName.c_str());
+ return -1;
+ }
+
+if (!strcasecmp(str.c_str(), "up"))
+ td->tariffConf.traffType = TRAFF_UP;
+else
+ if (!strcasecmp(str.c_str(), "down"))
+ td->tariffConf.traffType = TRAFF_DOWN;
+ else
+ if (!strcasecmp(str.c_str(), "up+down"))
+ td->tariffConf.traffType = TRAFF_UP_DOWN;
+ else
+ if (!strcasecmp(str.c_str(), "max"))
+ td->tariffConf.traffType = TRAFF_MAX;
+ else
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter TraffType incorrect";
+ printfd(__FILE__, "FILES_STORE::RestoreTariff - invalid trafftype for tariff '%s'\n", tariffName.c_str());
+ return -1;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::SaveTariff(const TARIFF_DATA & td, const string & tariffName) const
+{
+string tariffFileName = storeSettings.GetTariffsDir() + "/" + tariffName + ".tf";
+if (access(tariffFileName.c_str(), W_OK) != 0)
+ {
+ int fd = open(tariffFileName.c_str(), O_CREAT, 0600);
+ if (fd)
+ close(fd);
+ }
+
+CONFIGFILE cf(tariffFileName);
+
+int e = cf.Error();
+
+if (e)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Error writing tariff " + tariffName;
+ printfd(__FILE__, "FILES_STORE::RestoreTariff - failed to save tariff '%s'\n", tariffName.c_str());
+ return e;
+ }
+
+string param;
+for (int i = 0; i < DIR_NUM; i++)
+ {
+ strprintf(¶m, "PriceDayA%d", i);
+ cf.WriteDouble(param, td.dirPrice[i].priceDayA * pt_mega);
+
+ strprintf(¶m, "PriceDayB%d", i);
+ cf.WriteDouble(param, td.dirPrice[i].priceDayB * pt_mega);
+
+ strprintf(¶m, "PriceNightA%d", i);
+ cf.WriteDouble(param, td.dirPrice[i].priceNightA * pt_mega);
+
+ strprintf(¶m, "PriceNightB%d", i);
+ cf.WriteDouble(param, td.dirPrice[i].priceNightB * pt_mega);
+
+ strprintf(¶m, "Threshold%d", i);
+ cf.WriteInt(param, td.dirPrice[i].threshold);
+
+ string s;
+ strprintf(¶m, "Time%d", i);
+
+ strprintf(&s, "%0d:%0d-%0d:%0d",
+ td.dirPrice[i].hDay,
+ td.dirPrice[i].mDay,
+ td.dirPrice[i].hNight,
+ td.dirPrice[i].mNight);
+
+ cf.WriteString(param, s);
+
+ strprintf(¶m, "NoDiscount%d", i);
+ cf.WriteInt(param, td.dirPrice[i].noDiscount);
+
+ strprintf(¶m, "SinglePrice%d", i);
+ cf.WriteInt(param, td.dirPrice[i].singlePrice);
+ }
+
+cf.WriteDouble("PassiveCost", td.tariffConf.passiveCost);
+cf.WriteDouble("Fee", td.tariffConf.fee);
+cf.WriteDouble("Free", td.tariffConf.free);
+
+switch (td.tariffConf.traffType)
+ {
+ case TRAFF_UP:
+ cf.WriteString("TraffType", "up");
+ break;
+ case TRAFF_DOWN:
+ cf.WriteString("TraffType", "down");
+ break;
+ case TRAFF_UP_DOWN:
+ cf.WriteString("TraffType", "up+down");
+ break;
+ case TRAFF_MAX:
+ cf.WriteString("TraffType", "max");
+ break;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::WriteDetailedStat(const map<IP_DIR_PAIR, STAT_NODE> * statTree,
+ time_t lastStat,
+ const string & login) const
+{
+char fn[FN_STR_LEN];
+char dn[FN_STR_LEN];
+FILE * statFile;
+//char timestr[30];
+time_t t;//, lastTimeReal;
+tm * lt;
+
+t = time(NULL);
+
+snprintf(dn, FN_STR_LEN, "%s/%s/detail_stat", storeSettings.GetUsersDir().c_str(), login.c_str());
+if (access(dn, F_OK) != 0)
+ {
+ if (mkdir(dn, 0700) != 0)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Directory \'" + string(dn) + "\' cannot be created.";
+ printfd(__FILE__, "FILES_STORE::WriteDetailStat - mkdir failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+ }
+
+int e = chown(dn, storeSettings.GetStatUID(), storeSettings.GetStatGID());
+e += chmod(dn, storeSettings.GetStatModeDir());
+
+if (e)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ printfd(__FILE__, "FILES_STORE::WriteDetailStat - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
+ }
+
+lt = localtime(&t);
+
+if (lt->tm_hour == 0 && lt->tm_min <= 5)
+ {
+ t -= 3600 * 24;
+ lt = localtime(&t);
+ }
+
+snprintf(dn, FN_STR_LEN, "%s/%s/detail_stat/%d",
+ storeSettings.GetUsersDir().c_str(),
+ login.c_str(),
+ lt->tm_year+1900);
+
+if (access(dn, F_OK) != 0)
+ {
+ if (mkdir(dn, 0700) != 0)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Directory \'" + string(dn) + "\' cannot be created.";
+ printfd(__FILE__, "FILES_STORE::WriteDetailStat - mkdir failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+ }
+
+e = chown(dn, storeSettings.GetStatUID(), storeSettings.GetStatGID());
+e += chmod(dn, storeSettings.GetStatModeDir());
+
+if (e)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ printfd(__FILE__, "FILES_STORE::WriteDetailStat - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
+ }
+
+snprintf(dn, FN_STR_LEN, "%s/%s/detail_stat/%d/%s%d",
+ storeSettings.GetUsersDir().c_str(),
+ login.c_str(),
+ lt->tm_year+1900,
+ lt->tm_mon+1 < 10 ? "0" : "",
+ lt->tm_mon+1);
+if (access(dn, F_OK) != 0)
+ {
+ if (mkdir(dn, 0700) != 0)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Directory \'" + string(dn) + "\' cannot be created.";
+ printfd(__FILE__, "FILES_STORE::WriteDetailStat - mkdir failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+ }
+
+e = chown(dn, storeSettings.GetStatUID(), storeSettings.GetStatGID());
+e += chmod(dn, storeSettings.GetStatModeDir());
+
+if (e)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ printfd(__FILE__, "FILES_STORE::WriteDetailStat - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
+ }
+
+snprintf(fn, FN_STR_LEN, "%s/%s%d", dn, lt->tm_mday < 10 ? "0" : "", lt->tm_mday);
+
+statFile = fopen (fn, "at");
+
+if (!statFile)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "File \'" + string(fn) + "\' cannot be written.";
+ printfd(__FILE__, "FILES_STORE::WriteDetailStat - fopen failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+
+struct tm * lt1;
+struct tm * lt2;
+
+lt1 = localtime(&lastStat);
+
+int h1, m1, s1;
+int h2, m2, s2;
+
+h1 = lt1->tm_hour;
+m1 = lt1->tm_min;
+s1 = lt1->tm_sec;
+
+lt2 = localtime(&t);
+
+h2 = lt2->tm_hour;
+m2 = lt2->tm_min;
+s2 = lt2->tm_sec;
+
+if (fprintf(statFile, "-> %02d.%02d.%02d - %02d.%02d.%02d\n",
+ h1, m1, s1, h2, m2, s2) < 0)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = string("fprint failed. Message: '") + strerror(errno) + "'";
+ printfd(__FILE__, "FILES_STORE::WriteDetailStat - fprintf failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+
+map<IP_DIR_PAIR, STAT_NODE>::const_iterator stIter;
+stIter = statTree->begin();
+
+while (stIter != statTree->end())
+ {
+ string u, d;
+ x2str(stIter->second.up, u);
+ x2str(stIter->second.down, d);
+ #ifdef TRAFF_STAT_WITH_PORTS
+ if (fprintf(statFile, "%17s:%hu\t%15d\t%15s\t%15s\t%f\n",
+ inet_ntostring(stIter->first.ip).c_str(),
+ stIter->first.port,
+ stIter->first.dir,
+ d.c_str(),
+ u.c_str(),
+ stIter->second.cash) < 0)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "fprint failed. Message: '";
+ errorStr += strerror(errno);
+ errorStr += "'";
+ printfd(__FILE__, "FILES_STORE::WriteDetailStat - fprintf failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+ #else
+ if (fprintf(statFile, "%17s\t%15d\t%15s\t%15s\t%f\n",
+ inet_ntostring(stIter->first.ip).c_str(),
+ stIter->first.dir,
+ d.c_str(),
+ u.c_str(),
+ stIter->second.cash) < 0)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = string("fprint failed. Message: '");
+ errorStr += strerror(errno);
+ errorStr += "'";
+ printfd(__FILE__, "FILES_STORE::WriteDetailStat - fprintf failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+ #endif
+
+ ++stIter;
+ }
+
+fclose(statFile);
+
+e = chown(fn, storeSettings.GetStatUID(), storeSettings.GetStatGID());
+e += chmod(fn, storeSettings.GetStatMode());
+
+if (e)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ printfd(__FILE__, "FILES_STORE::WriteDetailStat - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::AddMessage(STG_MSG * msg, const string & login) const
+{
+//ðÒÏ×ÅÒÉÔØ ÅÓÌÔØ ÌÉ ÄÉÒÅËÔÏÒÉÑ ÄÌÑ ÓÏÏÂÝÅÎÉÊ. åÓÌÉ ÎÅÔ - ÓÏÚÄÁÔØ.
+//úÁÔÅÍ ÐÏÌÏÖÉÔØ ÓÏÏÂÝÅÎÉÅ Ó ÉÍÅÎÅÍ ÆÁÊÌÁ - ×ÒÅÍÅÎÎOÊ ÍÅÔËÏÊ. úÁÐÉÓÁÔØ ÔÕÄÁ
+//ÔÅËÓÔ É ÐÒÉÏÒÉÔÅÔ.
+
+string fn;
+string dn;
+struct timeval tv;
+FILE * msgFile;
+
+strprintf(&dn, "%s/%s/messages", storeSettings.GetUsersDir().c_str(), login.c_str());
+if (access(dn.c_str(), F_OK) != 0)
+ {
+ if (mkdir(dn.c_str(), 0700) != 0)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Directory \'";
+ errorStr += dn;
+ errorStr += "\' cannot be created.";
+ printfd(__FILE__, "FILES_STORE::AddMessage - mkdir failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+ }
+
+chmod(dn.c_str(), storeSettings.GetConfMode() | S_IXUSR);
+
+gettimeofday(&tv, NULL);
+
+msg->header.id = ((long long)tv.tv_sec) * 1000000 + ((long long)tv.tv_usec);
+strprintf(&fn, "%s/%lld", dn.c_str(), msg->header.id);
+
+msgFile = fopen (fn.c_str(), "wt");
+
+if (!msgFile)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "File \'";
+ errorStr += fn;
+ errorStr += "\' cannot be writen.";
+ printfd(__FILE__, "FILES_STORE::AddMessage - fopen failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+fclose(msgFile);
+return EditMessage(*msg, login);
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::EditMessage(const STG_MSG & msg, const string & login) const
+{
+//ðÒÏ×ÅÒÉÔØ ÅÓÌÔØ ÌÉ ÄÉÒÅËÔÏÒÉÑ ÄÌÑ ÓÏÏÂÝÅÎÉÊ. åÓÌÉ ÎÅÔ - ÓÏÚÄÁÔØ.
+//úÁÔÅÍ ÐÏÌÏÖÉÔØ ÓÏÏÂÝÅÎÉÅ Ó ÉÍÅÎÅÍ ÆÁÊÌÁ - ×ÒÅÍÅÎÎOÊ ÍÅÔËÏÊ. úÁÐÉÓÁÔØ ÔÕÄÁ
+//ÔÅËÓÔ É ÐÒÉÏÒÉÔÅÔ.
+
+string fn;
+
+FILE * msgFile;
+strprintf(&fn, "%s/%s/messages/%lld", storeSettings.GetUsersDir().c_str(), login.c_str(), msg.header.id);
+
+if (access(fn.c_str(), F_OK) != 0)
+ {
+ string idstr;
+ x2str(msg.header.id, idstr);
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Message for user \'";
+ errorStr += login + "\' with ID \'";
+ errorStr += idstr + "\' does not exist.";
+ printfd(__FILE__, "FILES_STORE::EditMessage - %s\n", errorStr.c_str());
+ return -1;
+ }
+
+msgFile = fopen(fn.c_str(), "wt");
+if (!msgFile)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "File \'" + fn + "\' cannot be writen.";
+ printfd(__FILE__, "FILES_STORE::EditMessage - fopen failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+
+bool res = true;
+res &= (fprintf(msgFile, "%d\n", msg.header.type) >= 0);
+res &= (fprintf(msgFile, "%u\n", msg.header.lastSendTime) >= 0);
+res &= (fprintf(msgFile, "%u\n", msg.header.creationTime) >= 0);
+res &= (fprintf(msgFile, "%u\n", msg.header.showTime) >= 0);
+res &= (fprintf(msgFile, "%d\n", msg.header.repeat) >= 0);
+res &= (fprintf(msgFile, "%u\n", msg.header.repeatPeriod) >= 0);
+res &= (fprintf(msgFile, "%s", msg.text.c_str()) >= 0);
+
+if (!res)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = string("fprintf failed. Message: '") + strerror(errno) + "'";
+ printfd(__FILE__, "FILES_STORE::EditMessage - fprintf failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+
+fclose(msgFile);
+
+chmod(fn.c_str(), storeSettings.GetConfMode());
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::GetMessage(uint64_t id, STG_MSG * msg, const string & login) const
+{
+string fn;
+strprintf(&fn, "%s/%s/messages/%lld", storeSettings.GetUsersDir().c_str(), login.c_str(), id);
+msg->header.id = id;
+return ReadMessage(fn, &msg->header, &msg->text);
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::DelMessage(uint64_t id, const string & login) const
+{
+string fn;
+strprintf(&fn, "%s/%s/messages/%lld", storeSettings.GetUsersDir().c_str(), login.c_str(), id);
+
+return unlink(fn.c_str());
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::GetMessageHdrs(vector<STG_MSG_HDR> * hdrsList, const string & login) const
+{
+vector<string> messages;
+string dn;
+dn = storeSettings.GetUsersDir() + "/" + login + "/messages/";
+GetFilesList(&messages, dn, S_IFREG, "");
+
+//hdrsList->resize(messages.size());
+
+for (unsigned i = 0; i < messages.size(); i++)
+ {
+ unsigned long long id = 0;
+
+ if (str2x(messages[i].c_str(), id))
+ {
+ if (unlink((dn + messages[i]).c_str()))
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = string("unlink failed. Message: '") + strerror(errno) + "'";
+ printfd(__FILE__, "FILES_STORE::GetMessageHdrs - unlink failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+ continue;
+ }
+
+ STG_MSG_HDR hdr;
+ if (ReadMessage(dn + messages[i], &hdr, NULL))
+ {
+ return -1;
+ }
+
+ if (hdr.repeat < 0)
+ {
+ if (unlink((dn + messages[i]).c_str()))
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = string("unlink failed. Message: '") + strerror(errno) + "'";
+ printfd(__FILE__, "FILES_STORE::GetMessageHdrs - unlink failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+ continue;
+ }
+
+ hdr.id = id;
+ hdrsList->push_back(hdr);
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::ReadMessage(const string & fileName,
+ STG_MSG_HDR * hdr,
+ string * text) const
+{
+FILE * msgFile;
+msgFile = fopen(fileName.c_str(), "rt");
+if (!msgFile)
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "File \'";
+ errorStr += fileName;
+ errorStr += "\' cannot be openned.";
+ printfd(__FILE__, "FILES_STORE::ReadMessage - fopen failed. Message: '%s'\n", strerror(errno));
+ return -1;
+ }
+char p[20];
+unsigned * d[6];
+d[0] = &hdr->type;
+d[1] = &hdr->lastSendTime;
+d[2] = &hdr->creationTime;
+d[3] = &hdr->showTime;
+d[4] = (unsigned*)(&hdr->repeat);
+d[5] = &hdr->repeatPeriod;
+
+memset(p, 0, sizeof(p));
+
+for (int pos = 0; pos < 6; pos++)
+ {
+ if (fgets(p, sizeof(p) - 1, msgFile) == NULL) {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Cannot read file \'";
+ errorStr += fileName;
+ errorStr += "\'. Missing data.";
+ printfd(__FILE__, "FILES_STORE::ReadMessage - cannot read file (missing data)\n");
+ printfd(__FILE__, "FILES_STORE::ReadMessage - position: %d\n", pos);
+ fclose(msgFile);
+ return -1;
+ }
+
+ char * ep;
+ ep = strrchr(p, '\r');
+ if (ep) *ep = 0;
+ ep = strrchr(p, '\n');
+ if (ep) *ep = 0;
+
+ if (feof(msgFile))
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Cannot read file \'";
+ errorStr += fileName;
+ errorStr += "\'. Missing data.";
+ printfd(__FILE__, "FILES_STORE::ReadMessage - cannot read file (feof)\n");
+ printfd(__FILE__, "FILES_STORE::ReadMessage - position: %d\n", pos);
+ fclose(msgFile);
+ return -1;
+ }
+
+ if (str2x(p, *(d[pos])))
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ errorStr = "Cannot read file \'";
+ errorStr += fileName;
+ errorStr += "\'. Incorrect value. \'";
+ errorStr += p;
+ errorStr += "\'";
+ printfd(__FILE__, "FILES_STORE::ReadMessage - incorrect value\n");
+ fclose(msgFile);
+ return -1;
+ }
+ }
+
+char txt[2048];
+memset(txt, 0, sizeof(txt));
+if (text)
+ {
+ text->erase(text->begin(), text->end());
+ while (!feof(msgFile))
+ {
+ txt[0] = 0;
+ if (fgets(txt, sizeof(txt) - 1, msgFile) == NULL) {
+ break;
+ }
+
+ (*text) += txt;
+ }
+ }
+//fprintf(msgFile, "%s\n", msg.text.c_str());
+fclose(msgFile);
+return 0;
+}
+//-----------------------------------------------------------------------------
+
--- /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>
+ */
+
+/*
+ $Revision: 1.22 $
+ $Date: 2010/01/19 11:06:53 $
+ $Author: faust $
+ */
+
+
+#ifndef FILE_STORE_H
+#define FILE_STORE_H
+
+#include <string>
+#include <sys/types.h>
+
+#include "base_settings.h"
+#include "base_store.h"
+#include "conffiles.h"
+#include "user_traff.h"
+
+using namespace std;
+//-----------------------------------------------------------------------------
+extern "C" BASE_STORE * GetStore();
+//-----------------------------------------------------------------------------
+class FILES_STORE_SETTINGS//: public BASE_SETTINGS
+{
+public:
+ FILES_STORE_SETTINGS();
+ virtual ~FILES_STORE_SETTINGS();
+ virtual int ParseSettings(const MODULE_SETTINGS & s);
+ virtual const string & GetStrError() const;
+
+ string GetWorkDir() const;
+ string GetUsersDir() const;
+ string GetAdminsDir() const;
+ string GetTariffsDir() const;
+
+ mode_t GetStatMode() const;
+ mode_t GetStatModeDir() const;
+ uid_t GetStatUID() const;
+ gid_t GetStatGID() const;
+
+ mode_t GetConfMode() const;
+ mode_t GetConfModeDir() const;
+ uid_t GetConfUID() const;
+ gid_t GetConfGID() const;
+
+ mode_t GetLogMode() const;
+ uid_t GetLogUID() const;
+ gid_t GetLogGID() const;
+
+ bool GetRemoveBak() const;
+ bool GetReadBak() const;
+
+private:
+ const MODULE_SETTINGS * settings;
+
+ int User2UID(const char * user, uid_t * uid);
+ int Group2GID(const char * gr, gid_t * gid);
+ int Str2Mode(const char * str, mode_t * mode);
+ int ParseOwner(const vector<PARAM_VALUE> & moduleParams, const string & owner, uid_t * uid);
+ int ParseGroup(const vector<PARAM_VALUE> & moduleParams, const string & group, uid_t * uid);
+ int ParseMode(const vector<PARAM_VALUE> & moduleParams, const string & modeStr, mode_t * mode);
+ int ParseYesNo(const string & value, bool * val);
+ string errorStr;
+
+ string workDir;
+ string usersDir;
+ string adminsDir;
+ string tariffsDir;
+
+ mode_t statMode;
+ uid_t statUID;
+ gid_t statGID;
+
+ mode_t confMode;
+ uid_t confUID;
+ gid_t confGID;
+
+ mode_t userLogMode;
+ uid_t userLogUID;
+ gid_t userLogGID;
+
+ bool removeBak;
+ bool readBak;
+};
+//-----------------------------------------------------------------------------
+class FILES_STORE: public BASE_STORE
+{
+public:
+ FILES_STORE();
+ virtual ~FILES_STORE();
+ virtual const string & GetStrError() const;
+
+ //User
+ virtual int GetUsersList(vector<string> * usersList) const;
+ virtual int AddUser(const string & login) const;
+ virtual int DelUser(const string & login) const;
+ virtual int SaveUserStat(const USER_STAT & stat, const string & login) const;
+ virtual int SaveUserConf(const USER_CONF & conf, const string & login) const;
+
+ virtual int RestoreUserStat(USER_STAT * stat, const string & login) const;
+ virtual int RestoreUserConf(USER_CONF * conf, const string & login) const;
+
+ virtual int WriteUserChgLog(const string & login,
+ const string & admLogin,
+ uint32_t admIP,
+ const string & paramName,
+ const string & oldValue,
+ const string & newValue,
+ const string & message = "") const;
+ virtual int WriteUserConnect(const string & login, uint32_t ip) const;
+ virtual int WriteUserDisconnect(const string & login,
+ const DIR_TRAFF & up,
+ const DIR_TRAFF & down,
+ const DIR_TRAFF & sessionUp,
+ const DIR_TRAFF & sessionDown,
+ double cash,
+ double freeMb,
+ const std::string & reason) const;
+
+ virtual int WriteDetailedStat(const map<IP_DIR_PAIR, STAT_NODE> * statTree,
+ time_t lastStat,
+ const string & login) const;
+
+ virtual int AddMessage(STG_MSG * msg, const string & login) const;
+ virtual int EditMessage(const STG_MSG & msg, const string & login) const;
+ virtual int GetMessage(uint64_t id, STG_MSG * msg, const string & login) const;
+ virtual int DelMessage(uint64_t id, const string & login) const;
+ virtual int GetMessageHdrs(vector<STG_MSG_HDR> * hdrsList, const string & login) const;
+ virtual int ReadMessage(const string & fileName,
+ STG_MSG_HDR * hdr,
+ string * text) const;
+
+ virtual int SaveMonthStat(const USER_STAT & stat, int month, int year, const string & login) const;
+
+ //Admin
+ virtual int GetAdminsList(vector<string> * adminsList) const;
+ virtual int AddAdmin(const string & login) const;
+ virtual int DelAdmin(const string & login) const;
+ virtual int RestoreAdmin(ADMIN_CONF * ac, const string & login) const;
+ virtual int SaveAdmin(const ADMIN_CONF & ac) const;
+
+ //Tariff
+ virtual int GetTariffsList(vector<string> * tariffsList) const;
+ virtual int AddTariff(const string & name) const;
+ virtual int DelTariff(const string & name) const;
+ virtual int SaveTariff(const TARIFF_DATA & td, const string & tariffName) const;
+ virtual int RestoreTariff(TARIFF_DATA * td, const string & tariffName) const;
+
+ //Corparation
+ virtual int GetCorpsList(vector<string> *) const {return 0;};
+ virtual int SaveCorp(const CORP_CONF &) const {return 0;};
+ virtual int RestoreCorp(CORP_CONF *, const string &) const {return 0;};
+ virtual int AddCorp(const string &) const {return 0;};
+ virtual int DelCorp(const string &) const {return 0;};
+
+ // Services
+ virtual int GetServicesList(vector<string> *) const {return 0;};
+ virtual int SaveService(const SERVICE_CONF &) const {return 0;};
+ virtual int RestoreService(SERVICE_CONF *, const string &) const {return 0;};
+ virtual int AddService(const string &) const {return 0;};
+ virtual int DelService(const string &) const {return 0;};
+
+ //virtual BASE_SETTINGS * GetStoreSettings();
+ virtual void SetSettings(const MODULE_SETTINGS & s);
+ virtual int ParseSettings();
+ virtual const string & GetVersion() const;
+
+private:
+ virtual int RestoreUserStat(USER_STAT * stat, const string & login, const string & fileName) const;
+ virtual int RestoreUserConf(USER_CONF * conf, const string & login, const string & fileName) const;
+
+ virtual int WriteLogString(const string & str, const string & login) const;
+ virtual int WriteLog2String(const string & str, const string & login) const;
+ int RemoveDir(const char * path) const;
+ int GetFilesList(vector<string> * filesList, const string & directory, mode_t mode, const string & ext) const;
+ mutable string errorStr;
+ string version;
+ FILES_STORE_SETTINGS storeSettings;
+ MODULE_SETTINGS settings;
+ mutable pthread_mutex_t mutex;
+};
+//-----------------------------------------------------------------------------
+
+#endif //FILE_STORE_H
+
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.9 2008/12/04 17:15:53 faust Exp $
+###############################################################################
+
+include ../../../../../Makefile.conf
+
+DEFS += -DIBPP_LINUX
+
+PROG = mod_store_firebird.so
+
+SRCS = ./firebird_store.cpp \
+ ./firebird_store_admins.cpp \
+ ./firebird_store_corporations.cpp \
+ ./firebird_store_messages.cpp \
+ ./firebird_store_services.cpp \
+ ./firebird_store_tariffs.cpp \
+ ./firebird_store_users.cpp \
+ ./firebird_store_utils.cpp
+
+STGLIBS = -libpp -lstg_common
+
+include ../../Makefile.in
+
--- /dev/null
+firebird_store.o: firebird_store.cpp firebird_store.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/base_store.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_stat.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/resetable.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_traff.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_const.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_locker.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/noncopyable.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_ips.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/common.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/corp_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/service_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/admin_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/tariff_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/base_settings.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_message.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_locker.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/ibpp.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h Makefile ../../../../../Makefile.conf
+ $(CC) -c $< -g3 -W -Wall -I/usr/local/include -DARCH_LE -fPIC -I /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include -DDEBUG -DLINUX -DIBPP_LINUX
+firebird_store_admins.o: firebird_store_admins.cpp firebird_store.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/base_store.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_stat.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/resetable.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_traff.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_const.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_locker.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/noncopyable.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_ips.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/common.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/corp_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/service_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/admin_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/tariff_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/base_settings.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_message.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_locker.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/ibpp.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/blowfish.h Makefile ../../../../../Makefile.conf
+ $(CC) -c $< -g3 -W -Wall -I/usr/local/include -DARCH_LE -fPIC -I /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include -DDEBUG -DLINUX -DIBPP_LINUX
+firebird_store_corporations.o: firebird_store_corporations.cpp \
+ firebird_store.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/base_store.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_stat.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/resetable.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_traff.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_const.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_locker.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/noncopyable.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_ips.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/common.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/corp_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/service_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/admin_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/tariff_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/base_settings.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_message.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_locker.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/ibpp.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h Makefile ../../../../../Makefile.conf
+ $(CC) -c $< -g3 -W -Wall -I/usr/local/include -DARCH_LE -fPIC -I /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include -DDEBUG -DLINUX -DIBPP_LINUX
+firebird_store_messages.o: firebird_store_messages.cpp firebird_store.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/base_store.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_stat.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/resetable.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_traff.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_const.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_locker.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/noncopyable.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_ips.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/common.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/corp_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/service_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/admin_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/tariff_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/base_settings.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_message.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_locker.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/ibpp.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h Makefile ../../../../../Makefile.conf
+ $(CC) -c $< -g3 -W -Wall -I/usr/local/include -DARCH_LE -fPIC -I /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include -DDEBUG -DLINUX -DIBPP_LINUX
+firebird_store_services.o: firebird_store_services.cpp firebird_store.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/base_store.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_stat.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/resetable.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_traff.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_const.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_locker.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/noncopyable.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_ips.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/common.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/corp_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/service_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/admin_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/tariff_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/base_settings.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_message.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_locker.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/ibpp.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h Makefile ../../../../../Makefile.conf
+ $(CC) -c $< -g3 -W -Wall -I/usr/local/include -DARCH_LE -fPIC -I /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include -DDEBUG -DLINUX -DIBPP_LINUX
+firebird_store_tariffs.o: firebird_store_tariffs.cpp firebird_store.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/base_store.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_stat.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/resetable.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_traff.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_const.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_locker.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/noncopyable.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_ips.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/common.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/corp_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/service_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/admin_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/tariff_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/base_settings.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_message.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_locker.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/ibpp.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h Makefile ../../../../../Makefile.conf
+ $(CC) -c $< -g3 -W -Wall -I/usr/local/include -DARCH_LE -fPIC -I /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include -DDEBUG -DLINUX -DIBPP_LINUX
+firebird_store_users.o: firebird_store_users.cpp \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_const.h \
+ firebird_store.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/base_store.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_stat.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/resetable.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_traff.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_const.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_locker.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/noncopyable.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_ips.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/common.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/corp_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/service_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/admin_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/tariff_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/base_settings.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_message.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_locker.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/ibpp.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h Makefile ../../../../../Makefile.conf
+ $(CC) -c $< -g3 -W -Wall -I/usr/local/include -DARCH_LE -fPIC -I /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include -DDEBUG -DLINUX -DIBPP_LINUX
+firebird_store_utils.o: firebird_store_utils.cpp firebird_store.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/base_store.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_stat.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/resetable.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_traff.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_const.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_locker.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/noncopyable.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_ips.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/common.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/corp_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/service_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/admin_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/tariff_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/base_settings.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_message.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_locker.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/ibpp.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h Makefile ../../../../../Makefile.conf
+ $(CC) -c $< -g3 -W -Wall -I/usr/local/include -DARCH_LE -fPIC -I /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include -DDEBUG -DLINUX -DIBPP_LINUX
--- /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>
+ */
+
+/*
+ * This file contains a realization of a base firebird-storage plugin class
+ *
+ * $Revision: 1.18 $
+ * $Date: 2010/01/08 16:00:45 $
+ *
+ */
+
+#include <string>
+#include <vector>
+#include <algorithm>
+
+using namespace std;
+
+#include "firebird_store.h"
+#include "ibpp.h"
+
+class FIREBIRD_STORE_CREATOR
+{
+public:
+ FIREBIRD_STORE_CREATOR()
+ : frb(new FIREBIRD_STORE())
+ {
+ };
+ ~FIREBIRD_STORE_CREATOR()
+ {
+ delete frb;
+ };
+ FIREBIRD_STORE * GetStore() { return frb; };
+private:
+ FIREBIRD_STORE * frb;
+} frsc;
+
+//-----------------------------------------------------------------------------
+BASE_STORE * GetStore()
+{
+return frsc.GetStore();
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+FIREBIRD_STORE::FIREBIRD_STORE()
+{
+db_server = "localhost";
+db_database = "/var/stg/stargazer.fdb";
+db_user = "stg";
+db_password = "123456";
+version = "firebird_store v.1.4";
+pthread_mutex_init(&mutex, NULL);
+
+// Advanced settings defaults
+
+til = IBPP::ilConcurrency;
+tlr = IBPP::lrWait;
+}
+//-----------------------------------------------------------------------------
+FIREBIRD_STORE::~FIREBIRD_STORE()
+{
+db->Disconnect();
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::ParseSettings()
+{
+vector<PARAM_VALUE>::iterator i;
+string s;
+
+for(i = settings.moduleParams.begin(); i != settings.moduleParams.end(); ++i)
+ {
+ s = i->param;
+ transform(s.begin(), s.end(), s.begin(), ToLower());
+ if (s == "server")
+ {
+ db_server = *(i->value.begin());
+ }
+ if (s == "database")
+ {
+ db_database = *(i->value.begin());
+ }
+ if (s == "user")
+ {
+ db_user = *(i->value.begin());
+ }
+ if (s == "password")
+ {
+ db_password = *(i->value.begin());
+ }
+
+ // Advanced settings block
+
+ if (s == "isolationLevel")
+ {
+ if (*(i->value.begin()) == "Concurrency")
+ {
+ til = IBPP::ilConcurrency;
+ }
+ else if (*(i->value.begin()) == "DirtyRead")
+ {
+ til = IBPP::ilReadDirty;
+ }
+ else if (*(i->value.begin()) == "ReadCommitted")
+ {
+ til = IBPP::ilReadCommitted;
+ }
+ else if (*(i->value.begin()) == "Consistency")
+ {
+ til = IBPP::ilConsistency;
+ }
+ }
+ if (s == "lockResolution")
+ {
+ if (*(i->value.begin()) == "Wait")
+ {
+ tlr = IBPP::lrWait;
+ }
+ else if (*(i->value.begin()) == "NoWait")
+ {
+ tlr = IBPP::lrNoWait;
+ }
+ }
+ }
+
+try
+ {
+ db = IBPP::DatabaseFactory(db_server, db_database, db_user, db_password, "", "KOI8U", "");
+ db->Connect();
+ }
+catch (IBPP::Exception & ex)
+ {
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
--- /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>
+ */
+
+/*
+ * Firebird storage class definition
+ *
+ * $Revision: 1.13 $
+ * $Date: 2010/01/19 11:07:25 $
+ *
+ */
+
+#ifndef FIREBIRD_STORE_H
+#define FIREBIRD_STORE_H
+
+#include <string>
+#include <vector>
+#include <map>
+
+#include "base_store.h"
+#include "stg_locker.h"
+#include "ibpp.h"
+//#include "firebird_database.h"
+
+struct ToLower
+{
+char operator() (char c) const { return std::tolower(c); }
+};
+
+extern "C" BASE_STORE * GetStore();
+
+class FIREBIRD_STORE : public BASE_STORE {
+public:
+ FIREBIRD_STORE();
+ virtual ~FIREBIRD_STORE();
+
+ int GetUsersList(std::vector<std::string> * usersList) const;
+ int AddUser(const std::string & login) const;
+ int DelUser(const std::string & login) const;
+ int SaveUserStat(const USER_STAT & stat, const std::string & login) const;
+ int SaveUserConf(const USER_CONF & conf, const std::string & login) const;
+ int RestoreUserStat(USER_STAT * stat, const std::string & login) const;
+ int RestoreUserConf(USER_CONF * conf, const std::string & login) const;
+ int WriteUserChgLog(const std::string & login,
+ const std::string & admLogin,
+ uint32_t admIP,
+ const std::string & paramName,
+ const std::string & oldValue,
+ const std::string & newValue,
+ const std::string & message) const;
+ int WriteUserConnect(const std::string & login, uint32_t ip) const;
+ int WriteUserDisconnect(const std::string & login,
+ const DIR_TRAFF & up,
+ const DIR_TRAFF & down,
+ const DIR_TRAFF & sessionUp,
+ const DIR_TRAFF & sessionDown,
+ double cash,
+ double freeMb,
+ const std::string & reason) const;
+ int WriteDetailedStat(const std::map<IP_DIR_PAIR, STAT_NODE> * statTree,
+ time_t lastStat,
+ const std::string & login) const;
+
+ int AddMessage(STG_MSG * msg, const std::string & login) const;
+ int EditMessage(const STG_MSG & msg, const std::string & login) const;
+ int GetMessage(uint64_t id, STG_MSG * msg, const std::string & login) const;
+ int DelMessage(uint64_t id, const std::string & login) const;
+ int GetMessageHdrs(std::vector<STG_MSG_HDR> * hdrsList, const std::string & login) const;
+
+ int SaveMonthStat(const USER_STAT & stat, int month, int year, const std::string & login) const;
+
+ int GetAdminsList(std::vector<std::string> * adminsList) const;
+ int SaveAdmin(const ADMIN_CONF & ac) const;
+ int RestoreAdmin(ADMIN_CONF * ac, const std::string & login) const;
+ int AddAdmin(const std::string & login) const;
+ int DelAdmin(const std::string & login) const;
+
+ int GetTariffsList(std::vector<std::string> * tariffsList) const;
+ int AddTariff(const std::string & name) const;
+ int DelTariff(const string & name) const;
+ int SaveTariff(const TARIFF_DATA & td, const std::string & tariffName) const;
+ int RestoreTariff(TARIFF_DATA * td, const std::string & tariffName) const;
+
+ int GetCorpsList(std::vector<std::string> * corpsList) const;
+ int SaveCorp(const CORP_CONF & cc) const;
+ int RestoreCorp(CORP_CONF * cc, const std::string & name) const;
+ int AddCorp(const std::string & name) const;
+ int DelCorp(const std::string & name) const;
+
+ inline void SetSettings(const MODULE_SETTINGS & s) { settings = s; };
+ int ParseSettings();
+
+ inline const string & GetStrError() const { return strError; };
+
+ inline const string & GetVersion() const { return version; };
+
+ int GetServicesList(std::vector<std::string> * servicesList) const;
+ int SaveService(const SERVICE_CONF & sc) const;
+ int RestoreService(SERVICE_CONF * sc, const std::string & name) const;
+ int AddService(const std::string & name) const;
+ int DelService(const std::string & name) const;
+private:
+ std::string version;
+ mutable std::string strError;
+ mutable std::string db_server, db_database, db_user, db_password;
+ MODULE_SETTINGS settings;
+ mutable IBPP::Database db;
+ mutable pthread_mutex_t mutex;
+ mutable IBPP::TIL til;
+ mutable IBPP::TLR tlr;
+
+ int SaveStat(const USER_STAT & stat, const std::string & login, int year = 0, int month = 0) const;
+
+ time_t ts2time_t(const IBPP::Timestamp & ts) const;
+ void time_t2ts(time_t t, IBPP::Timestamp * ts) const;
+ void ym2date(int year, int month, IBPP::Date * date) const;
+};
+
+#endif //FIREBIRD_STORE_H
+
--- /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>
+ */
+
+/*
+ * Administrators manipulation methods
+ *
+ * $Revision: 1.11 $
+ * $Date: 2008/12/04 17:10:06 $
+ *
+ */
+
+#include <string>
+#include <vector>
+
+using namespace std;
+
+#include "firebird_store.h"
+#include "ibpp.h"
+#include "blowfish.h"
+
+#define adm_enc_passwd "cjeifY8m3"
+
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::GetAdminsList(vector<string> * adminsList) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+string login;
+
+try
+ {
+ tr->Start();
+ st->Execute("select login from tb_admins");
+ while (st->Fetch())
+ {
+ st->Get(1, login);
+ adminsList->push_back(login);
+ }
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::SaveAdmin(const ADMIN_CONF & ac) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+char encodedPass[2 * ADM_PASSWD_LEN + 2];
+char cryptedPass[ADM_PASSWD_LEN + 1];
+char adminPass[ADM_PASSWD_LEN + 1];
+BLOWFISH_CTX ctx;
+
+memset(cryptedPass, 0, ADM_PASSWD_LEN + 1);
+strncpy(adminPass, ac.password.c_str(), ADM_PASSWD_LEN);
+EnDecodeInit(adm_enc_passwd, sizeof(adm_enc_passwd), &ctx);
+
+for (int i = 0; i < ADM_PASSWD_LEN / 8; i++)
+ EncodeString(cryptedPass + 8 * i, adminPass + 8 * i, &ctx);
+
+cryptedPass[ADM_PASSWD_LEN] = 0;
+Encode12(encodedPass, cryptedPass, ADM_PASSWD_LEN);
+
+try
+ {
+ tr->Start();
+ st->Prepare("update tb_admins set passwd=?, \
+ chg_conf=?, \
+ chg_password=?, \
+ chg_stat=?, \
+ chg_cash=?, \
+ usr_add_del=?, \
+ chg_tariff=?, \
+ chg_admin=? \
+ where login=?");
+ st->Set(1, encodedPass);
+ st->Set(2, static_cast<int16_t>(ac.priv.userConf));
+ st->Set(3, static_cast<int16_t>(ac.priv.userPasswd));
+ st->Set(4, static_cast<int16_t>(ac.priv.userStat));
+ st->Set(5, static_cast<int16_t>(ac.priv.userCash));
+ st->Set(6, static_cast<int16_t>(ac.priv.userAddDel));
+ st->Set(7, static_cast<int16_t>(ac.priv.tariffChg));
+ st->Set(8, static_cast<int16_t>(ac.priv.adminChg));
+ st->Set(9, ac.login);
+ st->Execute();
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::RestoreAdmin(ADMIN_CONF * ac, const string & login) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+char cryptedPass[ADM_PASSWD_LEN + 1];
+char adminPass[ADM_PASSWD_LEN + 1];
+BLOWFISH_CTX ctx;
+
+try
+ {
+ tr->Start();
+ st->Prepare("select * from tb_admins where login = ?");
+ st->Set(1, login);
+ st->Execute();
+ if (st->Fetch())
+ {
+ st->Get(2, ac->login);
+ st->Get(3, ac->password);
+ st->Get(4, (int16_t &)ac->priv.userConf);
+ st->Get(5, (int16_t &)ac->priv.userPasswd);
+ st->Get(6, (int16_t &)ac->priv.userStat);
+ st->Get(7, (int16_t &)ac->priv.userCash);
+ st->Get(8, (int16_t &)ac->priv.userAddDel);
+ st->Get(9, (int16_t &)ac->priv.tariffChg);
+ st->Get(10, (int16_t &)ac->priv.adminChg);
+ }
+ else
+ {
+ strError = "Admin \"" + login + "\" not found in database";
+ printfd(__FILE__, "Admin '%s' not found in database\n", login.c_str());
+ tr->Rollback();
+ return -1;
+ }
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+if (ac->password == "")
+ {
+ return 0;
+ }
+
+Decode21(cryptedPass, ac->password.c_str());
+EnDecodeInit(adm_enc_passwd, sizeof(adm_enc_passwd), &ctx);
+for (int i = 0; i < ADM_PASSWD_LEN / 8; i++)
+ {
+ DecodeString(adminPass + 8 * i, cryptedPass + 8 * i, &ctx);
+ }
+ac->password = adminPass;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::AddAdmin(const string & login) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("insert into tb_admins(login, \
+ passwd, \
+ chg_conf, \
+ chg_password, \
+ chg_stat, \
+ chg_cash, \
+ usr_add_del, \
+ chg_tariff, \
+ chg_admin, \
+ chg_service, \
+ chg_corporation) \
+ values (?, '', 0, 0, 0, 0, 0, 0, 0, 0, 0)");
+ st->Set(1, login);
+ st->Execute();
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::DelAdmin(const string & login) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("delete from tb_admins where login = ?");
+ st->Set(1, login);
+ st->Execute();
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
--- /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>
+ */
+
+/*
+ * Corporations manipulation methods
+ *
+ * $Revision: 1.5 $
+ * $Date: 2007/12/23 13:39:59 $
+ *
+ */
+
+#include "firebird_store.h"
+#include "ibpp.h"
+
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::GetCorpsList(vector<string> * corpsList) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+string name;
+
+try
+ {
+ tr->Start();
+ st->Execute("select name from tb_corporations");
+ while (st->Fetch())
+ {
+ st->Get(1, name);
+ corpsList->push_back(name);
+ }
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::SaveCorp(const CORP_CONF & cc) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Execute("update tb_corporations set cash = ? where name = ?");
+ st->Set(1, cc.cash);
+ st->Set(2, cc.name);
+ st->Execute();
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::RestoreCorp(CORP_CONF * cc, const string & name) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("select cash from tb_corporations where name = ?");
+ st->Set(1, name);
+ st->Execute();
+ if (st->Fetch())
+ {
+ st->Get(1, cc->cash);
+ }
+ else
+ {
+ strError = "Corporation \"" + name + "\" not found in database";
+ tr->Rollback();
+ printfd(__FILE__, "Corporation '%s' not found in database\n", name.c_str());
+ return -1;
+ }
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::AddCorp(const string & name) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("insert into tb_corporations (name, cash), values (?, 0)");
+ st->Set(1, name);
+ st->Execute();
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::DelCorp(const string & name) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("delete from tb_corporations where name = ?");
+ st->Set(1, name);
+ st->Execute();
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
--- /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>
+ */
+
+
+/*
+ * Messages manipualtion methods
+ *
+ * $Revision: 1.10 $
+ * $Date: 2009/03/03 16:16:23 $
+ *
+ */
+
+#include <sstream>
+
+#include "firebird_store.h"
+#include "ibpp.h"
+
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::AddMessage(STG_MSG * msg, const string & login) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("execute procedure sp_add_message(NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
+ st->Set(1, login);
+ st->Set(2, (int32_t)msg->header.ver);
+ st->Set(3, (int32_t)msg->header.type);
+ st->Set(4, (int32_t)msg->header.lastSendTime);
+ st->Set(5, (int32_t)msg->header.creationTime);
+ st->Set(6, (int32_t)msg->header.showTime);
+ st->Set(7, msg->header.repeat);
+ st->Set(8, (int32_t)msg->header.repeatPeriod);
+ st->Set(9, msg->text);
+ st->Execute();
+ st->Get(1, (int64_t &)msg->header.id);
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::EditMessage(const STG_MSG & msg,
+ const string & login) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("execute procedure sp_add_message(?, ?, ?, ?, ?, ?, ?, ?, ?)");
+ st->Set(1, (int64_t)msg.header.id);
+ st->Set(2, login);
+ st->Set(3, (int32_t)msg.header.ver);
+ st->Set(4, (int32_t)msg.header.type);
+ st->Set(5, (int32_t)msg.header.lastSendTime);
+ st->Set(6, (int32_t)msg.header.creationTime);
+ st->Set(7, (int32_t)msg.header.showTime);
+ st->Set(8, msg.header.repeat);
+ st->Set(9, (int32_t)msg.header.repeatPeriod);
+ st->Set(10, msg.text.c_str());
+ st->Execute();
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::GetMessage(uint64_t id,
+ STG_MSG * msg,
+ const string &) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("select * from tb_messages where pk_message = ?");
+ st->Set(1, (int64_t)id);
+ st->Execute();
+ if (st->Fetch())
+ {
+ st->Get(1, (int64_t &)msg->header.id);
+ st->Get(3, (int32_t &)msg->header.ver);
+ st->Get(4, (int32_t &)msg->header.type);
+ st->Get(5, (int32_t &)msg->header.lastSendTime);
+ st->Get(6, (int32_t &)msg->header.creationTime);
+ st->Get(7, (int32_t &)msg->header.showTime);
+ st->Get(8, msg->header.repeat);
+ st->Get(9, (int32_t &)msg->header.repeatPeriod);
+ st->Get(10, msg->text);
+ }
+ else
+ {
+ strprintf(&strError, "Message with id = %d not found in database", id);
+ printfd(__FILE__, "Message with id - %d not found in database\n", id);
+ tr->Rollback();
+ return -1;
+ }
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::DelMessage(uint64_t id, const string &) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("delete from tb_messages where pk_message = ?");
+ st->Set(1, (int64_t)id);
+ st->Execute();
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::GetMessageHdrs(vector<STG_MSG_HDR> * hdrsList,
+ const string & login) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+STG_MSG_HDR header;
+
+try
+ {
+ tr->Start();
+ st->Prepare("select pk_message, ver, msg_type, \
+ last_send_time, creation_time, \
+ show_time, repeat, repeat_period \
+ from tb_messages where \
+ fk_user = (select pk_user from tb_users where name = ?)");
+ st->Set(1, login);
+ st->Execute();
+ while (st->Fetch())
+ {
+ st->Get(1, (int64_t &)header.id);
+ st->Get(2, (int32_t &)header.ver);
+ st->Get(3, (int32_t &)header.type);
+ st->Get(4, (int32_t &)header.lastSendTime);
+ st->Get(5, (int32_t &)header.creationTime);
+ st->Get(6, (int32_t &)header.showTime);
+ st->Get(7, header.repeat);
+ st->Get(8, (int32_t &)header.repeatPeriod);
+ hdrsList->push_back(header);
+ }
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
--- /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>
+ */
+
+
+/*
+ * Services manipulation methods
+ *
+ * $Revision: 1.6 $
+ * $Date: 2009/05/13 13:19:33 $
+ *
+ */
+
+#include "firebird_store.h"
+#include "ibpp.h"
+
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::GetServicesList(vector<string> * servicesList) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+string name;
+
+try
+ {
+ tr->Start();
+ st->Execute("select name from tb_services");
+ while (st->Fetch())
+ {
+ st->Get(1, name);
+ servicesList->push_back(name);
+ }
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::SaveService(const SERVICE_CONF & sc) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("update tb_services set \
+ comments = ?, \
+ cost = ?, \
+ pay_day = ? \
+ where name = ?");
+ st->Set(1, sc.comment);
+ st->Set(2, sc.cost);
+ st->Set(3, sc.payDay);
+ st->Set(4, sc.name);
+ st->Execute();
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::RestoreService(SERVICE_CONF * sc,
+ const string & name) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("select * from tb_services where name = ?");
+ st->Set(1, name);
+ st->Execute();
+ if (st->Fetch())
+ {
+ st->Get(3, sc->comment);
+ st->Get(4, sc->cost);
+ st->Get(5, sc->payDay);
+ }
+ else
+ {
+ strError = "Service \"" + name + "\" not found in database";
+ printfd(__FILE__, "Service '%s' not found in database\n", name.c_str());
+ tr->Rollback();
+ return -1;
+ }
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::AddService(const string & name) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("insert into tb_services (name, comment, cost, pay_day) \
+ values (?, '', 0, 0)");
+ st->Set(1, name);
+ st->Execute();
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::DelService(const string & name) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("execute procedure sp_delete_service(?)");
+ st->Set(1, name);
+ st->Execute();
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
--- /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>
+ */
+
+/*
+ * Tariffs manipulation methods
+ *
+ * $Revision: 1.5 $
+ * $Date: 2007/12/23 13:39:59 $
+ *
+ */
+
+#include "firebird_store.h"
+#include "ibpp.h"
+
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::GetTariffsList(vector<string> * tariffsList) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+string name;
+
+try
+ {
+ tr->Start();
+ st->Execute("select name from tb_tariffs");
+ while (st->Fetch())
+ {
+ st->Get(1, name);
+ tariffsList->push_back(name);
+ }
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::AddTariff(const string & name) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("execute procedure sp_add_tariff(?, ?)");
+ st->Set(1, name);
+ st->Set(2, DIR_NUM);
+ st->Execute();
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::DelTariff(const string & name) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("execute procedure sp_delete_tariff(?)");
+ st->Set(1, name);
+ st->Execute();
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::SaveTariff(const TARIFF_DATA & td,
+ const string & tariffName) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+int32_t id, i;
+double pda, pdb, pna, pnb;
+int threshold;
+
+try
+ {
+ tr->Start();
+ st->Prepare("select pk_tariff from tb_tariffs where name = ?");
+ st->Set(1, tariffName);
+ st->Execute();
+ if (!st->Fetch())
+ {
+ tr->Rollback();
+ strprintf(&strError, "Tariff \"%s\" not found in database", tariffName.c_str());
+ printfd(__FILE__, "Tariff '%s' not found in database\n", tariffName.c_str());
+ return -1;
+ }
+ st->Get(1, id);
+ st->Close();
+ st->Prepare("update tb_tariffs set \
+ fee = ?, \
+ free = ?, \
+ passive_cost = ?, \
+ traff_type = ? \
+ where pk_tariff = ?");
+ st->Set(1, td.tariffConf.fee);
+ st->Set(2, td.tariffConf.free);
+ st->Set(3, td.tariffConf.passiveCost);
+ st->Set(4, td.tariffConf.traffType);
+ st->Set(5, id);
+ st->Execute();
+ st->Close();
+
+ IBPP::Time tb;
+ IBPP::Time te;
+
+ for(i = 0; i < DIR_NUM; i++)
+ {
+
+ tb.SetTime(td.dirPrice[i].hDay, td.dirPrice[i].mDay, 0);
+ te.SetTime(td.dirPrice[i].hNight, td.dirPrice[i].mNight, 0);
+
+ pda = td.dirPrice[i].priceDayA * 1024 * 1024;
+ pdb = td.dirPrice[i].priceDayB * 1024 * 1024;
+
+ if (td.dirPrice[i].singlePrice)
+ {
+ pna = pda;
+ pnb = pdb;
+ }
+ else
+ {
+ pna = td.dirPrice[i].priceNightA;
+ pnb = td.dirPrice[i].priceNightB;
+ }
+
+ if (td.dirPrice[i].noDiscount)
+ {
+ threshold = 0xffFFffFF;
+ }
+ else
+ {
+ threshold = td.dirPrice[i].threshold;
+ }
+
+ st->Prepare("update tb_tariffs_params set \
+ price_day_a = ?, \
+ price_day_b = ?, \
+ price_night_a = ?, \
+ price_night_b = ?, \
+ threshold = ?, \
+ time_day_begins = ?, \
+ time_day_ends = ? \
+ where fk_tariff = ? and dir_num = ?");
+ st->Set(1, pda);
+ st->Set(2, pdb);
+ st->Set(3, pna);
+ st->Set(4, pnb);
+ st->Set(5, threshold);
+ st->Set(6, tb);
+ st->Set(7, te);
+ st->Set(8, id);
+ st->Set(9, i);
+ st->Execute();
+ st->Close();
+ }
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::RestoreTariff(TARIFF_DATA * td,
+ const string & tariffName) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+int32_t id;
+int16_t dir;
+int i;
+IBPP::Time tb, te;
+int h, m, s;
+
+td->tariffConf.name = tariffName;
+
+try
+ {
+ tr->Start();
+ st->Prepare("select * from tb_tariffs where name = ?");
+ st->Set(1, tariffName);
+ st->Execute();
+ if (!st->Fetch())
+ {
+ strError = "Tariff \"" + tariffName + "\" not found in database";
+ printfd(__FILE__, "Tariff '%s' not found in database\n", tariffName.c_str());
+ tr->Rollback();
+ return -1;
+ }
+ st->Get(1, id);
+ st->Get(3, td->tariffConf.fee);
+ st->Get(4, td->tariffConf.free);
+ st->Get(5, td->tariffConf.passiveCost);
+ st->Get(6, td->tariffConf.traffType);
+ st->Close();
+ st->Prepare("select * from tb_tariffs_params where fk_tariff = ?");
+ st->Set(1, id);
+ st->Execute();
+ i = 0;
+ while (st->Fetch())
+ {
+ i++;
+ if (i > DIR_NUM)
+ {
+ strError = "Too mach params for tariff \"" + tariffName + "\"";
+ printfd(__FILE__, "Too mach params for tariff '%s'\n", tariffName.c_str());
+ tr->Rollback();
+ return -1;
+ }
+ st->Get(3, dir);
+ st->Get(4, td->dirPrice[dir].priceDayA);
+ td->dirPrice[dir].priceDayA /= 1024*1024;
+ st->Get(5, td->dirPrice[dir].priceDayB);
+ td->dirPrice[dir].priceDayB /= 1024*1024;
+ st->Get(6, td->dirPrice[dir].priceNightA);
+ td->dirPrice[dir].priceNightA /= 1024*1024;
+ st->Get(7, td->dirPrice[dir].priceNightB);
+ td->dirPrice[dir].priceNightB /= 1024*1024;
+ st->Get(8, td->dirPrice[dir].threshold);
+ if (td->dirPrice[dir].priceDayA == td->dirPrice[dir].priceNightA &&
+ td->dirPrice[dir].priceDayB == td->dirPrice[dir].priceNightB)
+ {
+ td->dirPrice[dir].singlePrice = true;
+ }
+ else
+ {
+ td->dirPrice[dir].singlePrice = false;
+ }
+ if (td->dirPrice[dir].threshold == (int)0xffFFffFF)
+ {
+ td->dirPrice[dir].noDiscount = true;
+ }
+ else
+ {
+
+ td->dirPrice[dir].noDiscount = false;
+ }
+ st->Get(9, tb);
+ st->Get(10, te);
+ tb.GetTime(h, m, s);
+ td->dirPrice[dir].hDay = h;
+ td->dirPrice[dir].mDay = m;
+ te.GetTime(h, m, s);
+ td->dirPrice[dir].hNight = h;
+ td->dirPrice[dir].mNight = m;
+ }
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
--- /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>
+ */
+
+/*
+ * User manipulation methods
+ *
+ * $Revision: 1.19 $
+ * $Date: 2010/01/19 11:07:25 $
+ *
+ */
+
+#include "stg_const.h"
+#include "firebird_store.h"
+#include "ibpp.h"
+
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::GetUsersList(vector<string> * usersList) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+string name;
+
+try
+ {
+ tr->Start();
+ st->Execute("select name from tb_users");
+ while (st->Fetch())
+ {
+ st->Get(1, name);
+ usersList->push_back(name);
+ }
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::AddUser(const string & name) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("execute procedure sp_add_user(?, ?)");
+ st->Set(1, name);
+ st->Set(2, DIR_NUM);
+ st->Execute();
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::DelUser(const string & login) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+ {
+ tr->Start();
+ st->Prepare("execute procedure sp_delete_user(?)");
+ st->Set(1, login);
+ st->Execute();
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::SaveUserStat(const USER_STAT & stat,
+ const string & login) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+return SaveStat(stat, login);
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::SaveStat(const USER_STAT & stat,
+ const string & login,
+ int year,
+ int month) const
+{
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+IBPP::Timestamp actTime;
+IBPP::Timestamp addTime;
+IBPP::Date dt;
+int i;
+int32_t sid, uid;
+
+try
+ {
+ tr->Start();
+ st->Prepare("select pk_user from tb_users where name = ?");
+ st->Set(1, login);
+ st->Execute();
+ if (!st->Fetch())
+ {
+ strError = "User \"" + login + "\" not found in database";
+ printfd(__FILE__, "User '%s' not found in database\n", login.c_str());
+ tr->Rollback();
+ return -1;
+ }
+ st->Get(1, uid);
+ st->Close();
+ st->Prepare("select first 1 pk_stat from tb_stats where fk_user = ? order by stats_date desc");
+ st->Set(1, uid);
+ st->Execute();
+ if (!st->Fetch())
+ {
+ tr->Rollback();
+ strError = "No stat info for user \"" + login + "\"";
+ printfd(__FILE__, "No stat info for user '%s'\n", login.c_str());
+ return -1;
+ }
+ st->Get(1, sid);
+ st->Close();
+
+ time_t2ts(stat.lastActivityTime, &actTime);
+ time_t2ts(stat.lastCashAddTime, &addTime);
+ if (year != 0)
+ ym2date(year, month, &dt);
+ else
+ dt.Today();
+
+ st->Prepare("update tb_stats set \
+ cash = ?, \
+ free_mb = ?, \
+ last_activity_time = ?, \
+ last_cash_add = ?, \
+ last_cash_add_time = ?, \
+ passive_time = ?, \
+ stats_date = ? \
+ where pk_stat = ?");
+
+ st->Set(1, stat.cash);
+ st->Set(2, stat.freeMb);
+ st->Set(3, actTime);
+ st->Set(4, stat.lastCashAdd);
+ st->Set(5, addTime);
+ st->Set(6, (int32_t)stat.passiveTime);
+ st->Set(7, dt);
+ st->Set(8, sid);
+
+ st->Execute();
+ st->Close();
+
+ for(i = 0; i < DIR_NUM; i++)
+ {
+ st->Prepare("update tb_stats_traffic set \
+ upload = ?, \
+ download = ? \
+ where fk_stat = ? and dir_num = ?");
+ st->Set(1, (int64_t)stat.up[i]);
+ st->Set(2, (int64_t)stat.down[i]);
+ st->Set(3, sid);
+ st->Set(4, i);
+ st->Execute();
+ st->Close();
+ }
+
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::SaveUserConf(const USER_CONF & conf,
+ const string & login) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+int i;
+int32_t uid;
+IBPP::Timestamp creditExpire;
+vector<string>::const_iterator it;
+
+try
+ {
+ tr->Start();
+ st->Prepare("select pk_user from tb_users where name = ?");
+ st->Set(1, login);
+ st->Execute();
+ if (!st->Fetch())
+ {
+ strError = "User \"" + login + "\" not found in database";
+ printfd(__FILE__, "User '%s' not found in database\n", login.c_str());
+ tr->Rollback();
+ return -1;
+ }
+ st->Get(1, uid);
+ st->Close();
+
+ time_t2ts(conf.creditExpire, &creditExpire);
+
+ st->Prepare("update tb_users set \
+ address = ?, \
+ always_online = ?, \
+ credit = ?, \
+ credit_expire = ?, \
+ disabled = ?, \
+ disabled_detail_stat = ?, \
+ email = ?, \
+ grp = ?, \
+ note = ?, \
+ passive = ?, \
+ passwd = ?, \
+ phone = ?, \
+ fk_tariff = (select pk_tariff from tb_tariffs \
+ where name = ?), \
+ fk_tariff_change = (select pk_tariff from tb_tariffs \
+ where name = ?), \
+ fk_corporation = (select pk_corporation from tb_corporations \
+ where name = ?), \
+ real_name = ? \
+ where pk_user = ?");
+
+ st->Set(1, conf.address);
+ st->Set(2, (bool)conf.alwaysOnline);
+ st->Set(3, conf.credit);
+ st->Set(4, creditExpire);
+ st->Set(5, (bool)conf.disabled);
+ st->Set(6, (bool)conf.disabledDetailStat);
+ st->Set(7, conf.email);
+ st->Set(8, conf.group);
+ st->Set(9, conf.note);
+ st->Set(10, (bool)conf.passive);
+ st->Set(11, conf.password);
+ st->Set(12, conf.phone);
+ st->Set(13, conf.tariffName);
+ st->Set(14, conf.nextTariff);
+ st->Set(15, conf.corp);
+ st->Set(16, conf.realName);
+ st->Set(17, uid);
+
+ st->Execute();
+ st->Close();
+
+ st->Prepare("delete from tb_users_services where fk_user = ?");
+ st->Set(1, uid);
+ st->Execute();
+ st->Close();
+
+ st->Prepare("insert into tb_users_services (fk_user, fk_service) \
+ values (?, (select pk_service from tb_services \
+ where name = ?))");
+ for(it = conf.service.begin(); it != conf.service.end(); ++it)
+ {
+ st->Set(1, uid);
+ st->Set(2, *it);
+ st->Execute();
+ }
+ st->Close();
+
+ st->Prepare("delete from tb_users_data where fk_user = ?");
+ st->Set(1, uid);
+ st->Execute();
+ st->Close();
+
+ i = 0;
+ st->Prepare("insert into tb_users_data (fk_user, data, num) values (?, ?, ?)");
+ for (it = conf.userdata.begin(); it != conf.userdata.end(); ++it)
+ {
+ st->Set(1, uid);
+ st->Set(2, *it);
+ st->Set(3, i++);
+ st->Execute();
+ }
+ st->Close();
+
+ st->Prepare("delete from tb_allowed_ip where fk_user = ?");
+ st->Set(1, uid);
+ st->Execute();
+
+ st->Prepare("insert into tb_allowed_ip (fk_user, ip, mask) values (?, ?, ?)");
+ for(i = 0; i < conf.ips.Count(); i++)
+ {
+ st->Set(1, uid);
+ st->Set(2, (int32_t)conf.ips[i].ip);
+ st->Set(3, (int32_t)conf.ips[i].mask);
+ st->Execute();
+ }
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::RestoreUserStat(USER_STAT * stat,
+ const string & login) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+IBPP::Timestamp actTime, addTime;
+int i, dir;
+int32_t uid, sid, passiveTime;
+
+try
+ {
+ tr->Start();
+ st->Prepare("select pk_user from tb_users where name = ?");
+ st->Set(1, login);
+ st->Execute();
+ if (!st->Fetch())
+ {
+ strError = "User \"" + login + "\" not found in database";
+ printfd(__FILE__, "User '%s' not found in database\n", login.c_str());
+ return -1;
+ }
+ st->Get(1, uid);
+ st->Close();
+
+ st->Prepare("select first 1 pk_stat, cash, free_mb, last_activity_time, \
+ last_cash_add, last_cash_add_time, passive_time from tb_stats \
+ where fk_user = ? order by stats_date desc");
+ st->Set(1, uid);
+ st->Execute();
+ if (!st->Fetch())
+ {
+ strError = "No stat info for user \"" + login + "\"";
+ printfd(__FILE__, "No stat info for user '%s'\n", login.c_str());
+ tr->Rollback();
+ return -1;
+ }
+
+ st->Get(1, sid);
+ st->Get(2, stat->cash);
+ st->Get(3, stat->freeMb);
+ st->Get(4, actTime);
+ st->Get(5, stat->lastCashAdd);
+ st->Get(6, addTime);
+ st->Get(7, passiveTime);
+
+ stat->passiveTime = passiveTime;
+
+ stat->lastActivityTime = ts2time_t(actTime);
+
+ stat->lastCashAddTime = ts2time_t(addTime);
+
+ st->Close();
+ st->Prepare("select * from tb_stats_traffic where fk_stat = ?");
+ st->Set(1, sid);
+ st->Execute();
+ for(i = 0; i < DIR_NUM; i++)
+ {
+ if (st->Fetch())
+ {
+ st->Get(3, dir);
+ st->Get(5, (int64_t &)stat->up[dir]);
+ st->Get(4, (int64_t &)stat->down[dir]);
+ }
+ else
+ {
+ break;
+ }
+ }
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::RestoreUserConf(USER_CONF * conf,
+ const string & login) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+int32_t uid;
+int i;
+IBPP::Timestamp timestamp;
+IP_MASK im;
+string name;
+bool test;
+
+try
+ {
+ tr->Start();
+ st->Prepare("select tb_users.pk_user, tb_users.address, tb_users.always_online, \
+ tb_users.credit, tb_users.credit_expire, tb_users.disabled, \
+ tb_users.disabled_detail_stat, tb_users.email, tb_users.grp, \
+ tb_users.note, tb_users.passive, tb_users.passwd, tb_users.phone, \
+ tb_users.real_name, tf1.name, tf2.name, tb_corporations.name \
+ from tb_users left join tb_tariffs tf1 \
+ on tf1.pk_tariff = tb_users.fk_tariff \
+ left join tb_tariffs tf2 \
+ on tf2.pk_tariff = tb_users.fk_tariff_change \
+ left join tb_corporations \
+ on tb_corporations.pk_corporation = tb_users.fk_corporation \
+ where tb_users.name = ?");
+ st->Set(1, login);
+ st->Execute();
+ if (!st->Fetch())
+ {
+ strError = "User \"" + login + "\" not found in database";
+ printfd(__FILE__, "User '%s' not found in database", login.c_str());
+ tr->Rollback();
+ return -1;
+ }
+ st->Get(1, uid);
+ // Getting base config
+ st->Get(2, conf->address);
+ st->Get(3, test);
+ conf->alwaysOnline = test;
+ st->Get(4, conf->credit);
+ st->Get(5, timestamp);
+
+ conf->creditExpire = ts2time_t(timestamp);
+
+ st->Get(6, test);
+ conf->disabled = test;
+ st->Get(7, test);
+ conf->disabledDetailStat = test;
+ st->Get(8, conf->email);
+ st->Get(9, conf->group);
+ st->Get(10, conf->note);
+ st->Get(11, test);
+ conf->passive = test;
+ st->Get(12, conf->password);
+ st->Get(13, conf->phone);
+ st->Get(14, conf->realName);
+ st->Get(15, conf->tariffName);
+ st->Get(16, conf->nextTariff);
+ st->Get(17, conf->corp);
+
+ if (conf->tariffName == "")
+ conf->tariffName = NO_TARIFF_NAME;
+ if (conf->corp == "")
+ conf->corp = NO_CORP_NAME;
+
+ // Services
+ st->Close();
+ st->Prepare("select name from tb_services \
+ where pk_service in \
+ (select fk_service from tb_users_services \
+ where fk_user = ?)");
+ st->Set(1, uid);
+ st->Execute();
+ while (st->Fetch())
+ {
+ st->Get(1, name);
+ conf->service.push_back(name);
+ }
+
+ // User data
+ st->Close();
+ st->Prepare("select data, num from tb_users_data where fk_user = ? order by num");
+ st->Set(1, uid);
+ st->Execute();
+ while (st->Fetch())
+ {
+ st->Get(2, i);
+ st->Get(1, conf->userdata[i]);
+ }
+
+ // User IPs
+ st->Close();
+ st->Prepare("select ip, mask from tb_allowed_ip \
+ where fk_user = ?");
+ st->Set(1, uid);
+ st->Execute();
+ conf->ips.Erase();
+ while (st->Fetch())
+ {
+ st->Get(1, (int32_t &)im.ip);
+ st->Get(2, (int32_t &)im.mask);
+ conf->ips.Add(im);
+ }
+
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::WriteUserChgLog(const string & login,
+ const string & admLogin,
+ uint32_t admIP,
+ const string & paramName,
+ const string & oldValue,
+ const string & newValue,
+ const string & message = "") const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+IBPP::Timestamp now;
+now.Now();
+
+string temp = ""; // Composed message for log
+
+try
+ {
+ tr->Start();
+ temp += "Admin \"" + admLogin + "\", ";
+ temp += inet_ntostring(admIP);
+ temp += ": ";
+ temp = temp + message;
+ //----------------------------------------------------------------------------------------
+ // Checking and inserting parameters in params table
+ st->Prepare("select pk_parameter from tb_parameters where name = ?");
+ st->Set(1, paramName);
+ st->Execute();
+ if (!st->Fetch())
+ {
+ st->Close();
+ st->Prepare("insert into tb_parameters (name) values (?)");
+ st->Set(1, paramName);
+ st->Execute();
+ }
+ st->Close();
+ //----------------------------------------------------------------------------------------
+ st->Prepare("insert into tb_params_log \
+ (fk_user, fk_parameter, event_time, from_val, to_val, comment) \
+ values ((select pk_user from tb_users \
+ where name = ?), \
+ (select pk_parameter from tb_parameters \
+ where name = ?), \
+ ?, ?, ?, ?)");
+ st->Set(1, login);
+ st->Set(2, paramName);
+ st->Set(3, now);
+ st->Set(4, oldValue);
+ st->Set(5, newValue);
+ st->Set(6, temp);
+ st->Execute();
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::WriteUserConnect(const string & login, uint32_t ip) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+IBPP::Timestamp now;
+now.Now();
+
+try
+ {
+ tr->Start();
+ st->Prepare("execute procedure sp_append_session_log(?, ?, 'c', ?)");
+ st->Set(1, login);
+ st->Set(2, now);
+ st->Set(3, (int32_t)ip);
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::WriteUserDisconnect(const string & login,
+ const DIR_TRAFF & up,
+ const DIR_TRAFF & down,
+ const DIR_TRAFF & sessionUp,
+ const DIR_TRAFF & sessionDown,
+ double cash,
+ double freeMb,
+ const std::string & reason) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+IBPP::Timestamp now;
+now.Now();
+
+int32_t id;
+int i;
+
+try
+ {
+ tr->Start();
+ st->Prepare("execute procedure sp_append_session_log(?, ?, 'd', 0)");
+ st->Set(1, login);
+ st->Set(2, now);
+ st->Execute();
+ st->Get(1, id);
+ st->Prepare("insert into tb_sessions_data \
+ (fk_session_log, dir_num, session_upload, \
+ session_download, month_upload, month_download) \
+ values (?, ?, ?, ?, ?, ?)");
+ for(i = 0; i < DIR_NUM; i++)
+ {
+ st->Set(1, id);
+ st->Set(2, i);
+ st->Set(3, (int64_t)sessionUp[i]);
+ st->Set(4, (int64_t)sessionDown[i]);
+ st->Set(5, (int64_t)up[i]);
+ st->Set(6, (int64_t)down[i]);
+ st->Execute();
+ }
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::WriteDetailedStat(const map<IP_DIR_PAIR, STAT_NODE> * statTree,
+ time_t lastStat,
+ const string & login) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+IBPP::Timestamp statTime, now;
+now.Now();
+
+time_t2ts(lastStat, &statTime);
+
+try
+ {
+ tr->Start();
+ map<IP_DIR_PAIR, STAT_NODE>::const_iterator it;
+ it = statTree->begin();
+ st->Prepare("insert into tb_detail_stats \
+ (till_time, from_time, fk_user, dir_num, \
+ ip, download, upload, cost) \
+ values (?, ?, (select pk_user from tb_users \
+ where name = ?), \
+ ?, ?, ?, ?, ?)");
+ while (it != statTree->end())
+ {
+ st->Set(1, now);
+ st->Set(2, statTime);
+ st->Set(3, login);
+ st->Set(4, it->first.dir);
+ st->Set(5, (int32_t)it->first.ip);
+ st->Set(6, (int64_t)it->second.down);
+ st->Set(7, (int64_t)it->second.up);
+ st->Set(8, it->second.cash);
+ st->Execute();
+ ++it;
+ }
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::SaveMonthStat(const USER_STAT & stat, int month, int year, const string & login) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+IBPP::Timestamp now;
+IBPP::Date nowDate;
+nowDate.Today();
+now.Now();
+int32_t id;
+int i;
+
+if (SaveStat(stat, login, year, month))
+ {
+ return -1;
+ }
+
+try
+ {
+ tr->Start();
+
+ st->Prepare("execute procedure sp_add_stat(?, 0, 0, ?, 0, ?, 0, ?)");
+ st->Set(1, login);
+ st->Set(2, now);
+ st->Set(3, now);
+ st->Set(4, nowDate);
+
+ st->Execute();
+ st->Get(1, id);
+ st->Close();
+
+ st->Prepare("insert into tb_stats_traffic \
+ (fk_stat, dir_num, upload, download) \
+ values (?, ?, 0, 0)");
+
+ for(i = 0; i < DIR_NUM; i++)
+ {
+ st->Set(1, id);
+ st->Set(2, i);
+ st->Execute();
+ }
+
+ tr->Commit();
+ }
+
+catch (IBPP::Exception & ex)
+ {
+ tr->Rollback();
+ strError = "IBPP exception";
+ printfd(__FILE__, ex.what());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
--- /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>
+ */
+
+/*
+ * Vairous utility methods
+ *
+ * $Revision: 1.8 $
+ * $Date: 2010/03/04 12:20:32 $
+ *
+ */
+
+#include <cstdio>
+
+#include "firebird_store.h"
+#include "ibpp.h"
+
+//-----------------------------------------------------------------------------
+time_t FIREBIRD_STORE::ts2time_t(const IBPP::Timestamp & ts) const
+{
+ char buf[32];
+ int year, month, day, hour, min, sec;
+ struct tm time_tm;
+
+ memset(&time_tm, 0, sizeof(time_tm));
+ ts.GetDate(year, month, day);
+ ts.GetTime(hour, min, sec);
+ sprintf(buf, "%d-%d-%d %d:%d:%d", year, month, day, hour, min, sec);
+ stg_strptime(buf, "%Y-%m-%d %H:%M:%S", &time_tm);
+
+ return mktime(&time_tm);
+}
+//-----------------------------------------------------------------------------
+void FIREBIRD_STORE::time_t2ts(time_t t, IBPP::Timestamp * ts) const
+{
+ struct tm res;
+
+ localtime_r(&t, &res); // Reenterable
+
+ *ts = IBPP::Timestamp(res.tm_year + 1900, res.tm_mon + 1, res.tm_mday, res.tm_hour, res.tm_min, res.tm_sec);
+}
+//-----------------------------------------------------------------------------
+void FIREBIRD_STORE::ym2date(int year, int month, IBPP::Date * date) const
+{
+ date->SetDate(year + 1900, month + 1, 1);
+ date->EndOfMonth();
+}
+//-----------------------------------------------------------------------------
+
--- /dev/null
+#include <sys/time.h>
+#include <errno.h>
+#include <string>
+
+#include <mysql/mysql.h>
+#include <mysql/errmsg.h>
+
+#include "user_ips.h"
+#include "user_conf.h"
+#include "user_stat.h"
+#include "mysql_store.h"
+#include "blowfish.h"
+
+#define adm_enc_passwd "cjeifY8m3"
+char qbuf[4096];
+
+using namespace std;
+
+const int pt_mega = 1024 * 1024;
+const string badSyms = "'`";
+const char repSym = '\"';
+const int RepitTimes = 3;
+
+int GetInt(const string & str, int * val, int defaultVal)
+{
+ char *res;
+
+ *val = strtol(str.c_str(), &res, 10);
+
+ if (*res != 0)
+ {
+ *val = defaultVal; //Error!
+ return EINVAL;
+ }
+
+ return 0;
+}
+
+int GetDouble(const string & str, double * val, double defaultVal)
+{
+ char *res;
+
+ *val = strtod(str.c_str(), &res);
+
+ if (*res != 0)
+ {
+ *val = defaultVal; //Error!
+ return EINVAL;
+ }
+
+ return 0;
+}
+
+int GetTime(const string & str, time_t * val, time_t defaultVal)
+{
+ char *res;
+
+ *val = strtol(str.c_str(), &res, 10);
+
+ if (*res != 0)
+ {
+ *val = defaultVal; //Error!
+ return EINVAL;
+ }
+
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+string ReplaceStr(string source, const string symlist, const char chgsym)
+{
+ string::size_type pos=0;
+
+ while( (pos = source.find_first_of(symlist,pos)) != string::npos)
+ source.replace(pos, 1,1, chgsym);
+
+ return source;
+}
+
+int GetULongLongInt(const string & str, uint64_t * val, uint64_t defaultVal)
+{
+ char *res;
+
+ *val = strtoull(str.c_str(), &res, 10);
+
+ if (*res != 0)
+ {
+ *val = defaultVal; //Error!
+ return EINVAL;
+ }
+
+ return 0;
+}
+
+class STORE_CREATOR
+{
+private:
+ BASE_STORE * bs;
+
+public:
+ STORE_CREATOR()
+ {
+ bs = new MYSQL_STORE();
+ };
+ ~STORE_CREATOR()
+ {
+ if (bs)
+ delete bs;
+ };
+
+ BASE_STORE * GetStore()
+ {
+ return bs;
+ };
+};
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//STORE_CREATOR sc;
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+BASE_STORE * GetStore()
+{
+//return sc.GetStore();
+return new MYSQL_STORE();
+}
+//-----------------------------------------------------------------------------
+MYSQL_STORE_SETTINGS::MYSQL_STORE_SETTINGS()
+{
+}
+//-----------------------------------------------------------------------------
+MYSQL_STORE_SETTINGS::~MYSQL_STORE_SETTINGS()
+{
+
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE_SETTINGS::ParseParam(const vector<PARAM_VALUE> & moduleParams,
+ const string & name, string & result)
+{
+PARAM_VALUE pv;
+pv.param = name;
+vector<PARAM_VALUE>::const_iterator pvi;
+pvi = find(moduleParams.begin(), moduleParams.end(), pv);
+if (pvi == moduleParams.end())
+ {
+ errorStr = "Parameter \'" + name + "\' not found.";
+ return -1;
+ }
+
+result = pvi->value[0];
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE_SETTINGS::ParseSettings(const MODULE_SETTINGS & s)
+{
+if (ParseParam(s.moduleParams, "dbuser", dbUser) < 0)
+ return -1;
+if (ParseParam(s.moduleParams, "rootdbpass", dbPass) < 0)
+ return -1;
+if (ParseParam(s.moduleParams, "dbname", dbName) < 0)
+ return -1;
+if (ParseParam(s.moduleParams, "dbhost", dbHost) < 0)
+ return -1;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+const string & MYSQL_STORE_SETTINGS::GetStrError() const
+{
+return errorStr;
+}
+//-----------------------------------------------------------------------------
+string MYSQL_STORE_SETTINGS::GetDBUser() const
+{
+return dbUser;
+}
+//-----------------------------------------------------------------------------
+string MYSQL_STORE_SETTINGS::GetDBPassword() const
+{
+return dbPass;
+}
+//-----------------------------------------------------------------------------
+string MYSQL_STORE_SETTINGS::GetDBHost() const
+{
+return dbHost;
+}
+//-----------------------------------------------------------------------------
+string MYSQL_STORE_SETTINGS::GetDBName() const
+{
+return dbName;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+MYSQL_STORE::MYSQL_STORE()
+{
+version = "mysql_store v.0.67";
+};
+//-----------------------------------------------------------------------------
+MYSQL_STORE::~MYSQL_STORE()
+{
+};
+//-----------------------------------------------------------------------------
+void MYSQL_STORE::SetSettings(const MODULE_SETTINGS & s)
+{
+settings = s;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::MysqlQuery(const char* sQuery,MYSQL * sock) const
+{
+ int ret,i;
+
+ if( (ret = mysql_query(sock,sQuery)) )
+ {
+ for(i=0; i<RepitTimes; i++)
+ {
+ if( (ret = mysql_query(sock,sQuery)) )
+ ;//need to send error result
+ else
+ return 0;
+ }
+ }
+
+ return ret;
+}
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::ParseSettings()
+{
+int ret = storeSettings.ParseSettings(settings);
+MYSQL mysql;
+MYSQL * sock;
+mysql_init(&mysql);
+if (ret)
+ errorStr = storeSettings.GetStrError();
+else
+{
+ if(storeSettings.GetDBPassword().length() == 0)
+ {
+ errorStr = "Database password must be not empty. Please read Manual.";
+ return -1;
+ }
+
+ if (!(sock = mysql_real_connect(&mysql,storeSettings.GetDBHost().c_str(),
+ storeSettings.GetDBUser().c_str(),storeSettings.GetDBPassword().c_str(),
+ 0,0,NULL,0)))
+ {
+ errorStr = "Couldn't connect to mysql engine! With error:\n";
+ errorStr += mysql_error(&mysql);
+ mysql_close(sock);
+ ret = -1;
+ }
+ else
+ {
+ if(mysql_select_db(sock, storeSettings.GetDBName().c_str()))
+ {
+ string res = "CREATE DATABASE " + storeSettings.GetDBName();
+
+ if(MysqlQuery(res.c_str(),sock))
+ {
+ errorStr = "Couldn't create database! With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ ret = -1;
+ }
+ else
+ {
+ if(mysql_select_db(sock, storeSettings.GetDBName().c_str()))
+ {
+ errorStr = "Couldn't select database! With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ ret = -1;
+ }
+ ret = CheckAllTables(sock);
+ }
+ }
+ else
+ ret = CheckAllTables(sock);
+ mysql_close(sock);
+ }
+
+}
+return ret;
+}
+//-----------------------------------------------------------------------------
+const string & MYSQL_STORE::GetStrError() const
+{
+return errorStr;
+}
+//-----------------------------------------------------------------------------
+const string & MYSQL_STORE::GetVersion() const
+{
+return version;
+}
+//-----------------------------------------------------------------------------
+bool MYSQL_STORE::IsTablePresent(const string & str,MYSQL * sock)
+{
+MYSQL_RES* result;
+
+if (!(result=mysql_list_tables(sock,str.c_str() )))
+{
+ errorStr = "Couldn't get tables list With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+unsigned int num_rows = mysql_num_rows(result);
+
+if(result)
+ mysql_free_result(result);
+
+return (num_rows == 1);
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::CheckAllTables(MYSQL * sock)
+{
+//admins-----------------------------------------------------------------------
+if(!IsTablePresent("admins",sock))
+{
+ sprintf(qbuf,"CREATE TABLE admins (login VARCHAR(40) DEFAULT '' PRIMARY KEY,"\
+ "password VARCHAR(150) DEFAULT '*',ChgConf TINYINT DEFAULT 0,"\
+ "ChgPassword TINYINT DEFAULT 0,ChgStat TINYINT DEFAULT 0,"\
+ "ChgCash TINYINT DEFAULT 0,UsrAddDel TINYINT DEFAULT 0,"\
+ "ChgTariff TINYINT DEFAULT 0,ChgAdmin TINYINT DEFAULT 0)");
+
+ if(MysqlQuery(qbuf,sock))
+ {
+ errorStr = "Couldn't create admin table list With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+
+ sprintf(qbuf,"INSERT INTO admins SET login='admin',"\
+ "password='geahonjehjfofnhammefahbbbfbmpkmkmmefahbbbfbmpkmkmmefahbbbfbmpkmkaa',"\
+ "ChgConf=1,ChgPassword=1,ChgStat=1,ChgCash=1,UsrAddDel=1,ChgTariff=1,ChgAdmin=1");
+
+ if(MysqlQuery(qbuf,sock))
+ {
+ errorStr = "Couldn't create default admin. With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+}
+
+//tariffs-----------------------------------------------------------------------
+string param, res;
+if(!IsTablePresent("tariffs",sock))
+{
+ res = "CREATE TABLE tariffs (name VARCHAR(40) DEFAULT '' PRIMARY KEY,";
+
+ for (int i = 0; i < DIR_NUM; i++)
+ {
+ strprintf(¶m, " PriceDayA%d DOUBLE DEFAULT 0.0,", i);
+ res += param;
+
+ strprintf(¶m, " PriceDayB%d DOUBLE DEFAULT 0.0,", i);
+ res += param;
+
+ strprintf(¶m, " PriceNightA%d DOUBLE DEFAULT 0.0,", i);
+ res += param;
+
+ strprintf(¶m, " PriceNightB%d DOUBLE DEFAULT 0.0,", i);
+ res += param;
+
+ strprintf(¶m, " Threshold%d INT DEFAULT 0,", i);
+ res += param;
+
+ string s;
+ strprintf(¶m, " Time%d VARCHAR(15) DEFAULT '0:0-0:0',", i);
+ res += param;
+
+ strprintf(¶m, " NoDiscount%d INT DEFAULT 0,", i);
+ res += param;
+
+ strprintf(¶m, " SinglePrice%d INT DEFAULT 0,", i);
+ res += param;
+ }
+
+ res += "PassiveCost DOUBLE DEFAULT 0.0, Fee DOUBLE DEFAULT 0.0,"\
+ "Free DOUBLE DEFAULT 0.0, TraffType VARCHAR(10) DEFAULT '')";
+
+ if(MysqlQuery(res.c_str(),sock))
+ {
+ errorStr = "Couldn't create tariffs table list With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+
+ res = "INSERT INTO tariffs SET name='tariff',";
+
+ for (int i = 0; i < DIR_NUM; i++)
+ {
+ strprintf(¶m, " NoDiscount%d=1,", i);
+ res += param;
+
+ strprintf(¶m, " Threshold%d=0,", i);
+ res += param;
+
+ strprintf(¶m, " Time%d='0:0-0:0',", i);
+ res += param;
+
+ if(i != 0 && i != 1)
+ {
+ strprintf(¶m, " SinglePrice%d=0,", i);
+ res += param;
+ }
+
+ if(i != 1)
+ {
+ strprintf(¶m, " PriceDayA%d=0.0,", i);
+ res += param;
+ }
+ if(i != 1)
+ {
+ strprintf(¶m, " PriceDayB%d=0.0,", i);
+ res += param;
+ }
+
+ if(i != 0)
+ {
+ strprintf(¶m, " PriceNightA%d=0.0,", i);
+ res += param;
+ }
+ if(i != 0)
+ {
+ strprintf(¶m, " PriceNightB%d=0.0,", i);
+ res += param;
+ }
+ }
+
+ res += "PassiveCost=0.0, Fee=10.0, Free=0,"\
+ "SinglePrice0=1, SinglePrice1=1,PriceDayA1=0.75,PriceDayB1=0.75,"\
+ "PriceNightA0=1.0,PriceNightB0=1.0,TraffType='up+down'";
+
+ if(MysqlQuery(res.c_str(),sock))
+ {
+ errorStr = "Couldn't create default tariff. With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+}
+
+//users-----------------------------------------------------------------------
+if(!IsTablePresent("users",sock))
+{
+ res = "CREATE TABLE users (login VARCHAR(50) NOT NULL DEFAULT '' PRIMARY KEY, Password VARCHAR(150) NOT NULL DEFAULT '*',"\
+ "Passive INT(3) DEFAULT 0,Down INT(3) DEFAULT 0,DisabledDetailStat INT(3) DEFAULT 0,AlwaysOnline INT(3) DEFAULT 0,Tariff VARCHAR(40) NOT NULL DEFAULT '',"\
+ "Address VARCHAR(254) NOT NULL DEFAULT '',Phone VARCHAR(128) NOT NULL DEFAULT '',Email VARCHAR(50) NOT NULL DEFAULT '',"\
+ "Note TEXT NOT NULL,RealName VARCHAR(254) NOT NULL DEFAULT '',StgGroup VARCHAR(40) NOT NULL DEFAULT '',"\
+ "Credit DOUBLE DEFAULT 0, TariffChange VARCHAR(40) NOT NULL DEFAULT '',";
+
+ for (int i = 0; i < USERDATA_NUM; i++)
+ {
+ strprintf(¶m, " Userdata%d VARCHAR(254) NOT NULL,", i);
+ res += param;
+ }
+
+ param = " CreditExpire INT(11) DEFAULT 0,";
+ res += param;
+
+ strprintf(¶m, " IP VARCHAR(254) DEFAULT '*',");
+ res += param;
+
+ for (int i = 0; i < DIR_NUM; i++)
+ {
+ strprintf(¶m, " D%d BIGINT(30) DEFAULT 0,", i);
+ res += param;
+
+ strprintf(¶m, " U%d BIGINT(30) DEFAULT 0,", i);
+ res += param;
+ }
+
+ strprintf(¶m, "Cash DOUBLE DEFAULT 0,FreeMb DOUBLE DEFAULT 0,LastCashAdd DOUBLE DEFAULT 0,"\
+ "LastCashAddTime INT(11) DEFAULT 0,PassiveTime INT(11) DEFAULT 0,LastActivityTime INT(11) DEFAULT 0,"\
+ "NAS VARCHAR(17) NOT NULL, INDEX (AlwaysOnline), INDEX (IP), INDEX (Address),"\
+ " INDEX (Tariff),INDEX (Phone),INDEX (Email),INDEX (RealName))");
+ res += param;
+
+ if(MysqlQuery(res.c_str(),sock))
+ {
+ errorStr = "Couldn't create users table list With error:\n";
+ errorStr += mysql_error(sock);
+ errorStr += "\n\n" + res;
+ mysql_close(sock);
+ return -1;
+ }
+
+ res = "INSERT INTO users SET login='test',Address='',AlwaysOnline=0,"\
+ "Credit=0.0,CreditExpire=0,Down=0,Email='',DisabledDetailStat=0,"\
+ "StgGroup='',IP='192.168.1.1',Note='',Passive=0,Password='123456',"\
+ "Phone='', RealName='',Tariff='tariff',TariffChange='',Userdata0='',"\
+ "Userdata1='',";
+
+ for (int i = 0; i < DIR_NUM; i++)
+ {
+ strprintf(¶m, " D%d=0,", i);
+ res += param;
+
+ strprintf(¶m, " U%d=0,", i);
+ res += param;
+ }
+
+ res += "Cash=10.0,FreeMb=0.0,LastActivityTime=0,LastCashAdd=0,"\
+ "LastCashAddTime=0, PassiveTime=0";
+
+ if(MysqlQuery(res.c_str(),sock))
+ {
+ errorStr = "Couldn't create default user. With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+}
+/*
+//logs-----------------------------------------------------------------------
+if(!IsTablePresent("logs"))
+{
+ sprintf(qbuf,"CREATE TABLE logs (unid INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, login VARCHAR(40),text TEXT)");
+
+ if(MysqlQuery(qbuf))
+ {
+ errorStr = "Couldn't create admin table list With error:\n";
+ errorStr += mysql_error(sock);
+ return -1;
+ }
+}
+*/
+//messages---------------------------------------------------------------------
+if(!IsTablePresent("messages",sock))
+{
+ sprintf(qbuf,"CREATE TABLE messages (login VARCHAR(40) DEFAULT '', id BIGINT, "\
+ "type INT, lastSendTime INT, creationTime INT, showTime INT,"\
+ "stgRepeat INT, repeatPeriod INT, text TEXT)");
+
+ if(MysqlQuery(qbuf,sock))
+ {
+ errorStr = "Couldn't create messages table. With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+}
+
+//month_stat-------------------------------------------------------------------
+if(!IsTablePresent("stat",sock))
+{
+ res = "CREATE TABLE stat (login VARCHAR(50), month TINYINT, year SMALLINT,";
+
+ for (int i = 0; i < DIR_NUM; i++)
+ {
+ strprintf(¶m, " U%d BIGINT,", i);
+ res += param;
+
+ strprintf(¶m, " D%d BIGINT,", i);
+ res += param;
+ }
+
+ res += " cash DOUBLE, INDEX (login))";
+
+ if(MysqlQuery(res.c_str(),sock))
+ {
+ errorStr = "Couldn't create stat table. With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+int MYSQL_STORE::GetAllParams(vector<string> * ParamList,
+ const string & table, const string & name) const
+{
+MYSQL_RES *res;
+MYSQL_ROW row;
+MYSQL * sock=NULL;
+unsigned int num,i;
+
+ParamList->clear();
+
+sprintf(qbuf,"SELECT %s FROM %s", name.c_str(), table.c_str());
+
+if(MysqlGetQuery(qbuf,sock))
+{
+ errorStr = "Couldn't GetAllParams Query for: ";
+ errorStr += name + " - " + table + "\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+if (!(res=mysql_store_result(sock)))
+{
+ errorStr = "Couldn't GetAllParams Results for: ";
+ errorStr += name + " - " + table + "\n";
+ errorStr += mysql_error(sock);
+ return -1;
+}
+
+num = mysql_num_rows(res);
+
+for(i=0;i<num;i++)
+{
+ row = mysql_fetch_row(res);
+ ParamList->push_back(row[0]);
+}
+
+mysql_free_result(res);
+mysql_close(sock);
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::GetUsersList(vector<string> * usersList) const
+{
+if(GetAllParams(usersList, "users", "login"))
+ return -1;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::GetAdminsList(vector<string> * adminsList) const
+{
+if(GetAllParams(adminsList, "admins", "login"))
+ return -1;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::GetTariffsList(vector<string> * tariffsList) const
+{
+if(GetAllParams(tariffsList, "tariffs", "name"))
+ return -1;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::AddUser(const string & login) const
+{
+sprintf(qbuf,"INSERT INTO users SET login='%s'", login.c_str());
+
+if(MysqlSetQuery(qbuf))
+{
+ errorStr = "Couldn't add user:\n";
+ //errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::DelUser(const string & login) const
+{
+sprintf(qbuf,"DELETE FROM users WHERE login='%s' LIMIT 1", login.c_str());
+
+if(MysqlSetQuery(qbuf))
+{
+ errorStr = "Couldn't delete user:\n";
+ //errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::RestoreUserConf(USER_CONF * conf, const string & login) const
+{
+MYSQL_RES *res;
+MYSQL_ROW row;
+MYSQL * sock;
+string query;
+
+query = "SELECT login, Password, Passive, Down, DisabledDetailStat, \
+ AlwaysOnline, Tariff, Address, Phone, Email, Note, \
+ RealName, StgGroup, Credit, TariffChange, ";
+
+for (int i = 0; i < USERDATA_NUM; i++)
+{
+ sprintf(qbuf, "Userdata%d, ", i);
+ query += qbuf;
+}
+
+query += "CreditExpire, IP FROM users WHERE login='";
+query += login + "' LIMIT 1";
+
+//sprintf(qbuf,"SELECT * FROM users WHERE login='%s' LIMIT 1", login.c_str());
+
+if(MysqlGetQuery(query.c_str(),sock))
+{
+ errorStr = "Couldn't restore Tariff(on query):\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+if (!(res=mysql_store_result(sock)))
+{
+ errorStr = "Couldn't restore Tariff(on getting result):\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+row = mysql_fetch_row(res);
+
+string param;
+
+conf->password = row[1];
+
+if (conf->password.empty())
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' password is blank.";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetInt(row[2],&conf->passive, 0) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' data not read. Parameter Passive.";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetInt(row[3], &conf->disabled, 0) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' data not read. Parameter Down.";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetInt(row[4], &conf->disabledDetailStat, 0) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' data not read. Parameter DisabledDetailStat.";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetInt(row[5], &conf->alwaysOnline, 0) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' data not read. Parameter AlwaysOnline.";
+ mysql_close(sock);
+ return -1;
+ }
+
+conf->tariffName = row[6];
+
+if (conf->tariffName.empty())
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' tariff is blank.";
+ mysql_close(sock);
+ return -1;
+ }
+
+conf->address = row[7];
+conf->phone = row[8];
+conf->email = row[9];
+conf->note = row[10];
+conf->realName = row[11];
+conf->group = row[12];
+
+if (GetDouble(row[13], &conf->credit, 0) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' data not read. Parameter Credit.";
+ mysql_close(sock);
+ return -1;
+ }
+
+conf->nextTariff = row[14];
+
+for (int i = 0; i < USERDATA_NUM; i++)
+ {
+ conf->userdata[i] = row[15+i];
+ }
+
+GetTime(row[15+USERDATA_NUM], &conf->creditExpire, 0);
+
+string ipStr = row[16+USERDATA_NUM];
+USER_IPS i;
+try
+ {
+ i = StrToIPS(ipStr);
+ }
+catch (string s)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' data not read. Parameter IP address. " + s;
+ mysql_close(sock);
+ return -1;
+ }
+conf->ips = i;
+
+mysql_free_result(res);
+mysql_close(sock);
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::RestoreUserStat(USER_STAT * stat, const string & login) const
+{
+MYSQL_RES *res;
+MYSQL_ROW row;
+MYSQL * sock;
+
+string query;
+
+query = "SELECT ";
+
+for (int i = 0; i < DIR_NUM; i++)
+{
+ sprintf(qbuf, "D%d, U%d, ", i, i);
+ query += qbuf;
+}
+
+query += "Cash, FreeMb, LastCashAdd, LastCashAddTime, PassiveTime, LastActivityTime \
+ FROM users WHERE login = '";
+query += login + "'";
+
+//sprintf(qbuf,"SELECT * FROM users WHERE login='%s' LIMIT 1", login.c_str());
+
+if(MysqlGetQuery(query.c_str() ,sock))
+{
+ errorStr = "Couldn't restore UserStat(on query):\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+if (!(res=mysql_store_result(sock)))
+{
+ errorStr = "Couldn't restore UserStat(on getting result):\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+row = mysql_fetch_row(res);
+
+unsigned int startPos=0;
+
+char s[22];
+uint64_t traffU[DIR_NUM];
+uint64_t traffD[DIR_NUM];
+
+for (int i = 0; i < DIR_NUM; i++)
+ {
+ sprintf(s, "D%d", i);
+ if (GetULongLongInt(row[startPos+i*2],&traffD[i], 0) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' stat not read. Parameter " + string(s);
+ mysql_close(sock);
+ return -1;
+ }
+ stat->down = traffD;
+
+ sprintf(s, "U%d", i);
+ if (GetULongLongInt(row[startPos+i*2+1], &traffU[i], 0) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' stat not read. Parameter " + string(s);
+ mysql_close(sock);
+ return -1;
+ }
+ stat->up = traffU;
+ }//for
+
+startPos += (2*DIR_NUM);
+
+if (GetDouble(row[startPos], &stat->cash, 0) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' stat not read. Parameter Cash";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetDouble(row[startPos+1],&stat->freeMb, 0) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' stat not read. Parameter FreeMb";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetDouble(row[startPos+2], &stat->lastCashAdd, 0) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' stat not read. Parameter LastCashAdd";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetTime(row[startPos+3], &stat->lastCashAddTime, 0) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' stat not read. Parameter LastCashAddTime";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetTime(row[startPos+4], &stat->passiveTime, 0) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' stat not read. Parameter PassiveTime";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetTime(row[startPos+5], &stat->lastActivityTime, 0) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' stat not read. Parameter LastActivityTime";
+ mysql_close(sock);
+ return -1;
+ }
+
+mysql_free_result(res);
+mysql_close(sock);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::SaveUserConf(const USER_CONF & conf, const string & login) const
+{
+string param;
+string res;
+
+strprintf(&res,"UPDATE users SET Password='%s', Passive=%d, Down=%d, DisabledDetailStat = %d, "\
+ "AlwaysOnline=%d, Tariff='%s', Address='%s', Phone='%s', Email='%s', "\
+ "Note='%s', RealName='%s', StgGroup='%s', Credit=%f, TariffChange='%s', ",
+ conf.password.c_str(),
+ conf.passive,
+ conf.disabled,
+ conf.disabledDetailStat,
+ conf.alwaysOnline,
+ conf.tariffName.c_str(),
+ (ReplaceStr(conf.address,badSyms,repSym)).c_str(),
+ (ReplaceStr(conf.phone,badSyms,repSym)).c_str(),
+ (ReplaceStr(conf.email,badSyms,repSym)).c_str(),
+ (ReplaceStr(conf.note,badSyms,repSym)).c_str(),
+ (ReplaceStr(conf.realName,badSyms,repSym)).c_str(),
+ (ReplaceStr(conf.group,badSyms,repSym)).c_str(),
+ conf.credit,
+ conf.nextTariff.c_str()
+ );
+
+for (int i = 0; i < USERDATA_NUM; i++)
+ {
+ strprintf(¶m, " Userdata%d='%s',", i,
+ (ReplaceStr(conf.userdata[i],badSyms,repSym)).c_str());
+ res += param;
+ }
+
+strprintf(¶m, " CreditExpire=%d,", conf.creditExpire);
+res += param;
+
+stringstream ipStr;
+ipStr << conf.ips;
+
+strprintf(¶m, " IP='%s'", ipStr.str().c_str());
+res += param;
+
+strprintf(¶m, " WHERE login='%s' LIMIT 1", login.c_str());
+res += param;
+
+if(MysqlSetQuery(res.c_str()))
+{
+ errorStr = "Couldn't save user conf:\n";
+ //errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::SaveUserStat(const USER_STAT & stat, const string & login) const
+{
+string param;
+string res;
+
+res = "UPDATE users SET";
+
+for (int i = 0; i < DIR_NUM; i++)
+ {
+ strprintf(¶m, " D%d=%lld,", i, stat.down[i]);
+ res += param;
+
+ strprintf(¶m, " U%d=%lld,", i, stat.up[i]);
+ res += param;
+ }
+
+strprintf(¶m, " Cash=%f, FreeMb=%f, LastCashAdd=%f, LastCashAddTime=%d,"\
+ " PassiveTime=%d, LastActivityTime=%d",
+ stat.cash,
+ stat.freeMb,
+ stat.lastCashAdd,
+ stat.lastCashAddTime,
+ stat.passiveTime,
+ stat.lastActivityTime
+ );
+res += param;
+
+strprintf(¶m, " WHERE login='%s' LIMIT 1", login.c_str());
+res += param;
+
+if(MysqlSetQuery(res.c_str()))
+{
+ errorStr = "Couldn't save user stat:\n";
+// errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::WriteLogString(const string & str, const string & login) const
+{
+string res, tempStr;
+time_t t;
+tm * lt;
+
+t = time(NULL);
+lt = localtime(&t);
+
+MYSQL_RES* result;
+MYSQL * sock;
+strprintf(&tempStr, "logs_%02d_%4d", lt->tm_mon+1, lt->tm_year+1900);
+if (!(sock=MysqlConnect())){
+ errorStr = "Couldn't connect to Server";
+ return -1;
+}
+if (!(result=mysql_list_tables(sock,tempStr.c_str() )))
+{
+ errorStr = "Couldn't get table " + tempStr + ":\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+unsigned int num_rows = mysql_num_rows(result);
+
+mysql_free_result(result);
+
+if (num_rows < 1)
+{
+ sprintf(qbuf,"CREATE TABLE logs_%02d_%4d (unid INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, login VARCHAR(40),text TEXT)",
+ lt->tm_mon+1, lt->tm_year+1900);
+
+ if(MysqlQuery(qbuf,sock))
+ {
+ errorStr = "Couldn't create WriteDetailedStat table:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+}
+
+strprintf(&res, "%s -- %s",LogDate(t), str.c_str());
+
+string send;
+
+strprintf(&send,"INSERT INTO logs_%02d_%4d SET login='%s', text='%s'",
+ lt->tm_mon+1, lt->tm_year+1900,
+ login.c_str(), (ReplaceStr(res,badSyms,repSym)).c_str());
+
+if(MysqlQuery(send.c_str(),sock))
+{
+ errorStr = "Couldn't write log string:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+mysql_close(sock);
+return 0;
+
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::WriteUserChgLog(const string & login,
+ const string & admLogin,
+ uint32_t admIP,
+ const string & paramName,
+ const string & oldValue,
+ const string & newValue,
+ const string & message) const
+{
+string userLogMsg = "Admin \'" + admLogin + "\', " + string(inet_ntostr(admIP)) + ": \'"
+ + paramName + "\' parameter changed from \'" + oldValue +
+ "\' to \'" + newValue + "\'. " + message;
+
+return WriteLogString(userLogMsg, login);
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::WriteUserConnect(const string & login, uint32_t ip) const
+{
+string logStr = "Connect, " + string(inet_ntostr(ip));
+return WriteLogString(logStr, login);
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::WriteUserDisconnect(const string & login,
+ const DIR_TRAFF & up,
+ const DIR_TRAFF & down,
+ const DIR_TRAFF & sessionUp,
+ const DIR_TRAFF & sessionDown,
+ double cash,
+ double freeMb) const
+{
+string logStr = "Disconnect, ";
+stringstream sssu;
+stringstream sssd;
+stringstream ssmu;
+stringstream ssmd;
+stringstream sscash;
+
+ssmu << up;
+ssmd << down;
+
+sssu << sessionUp;
+sssd << sessionDown;
+
+sscash << cash;
+
+logStr += " session upload: \'";
+logStr += sssu.str();
+logStr += "\' session download: \'";
+logStr += sssd.str();
+logStr += "\' month upload: \'";
+logStr += ssmu.str();
+logStr += "\' month download: \'";
+logStr += ssmd.str();
+logStr += "\' cash: \'";
+logStr += sscash.str();
+logStr += "\'";
+
+return WriteLogString(logStr, login);
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::SaveMonthStat(const USER_STAT & stat, int month, int year,
+ const string & login) const
+{
+string param, res;
+
+strprintf(&res, "INSERT INTO stat SET login='%s', month=%d, year=%d,",
+ login.c_str(), month+1, year+1900);
+
+for (int i = 0; i < DIR_NUM; i++)
+ {
+ strprintf(¶m, " U%d=%lld,", i, stat.up[i]);
+ res += param;
+
+ strprintf(¶m, " D%d=%lld,", i, stat.down[i]);
+ res += param;
+ }
+
+strprintf(¶m, " cash=%f", stat.cash);
+res += param;
+
+if(MysqlSetQuery(res.c_str()))
+{
+ errorStr = "Couldn't SaveMonthStat:\n";
+ //errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------*/
+int MYSQL_STORE::AddAdmin(const string & login) const
+{
+sprintf(qbuf,"INSERT INTO admins SET login='%s'", login.c_str());
+
+if(MysqlSetQuery(qbuf))
+{
+ errorStr = "Couldn't add admin:\n";
+ //errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------*/
+int MYSQL_STORE::DelAdmin(const string & login) const
+{
+sprintf(qbuf,"DELETE FROM admins where login='%s' LIMIT 1", login.c_str());
+
+if(MysqlSetQuery(qbuf))
+{
+ errorStr = "Couldn't delete admin:\n";
+ //errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------*/
+int MYSQL_STORE::SaveAdmin(const ADMIN_CONF & ac) const
+{
+char passwordE[2 * ADM_PASSWD_LEN + 2];
+char pass[ADM_PASSWD_LEN + 1];
+char adminPass[ADM_PASSWD_LEN + 1];
+
+memset(pass, 0, sizeof(pass));
+memset(adminPass, 0, sizeof(adminPass));
+
+BLOWFISH_CTX ctx;
+EnDecodeInit(adm_enc_passwd, strlen(adm_enc_passwd), &ctx);
+
+strncpy(adminPass, ac.password.c_str(), ADM_PASSWD_LEN);
+adminPass[ADM_PASSWD_LEN - 1] = 0;
+
+for (int i = 0; i < ADM_PASSWD_LEN/8; i++)
+ {
+ EncodeString(pass + 8*i, adminPass + 8*i, &ctx);
+ }
+
+pass[ADM_PASSWD_LEN - 1] = 0;
+Encode12(passwordE, pass, ADM_PASSWD_LEN);
+
+sprintf(qbuf,"UPDATE admins SET password='%s', ChgConf=%d, ChgPassword=%d, "\
+ "ChgStat=%d, ChgCash=%d, UsrAddDel=%d, ChgTariff=%d, ChgAdmin=%d "\
+ "WHERE login='%s' LIMIT 1",
+ passwordE,
+ ac.priv.userConf,
+ ac.priv.userPasswd,
+ ac.priv.userStat,
+ ac.priv.userCash,
+ ac.priv.userAddDel,
+ ac.priv.tariffChg,
+ ac.priv.adminChg,
+ ac.login.c_str()
+ );
+
+if(MysqlSetQuery(qbuf))
+{
+ errorStr = "Couldn't save admin:\n";
+ //errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::RestoreAdmin(ADMIN_CONF * ac, const string & login) const
+{
+char pass[ADM_PASSWD_LEN + 1];
+char password[ADM_PASSWD_LEN + 1];
+char passwordE[2*ADM_PASSWD_LEN + 2];
+BLOWFISH_CTX ctx;
+
+string p;
+MYSQL_RES *res;
+MYSQL_ROW row;
+MYSQL * sock;
+sprintf(qbuf,"SELECT * FROM admins WHERE login='%s' LIMIT 1", login.c_str());
+
+if(MysqlGetQuery(qbuf,sock))
+{
+ errorStr = "Couldn't restore admin:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+if (!(res=mysql_store_result(sock)))
+{
+ errorStr = "Couldn't restore admin:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+if ( mysql_num_rows(res) == 0)
+{
+ mysql_free_result(res);
+ errorStr = "Couldn't restore admin as couldn't found him in table.\n";
+ mysql_close(sock);
+ return -1;
+}
+
+row = mysql_fetch_row(res);
+
+p = row[1];
+int a;
+
+if(p.length() == 0)
+{
+ mysql_free_result(res);
+ errorStr = "Error in parameter password";
+ mysql_close(sock);
+ return -1;
+}
+
+memset(passwordE, 0, sizeof(passwordE));
+strncpy(passwordE, p.c_str(), 2*ADM_PASSWD_LEN);
+
+memset(pass, 0, sizeof(pass));
+
+if (passwordE[0] != 0)
+ {
+ Decode21(pass, passwordE);
+ EnDecodeInit(adm_enc_passwd, strlen(adm_enc_passwd), &ctx);
+
+ for (int i = 0; i < ADM_PASSWD_LEN/8; i++)
+ {
+ DecodeString(password + 8*i, pass + 8*i, &ctx);
+ }
+ }
+else
+ {
+ password[0] = 0;
+ }
+
+ac->password = password;
+
+if (GetInt(row[2], &a, 0) == 0)
+ ac->priv.userConf = a;
+else
+ {
+ mysql_free_result(res);
+ errorStr = "Error in parameter ChgConf";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetInt(row[3], &a, 0) == 0)
+ ac->priv.userPasswd = a;
+else
+ {
+ mysql_free_result(res);
+ errorStr = "Error in parameter ChgPassword";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetInt(row[4], &a, 0) == 0)
+ ac->priv.userStat = a;
+else
+ {
+ mysql_free_result(res);
+ errorStr = "Error in parameter ChgStat";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetInt(row[5], &a, 0) == 0)
+ ac->priv.userCash = a;
+else
+ {
+ mysql_free_result(res);
+ errorStr = "Error in parameter ChgCash";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetInt(row[6], &a, 0) == 0)
+ ac->priv.userAddDel = a;
+else
+ {
+ mysql_free_result(res);
+ errorStr = "Error in parameter UsrAddDel";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetInt(row[7], &a, 0) == 0)
+ ac->priv.tariffChg = a;
+else
+ {
+ mysql_free_result(res);
+ errorStr = "Error in parameter ChgTariff";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetInt(row[8], &a, 0) == 0)
+ ac->priv.adminChg = a;
+else
+ {
+ mysql_free_result(res);
+ errorStr = "Error in parameter ChgAdmin";
+ mysql_close(sock);
+ return -1;
+ }
+
+mysql_free_result(res);
+mysql_close(sock);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::AddTariff(const string & name) const
+{
+sprintf(qbuf,"INSERT INTO tariffs SET name='%s'", name.c_str());
+
+if(MysqlSetQuery(qbuf))
+{
+ errorStr = "Couldn't add tariff:\n";
+// errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::DelTariff(const string & name) const
+{
+sprintf(qbuf,"DELETE FROM tariffs WHERE name='%s' LIMIT 1", name.c_str());
+
+if(MysqlSetQuery(qbuf))
+{
+ errorStr = "Couldn't delete tariff: ";
+// errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::RestoreTariff(TARIFF_DATA * td, const string & tariffName) const
+{
+MYSQL_RES *res;
+MYSQL_ROW row;
+MYSQL * sock;
+sprintf(qbuf,"SELECT * FROM tariffs WHERE name='%s' LIMIT 1", tariffName.c_str());
+
+if(MysqlGetQuery(qbuf,sock))
+{
+ errorStr = "Couldn't restore Tariff:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+if (!(res=mysql_store_result(sock)))
+{
+ errorStr = "Couldn't restore Tariff:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+string str;
+td->tariffConf.name = tariffName;
+
+row = mysql_fetch_row(res);
+
+string param;
+for (int i = 0; i<DIR_NUM; i++)
+ {
+ strprintf(¶m, "Time%d", i);
+ str = row[6+i*8];
+ if (str.length() == 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ mysql_close(sock);
+ return -1;
+ }
+
+ ParseTariffTimeStr(str.c_str(),
+ td->dirPrice[i].hDay,
+ td->dirPrice[i].mDay,
+ td->dirPrice[i].hNight,
+ td->dirPrice[i].mNight);
+
+ strprintf(¶m, "PriceDayA%d", i);
+ if (GetDouble(row[1+i*8], &td->dirPrice[i].priceDayA, 0.0) < 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ mysql_close(sock);
+ return -1;
+ }
+ td->dirPrice[i].priceDayA /= (1024*1024);
+
+ strprintf(¶m, "PriceDayB%d", i);
+ if (GetDouble(row[2+i*8], &td->dirPrice[i].priceDayB, 0.0) < 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ mysql_close(sock);
+ return -1;
+ }
+ td->dirPrice[i].priceDayB /= (1024*1024);
+
+ strprintf(¶m, "PriceNightA%d", i);
+ if (GetDouble(row[3+i*8], &td->dirPrice[i].priceNightA, 0.0) < 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ mysql_close(sock);
+ return -1;
+ }
+ td->dirPrice[i].priceNightA /= (1024*1024);
+
+ strprintf(¶m, "PriceNightB%d", i);
+ if (GetDouble(row[4+i*8], &td->dirPrice[i].priceNightB, 0.0) < 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ mysql_close(sock);
+ return -1;
+ }
+ td->dirPrice[i].priceNightB /= (1024*1024);
+
+ strprintf(¶m, "Threshold%d", i);
+ if (GetInt(row[5+i*8], &td->dirPrice[i].threshold, 0) < 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ mysql_close(sock);
+ return -1;
+ }
+
+ strprintf(¶m, "SinglePrice%d", i);
+ if (GetInt(row[8+i*8], &td->dirPrice[i].singlePrice, 0) < 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ mysql_close(sock);
+ return -1;
+ }
+
+ strprintf(¶m, "NoDiscount%d", i);
+ if (GetInt(row[7+i*8], &td->dirPrice[i].noDiscount, 0) < 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ mysql_close(sock);
+ return -1;
+ }
+ }//main for
+
+if (GetDouble(row[2+8*DIR_NUM], &td->tariffConf.fee, 0.0) < 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter Fee";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetDouble(row[3+8*DIR_NUM], &td->tariffConf.free, 0.0) < 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter Free";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetDouble(row[1+8*DIR_NUM], &td->tariffConf.passiveCost, 0.0) < 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter PassiveCost";
+ mysql_close(sock);
+ return -1;
+ }
+
+ str = row[4+8*DIR_NUM];
+ param = "TraffType";
+
+ if (str.length() == 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ mysql_close(sock);
+ return -1;
+ }
+
+if (!strcasecmp(str.c_str(), "up"))
+ td->tariffConf.traffType = TRAFF_UP;
+else
+ if (!strcasecmp(str.c_str(), "down"))
+ td->tariffConf.traffType = TRAFF_DOWN;
+ else
+ if (!strcasecmp(str.c_str(), "up+down"))
+ td->tariffConf.traffType = TRAFF_UP_DOWN;
+ else
+ if (!strcasecmp(str.c_str(), "max"))
+ td->tariffConf.traffType = TRAFF_MAX;
+ else
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter TraffType incorrect";
+ mysql_close(sock);
+ return -1;
+ }
+
+mysql_free_result(res);
+mysql_close(sock);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::SaveTariff(const TARIFF_DATA & td, const string & tariffName) const
+{
+string param;
+
+string res="UPDATE tariffs SET";
+
+for (int i = 0; i < DIR_NUM; i++)
+ {
+ strprintf(¶m, " PriceDayA%d=%f,", i,
+ td.dirPrice[i].priceDayA * pt_mega);
+ res += param;
+
+ strprintf(¶m, " PriceDayB%d=%f,", i,
+ td.dirPrice[i].priceDayB * pt_mega);
+ res += param;
+
+ strprintf(¶m, " PriceNightA%d=%f,", i,
+ td.dirPrice[i].priceNightA * pt_mega);
+ res += param;
+
+ strprintf(¶m, " PriceNightB%d=%f,", i,
+ td.dirPrice[i].priceNightB * pt_mega);
+ res += param;
+
+ strprintf(¶m, " Threshold%d=%d,", i,
+ td.dirPrice[i].threshold);
+ res += param;
+
+ string s;
+ strprintf(¶m, " Time%d", i);
+
+ strprintf(&s, "%0d:%0d-%0d:%0d",
+ td.dirPrice[i].hDay,
+ td.dirPrice[i].mDay,
+ td.dirPrice[i].hNight,
+ td.dirPrice[i].mNight);
+
+ res += (param + "='" + s + "',");
+
+ strprintf(¶m, " NoDiscount%d=%d,", i,
+ td.dirPrice[i].noDiscount);
+ res += param;
+
+ strprintf(¶m, " SinglePrice%d=%d,", i,
+ td.dirPrice[i].singlePrice);
+ res += param;
+ }
+
+strprintf(¶m, " PassiveCost=%f,", td.tariffConf.passiveCost);
+res += param;
+
+strprintf(¶m, " Fee=%f,", td.tariffConf.fee);
+res += param;
+
+strprintf(¶m, " Free=%f,", td.tariffConf.free);
+res += param;
+
+switch (td.tariffConf.traffType)
+ {
+ case TRAFF_UP:
+ res += " TraffType='up'";
+ break;
+ case TRAFF_DOWN:
+ res += " TraffType='down'";
+ break;
+ case TRAFF_UP_DOWN:
+ res += " TraffType='up+down'";
+ break;
+ case TRAFF_MAX:
+ res += " TraffType='max'";
+ break;
+ }
+strprintf(¶m, " WHERE name='%s' LIMIT 1", tariffName.c_str());
+res += param;
+
+if(MysqlSetQuery(res.c_str()))
+{
+ errorStr = "Couldn't save admin:\n";
+ //errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::WriteDetailedStat(const map<IP_DIR_PAIR, STAT_NODE> * statTree,
+ time_t lastStat,
+ const string & login) const
+{
+string res, stTime, endTime, tempStr;
+time_t t;
+tm * lt;
+
+t = time(NULL);
+lt = localtime(&t);
+
+if (lt->tm_hour == 0 && lt->tm_min <= 5)
+ {
+ t -= 3600 * 24;
+ lt = localtime(&t);
+ }
+
+MYSQL_RES* result;
+MYSQL * sock;
+strprintf(&tempStr, "detailstat_%02d_%4d", lt->tm_mon+1, lt->tm_year+1900);
+
+if (!(sock=MysqlConnect())){
+ mysql_close(sock);
+ return -1;
+}
+
+if (!(result=mysql_list_tables(sock,tempStr.c_str() )))
+{
+ errorStr = "Couldn't get table " + tempStr + ":\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+unsigned int num_rows = mysql_num_rows(result);
+
+mysql_free_result(result);
+
+if (num_rows < 1)
+{
+ sprintf(qbuf,"CREATE TABLE detailstat_%02d_%4d (login VARCHAR(40) DEFAULT '',"\
+ "day TINYINT DEFAULT 0,startTime TIME,endTime TIME,"\
+ "IP VARCHAR(17) DEFAULT '',dir INT DEFAULT 0,"\
+ "down BIGINT DEFAULT 0,up BIGINT DEFAULT 0, cash DOUBLE DEFAULT 0.0, INDEX (login), INDEX(dir), INDEX(day), INDEX(IP))",
+ lt->tm_mon+1, lt->tm_year+1900);
+
+ if(MysqlQuery(qbuf,sock))
+ {
+ errorStr = "Couldn't create WriteDetailedStat table:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+}
+
+struct tm * lt1;
+struct tm * lt2;
+
+lt1 = localtime(&lastStat);
+
+int h1, m1, s1;
+int h2, m2, s2;
+
+h1 = lt1->tm_hour;
+m1 = lt1->tm_min;
+s1 = lt1->tm_sec;
+
+lt2 = localtime(&t);
+
+h2 = lt2->tm_hour;
+m2 = lt2->tm_min;
+s2 = lt2->tm_sec;
+
+strprintf(&stTime, "%02d:%02d:%02d", h1, m1, s1);
+strprintf(&endTime, "%02d:%02d:%02d", h2, m2, s2);
+
+strprintf(&res,"INSERT INTO detailstat_%02d_%4d SET login='%s',"\
+ "day=%d,startTime='%s',endTime='%s',",
+ lt->tm_mon+1, lt->tm_year+1900,
+ login.c_str(),
+ lt->tm_mday,
+ stTime.c_str(),
+ endTime.c_str()
+ );
+
+int retRes;
+map<IP_DIR_PAIR, STAT_NODE>::const_iterator stIter;
+stIter = statTree->begin();
+
+while (stIter != statTree->end())
+ {
+ strprintf(&tempStr,"IP='%s', dir=%d, down=%lld, up=%lld, cash=%f",
+ inet_ntostr(stIter->first.ip),
+ stIter->first.dir,
+ stIter->second.down,
+ stIter->second.up,
+ stIter->second.cash
+ );
+
+ if( (retRes = MysqlQuery((res+tempStr).c_str(),sock)) )
+ {
+ errorStr = "Couldn't insert data in WriteDetailedStat:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+
+ result=mysql_store_result(sock);
+ if(result)
+ mysql_free_result(result);
+
+ ++stIter;
+ }
+mysql_close(sock);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::AddMessage(STG_MSG * msg, const string & login) const
+{
+struct timeval tv;
+
+gettimeofday(&tv, NULL);
+
+msg->header.id = ((long long)tv.tv_sec) * 1000000 + ((long long)tv.tv_usec);
+
+sprintf(qbuf,"INSERT INTO messages SET login='%s', id=%lld",
+ login.c_str(),
+ (long long)msg->header.id
+ );
+
+if(MysqlSetQuery(qbuf))
+{
+ errorStr = "Couldn't add message:\n";
+ //errorStr += mysql_error(sock);
+ return -1;
+}
+
+return EditMessage(*msg, login);
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::EditMessage(const STG_MSG & msg, const string & login) const
+{
+string res;
+
+strprintf(&res,"UPDATE messages SET type=%d, lastSendTime=%u, creationTime=%u, "\
+ "showTime=%u, stgRepeat=%d, repeatPeriod=%u, text='%s' "\
+ "WHERE login='%s' AND id=%lld LIMIT 1",
+ msg.header.type,
+ msg.header.lastSendTime,
+ msg.header.creationTime,
+ msg.header.showTime,
+ msg.header.repeat,
+ msg.header.repeatPeriod,
+ (ReplaceStr(msg.text,badSyms,repSym)).c_str(),
+ login.c_str(),
+ (long long)msg.header.id
+ );
+
+if(MysqlSetQuery(res.c_str()))
+{
+ errorStr = "Couldn't edit message:\n";
+ //errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::GetMessage(uint64_t id, STG_MSG * msg, const string & login) const
+{
+MYSQL_RES *res;
+MYSQL_ROW row;
+MYSQL * sock;
+
+sprintf(qbuf,"SELECT * FROM messages WHERE login='%s' AND id=%lld LIMIT 1",
+ login.c_str(), id);
+
+if(MysqlGetQuery(qbuf,sock))
+{
+ errorStr = "Couldn't GetMessage:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+if (!(res=mysql_store_result(sock)))
+{
+ errorStr = "Couldn't GetMessage:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+row = mysql_fetch_row(res);
+
+if(row[2]&&str2x(row[2], msg->header.type))
+{
+ mysql_free_result(res);
+ errorStr = "Invalid value in message header for user: " + login;
+ mysql_close(sock);
+ return -1;
+}
+
+if(row[3] && str2x(row[3], msg->header.lastSendTime))
+{
+ mysql_free_result(res);
+ errorStr = "Invalid value in message header for user: " + login;
+ mysql_close(sock);
+ return -1;
+}
+
+if(row[4] && str2x(row[4], msg->header.creationTime))
+{
+ mysql_free_result(res);
+ errorStr = "Invalid value in message header for user: " + login;
+ mysql_close(sock);
+ return -1;
+}
+
+if(row[5] && str2x(row[5], msg->header.showTime))
+{
+ mysql_free_result(res);
+ errorStr = "Invalid value in message header for user: " + login;
+ mysql_close(sock);
+ return -1;
+}
+
+if(row[6] && str2x(row[6], msg->header.repeat))
+{
+ mysql_free_result(res);
+ errorStr = "Invalid value in message header for user: " + login;
+ mysql_close(sock);
+ return -1;
+}
+
+if(row[7] && str2x(row[7], msg->header.repeatPeriod))
+{
+ mysql_free_result(res);
+ errorStr = "Invalid value in message header for user: " + login;
+ mysql_close(sock);
+ return -1;
+}
+
+msg->header.id = id;
+msg->text = row[8];
+
+mysql_free_result(res);
+mysql_close(sock);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::DelMessage(uint64_t id, const string & login) const
+{
+sprintf(qbuf,"DELETE FROM messages WHERE login='%s' AND id=%lld LIMIT 1",
+ login.c_str(),(long long)id);
+
+if(MysqlSetQuery(qbuf))
+{
+ errorStr = "Couldn't delete Message:\n";
+ //errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::GetMessageHdrs(vector<STG_MSG_HDR> * hdrsList, const string & login) const
+{
+MYSQL_RES *res;
+MYSQL_ROW row;
+MYSQL * sock;
+sprintf(qbuf,"SELECT * FROM messages WHERE login='%s'", login.c_str());
+
+if(MysqlGetQuery(qbuf,sock))
+{
+ errorStr = "Couldn't GetMessageHdrs:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+if (!(res=mysql_store_result(sock)))
+{
+ errorStr = "Couldn't GetMessageHdrs:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+unsigned int i, num_rows = mysql_num_rows(res);
+long long int unsigned id;
+
+for (i=0; i<num_rows; i++)
+{
+ row = mysql_fetch_row(res);
+ if (str2x(row[1], id))
+ continue;
+
+ STG_MSG_HDR hdr;
+ if (row[2])
+ if(str2x(row[2], hdr.type))
+ continue;
+
+ if (row[3])
+ if(str2x(row[3], hdr.lastSendTime))
+ continue;
+
+ if (row[4])
+ if(str2x(row[4], hdr.creationTime))
+ continue;
+
+ if (row[5])
+ if(str2x(row[5], hdr.showTime))
+ continue;
+
+ if (row[6])
+ if(str2x(row[6], hdr.repeat))
+ continue;
+
+ if (row[7])
+ if(str2x(row[7], hdr.repeatPeriod))
+ continue;
+
+ hdr.id = id;
+ hdrsList->push_back(hdr);
+}
+
+mysql_free_result(res);
+mysql_close(sock);
+return 0;
+}
+//-----------------------------------------------------------------------------
+
+int MYSQL_STORE::MysqlSetQuery(const char * Query) const {
+
+ MYSQL * sock;
+ int ret=MysqlGetQuery(Query,sock);
+ mysql_close(sock);
+ return ret;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::MysqlGetQuery(const char * Query,MYSQL * & sock) const {
+ if (!(sock=MysqlConnect())) {
+ return -1;
+ }
+ return MysqlQuery(Query,sock);
+}
+//-----------------------------------------------------------------------------
+MYSQL * MYSQL_STORE::MysqlConnect() const {
+ MYSQL * sock;
+ if ( !(sock=mysql_init(NULL)) ){
+ errorStr= "mysql init susck\n";
+ return NULL;
+ }
+ if (!(sock = mysql_real_connect(sock,storeSettings.GetDBHost().c_str(),
+ storeSettings.GetDBUser().c_str(),storeSettings.GetDBPassword().c_str(),
+ 0,0,NULL,0)))
+ {
+ errorStr = "Couldn't connect to mysql engine! With error:\n";
+ errorStr += mysql_error(sock);
+ return NULL;
+ }
+ else{
+ if(mysql_select_db(sock, storeSettings.GetDBName().c_str())){
+ errorStr = "Database lost !\n";
+ return NULL;
+ }
+ }
+ return sock;
+}
+//-----------------------------------------------------------------------------
--- /dev/null
+ /*
+ $Revision: 1.1.1.1 $
+ $Date: 2007/11/17 18:28:39 $
+ */
+
+
+#ifndef FILE_STORE_H
+#define FILE_STORE_H
+
+#include <string>
+
+#include "base_settings.h"
+#include "base_store.h"
+#include "user_traff.h"
+#include <mysql/mysql.h>
+
+using namespace std;
+//-----------------------------------------------------------------------------
+extern "C" BASE_STORE * GetStore();
+//-----------------------------------------------------------------------------
+class MYSQL_STORE_SETTINGS//: public BASE_SETTINGS
+{
+public:
+ MYSQL_STORE_SETTINGS();
+ virtual ~MYSQL_STORE_SETTINGS();
+ virtual int ParseSettings(const MODULE_SETTINGS & s);
+ virtual const string & GetStrError() const;
+
+ string GetDBUser() const;
+ string GetDBPassword() const;
+ string GetDBHost() const;
+ string GetDBName() const;
+
+private:
+ const MODULE_SETTINGS * settings;
+
+ int ParseParam(const vector<PARAM_VALUE> & moduleParams,
+ const string & name, string & result);
+
+ string errorStr;
+
+ string dbUser;
+ string dbPass;
+ string dbName;
+ string dbHost;
+};
+//-----------------------------------------------------------------------------
+class MYSQL_STORE: public BASE_STORE
+{
+public:
+ MYSQL_STORE();
+ virtual ~MYSQL_STORE();
+ virtual const string & GetStrError() const;
+
+ //User
+ virtual int GetUsersList(vector<string> * usersList) const;
+ virtual int AddUser(const string & login) const;
+ virtual int DelUser(const string & login) const;
+ virtual int SaveUserStat(const USER_STAT & stat, const string & login) const;
+ virtual int SaveUserConf(const USER_CONF & conf, const string & login) const;
+ virtual int RestoreUserStat(USER_STAT * stat, const string & login) const;
+ virtual int RestoreUserConf(USER_CONF * conf, const string & login) const;
+ virtual int WriteUserChgLog(const string & login,
+ const string & admLogin,
+ uint32_t admIP,
+ const string & paramName,
+ const string & oldValue,
+ const string & newValue,
+ const string & message = "") const;
+ virtual int WriteUserConnect(const string & login, uint32_t ip) const;
+ virtual int WriteUserDisconnect(const string & login,
+ const DIR_TRAFF & up,
+ const DIR_TRAFF & down,
+ const DIR_TRAFF & sessionUp,
+ const DIR_TRAFF & sessionDown,
+ double cash,
+ double freeMb) const;
+
+ virtual int WriteDetailedStat(const map<IP_DIR_PAIR, STAT_NODE> * statTree,
+ time_t lastStat,
+ const string & login) const;
+
+ virtual int AddMessage(STG_MSG * msg, const string & login) const;
+ virtual int EditMessage(const STG_MSG & msg, const string & login) const;
+ virtual int GetMessage(uint64_t id, STG_MSG * msg, const string & login) const;
+ virtual int DelMessage(uint64_t id, const string & login) const;
+ virtual int GetMessageHdrs(vector<STG_MSG_HDR> * hdrsList, const string & login) const;
+
+ virtual int SaveMonthStat(const USER_STAT & stat, int month, int year, const string & login) const;
+
+ //Admin
+ virtual int GetAdminsList(vector<string> * adminsList) const;
+ virtual int AddAdmin(const string & login) const;
+ virtual int DelAdmin(const string & login) const;
+ virtual int RestoreAdmin(ADMIN_CONF * ac, const string & login) const;
+ virtual int SaveAdmin(const ADMIN_CONF & ac) const;
+
+ //Tariff
+ virtual int GetTariffsList(vector<string> * tariffsList) const;
+ virtual int AddTariff(const string & name) const;
+ virtual int DelTariff(const string & name) const;
+ virtual int SaveTariff(const TARIFF_DATA & td, const string & tariffName) const;
+ virtual int RestoreTariff(TARIFF_DATA * td, const string & tariffName) const;
+
+ //Corparation
+ virtual int GetCorpsList(vector<string> * corpsList) const {return 0;};
+ virtual int SaveCorp(const CORP_CONF & cc) const {return 0;};
+ virtual int RestoreCorp(CORP_CONF * cc, const string & name) const {return 0;};
+ virtual int AddCorp(const string & name) const {return 0;};
+ virtual int DelCorp(const string & name) const {return 0;};
+
+ // Services
+ virtual int GetServicesList(vector<string> * corpsList) const {return 0;};
+ virtual int SaveService(const SERVICE_CONF & sc) const {return 0;};
+ virtual int RestoreService(SERVICE_CONF * sc, const string & name) const {return 0;};
+ virtual int AddService(const string & name) const {return 0;};
+ virtual int DelService(const string & name) const {return 0;};
+
+ //virtual BASE_SETTINGS * GetStoreSettings();
+ virtual void SetSettings(const MODULE_SETTINGS & s);
+ virtual int ParseSettings();
+ virtual const string & GetVersion() const;
+
+private:
+ virtual int WriteLogString(const string & str, const string & login) const;
+ int GetAllParams(vector<string> * ParamList, const string & table, const string & name) const;
+ int CheckAllTables(MYSQL * sock);
+ bool IsTablePresent(const string & str,MYSQL * sock);
+ mutable string errorStr;
+// int Reconnect();
+ int MysqlQuery(const char* sQuery,MYSQL * sock) const;
+ int MysqlGetQuery(const char * Query,MYSQL * & sock) const;
+ int MysqlSetQuery(const char * Query) const;
+ MYSQL * MysqlConnect() const ;
+ string version;
+ MYSQL_STORE_SETTINGS storeSettings;
+ MODULE_SETTINGS settings;
+ //mutable MYSQL mysql;
+ //mutable MYSQL* sock;
+};
+//-----------------------------------------------------------------------------
+
+#endif //FILE_STORE_H
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.6 2010/03/25 10:35:55 faust Exp $
+###############################################################################
+
+include ../../../../../Makefile.conf
+
+PROG = mod_store_mysql.so
+
+SRCS = ./mysql_store.cpp
+
+STGLIBS = -lconffiles -lstg_common -lstg_crypto
+
+MYSQL_CFLAGS = $(shell mysql_config --cflags)
+MYSQL_LDFLAGS = $(shell mysql_config --libs_r)
+
+CXXFLAGS += $(MYSQL_CFLAGS)
+LIBS += $(MYSQL_LDFLAGS)
+
+include ../../Makefile.in
+
--- /dev/null
+mysql_store.o: mysql_store.cpp /usr/include/mysql/mysql.h \
+ /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \
+ /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \
+ /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \
+ /usr/include/mysql/errmsg.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_ips.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/common.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_const.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_ips.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/resetable.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_stat.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_traff.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_locker.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/noncopyable.h \
+ mysql_store.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/base_settings.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/base_store.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_stat.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/corp_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/service_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/admin_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/tariff_conf.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/base_settings.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/stg_message.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/user_traff.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/blowfish.h Makefile ../../../../../Makefile.conf
+ $(CC) -c $< -g3 -W -Wall -I/usr/local/include -DARCH_LE -I/usr/include/mysql -DHAVE_ERRNO_AS_DEFINE=1 -DUNIV_LINUX -DUNIV_LINUX -fPIC -I /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include -DDEBUG -DLINUX
--- /dev/null
+#include <sys/time.h>
+#include <cerrno>
+#include <cstdio>
+#include <cstdlib>
+#include <string>
+#include <algorithm>
+
+#include <mysql.h>
+#include <errmsg.h>
+
+#include "user_ips.h"
+#include "user_conf.h"
+#include "user_stat.h"
+#include "mysql_store.h"
+#include "blowfish.h"
+
+#define adm_enc_passwd "cjeifY8m3"
+char qbuf[4096];
+
+using namespace std;
+
+const int pt_mega = 1024 * 1024;
+const string badSyms = "'`";
+const char repSym = '\"';
+const int RepitTimes = 3;
+
+int GetInt(const string & str, int * val, int defaultVal)
+{
+ char *res;
+
+ *val = strtol(str.c_str(), &res, 10);
+
+ if (*res != 0)
+ {
+ *val = defaultVal; //Error!
+ return EINVAL;
+ }
+
+ return 0;
+}
+
+int GetDouble(const string & str, double * val, double defaultVal)
+{
+ char *res;
+
+ *val = strtod(str.c_str(), &res);
+
+ if (*res != 0)
+ {
+ *val = defaultVal; //Error!
+ return EINVAL;
+ }
+
+ return 0;
+}
+
+int GetTime(const string & str, time_t * val, time_t defaultVal)
+{
+ char *res;
+
+ *val = strtol(str.c_str(), &res, 10);
+
+ if (*res != 0)
+ {
+ *val = defaultVal; //Error!
+ return EINVAL;
+ }
+
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+string ReplaceStr(string source, const string symlist, const char chgsym)
+{
+ string::size_type pos=0;
+
+ while( (pos = source.find_first_of(symlist,pos)) != string::npos)
+ source.replace(pos, 1,1, chgsym);
+
+ return source;
+}
+
+int GetULongLongInt(const string & str, uint64_t * val, uint64_t defaultVal)
+{
+ char *res;
+
+ *val = strtoull(str.c_str(), &res, 10);
+
+ if (*res != 0)
+ {
+ *val = defaultVal; //Error!
+ return EINVAL;
+ }
+
+ return 0;
+}
+
+class MYSQL_STORE_CREATOR
+{
+private:
+ MYSQL_STORE * ms;
+
+public:
+ MYSQL_STORE_CREATOR()
+ : ms(new MYSQL_STORE())
+ {
+ };
+ ~MYSQL_STORE_CREATOR()
+ {
+ delete ms;
+ };
+
+ MYSQL_STORE * GetStore()
+ {
+ return ms;
+ };
+} msc;
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+BASE_STORE * GetStore()
+{
+return msc.GetStore();
+}
+//-----------------------------------------------------------------------------
+MYSQL_STORE_SETTINGS::MYSQL_STORE_SETTINGS()
+ : settings(NULL)
+{
+}
+//-----------------------------------------------------------------------------
+MYSQL_STORE_SETTINGS::~MYSQL_STORE_SETTINGS()
+{
+
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE_SETTINGS::ParseParam(const vector<PARAM_VALUE> & moduleParams,
+ const string & name, string & result)
+{
+PARAM_VALUE pv;
+pv.param = name;
+vector<PARAM_VALUE>::const_iterator pvi;
+pvi = find(moduleParams.begin(), moduleParams.end(), pv);
+if (pvi == moduleParams.end())
+ {
+ errorStr = "Parameter \'" + name + "\' not found.";
+ return -1;
+ }
+
+result = pvi->value[0];
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE_SETTINGS::ParseSettings(const MODULE_SETTINGS & s)
+{
+if (ParseParam(s.moduleParams, "dbuser", dbUser) < 0)
+ return -1;
+if (ParseParam(s.moduleParams, "rootdbpass", dbPass) < 0)
+ return -1;
+if (ParseParam(s.moduleParams, "dbname", dbName) < 0)
+ return -1;
+if (ParseParam(s.moduleParams, "dbhost", dbHost) < 0)
+ return -1;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+const string & MYSQL_STORE_SETTINGS::GetStrError() const
+{
+return errorStr;
+}
+//-----------------------------------------------------------------------------
+string MYSQL_STORE_SETTINGS::GetDBUser() const
+{
+return dbUser;
+}
+//-----------------------------------------------------------------------------
+string MYSQL_STORE_SETTINGS::GetDBPassword() const
+{
+return dbPass;
+}
+//-----------------------------------------------------------------------------
+string MYSQL_STORE_SETTINGS::GetDBHost() const
+{
+return dbHost;
+}
+//-----------------------------------------------------------------------------
+string MYSQL_STORE_SETTINGS::GetDBName() const
+{
+return dbName;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+MYSQL_STORE::MYSQL_STORE()
+{
+version = "mysql_store v.0.67";
+};
+//-----------------------------------------------------------------------------
+MYSQL_STORE::~MYSQL_STORE()
+{
+};
+//-----------------------------------------------------------------------------
+void MYSQL_STORE::SetSettings(const MODULE_SETTINGS & s)
+{
+settings = s;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::MysqlQuery(const char* sQuery,MYSQL * sock) const
+{
+ int ret,i;
+
+ if( (ret = mysql_query(sock,sQuery)) )
+ {
+ for(i=0; i<RepitTimes; i++)
+ {
+ if( (ret = mysql_query(sock,sQuery)) )
+ ;//need to send error result
+ else
+ return 0;
+ }
+ }
+
+ return ret;
+}
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::ParseSettings()
+{
+int ret = storeSettings.ParseSettings(settings);
+MYSQL mysql;
+MYSQL * sock;
+mysql_init(&mysql);
+if (ret)
+ errorStr = storeSettings.GetStrError();
+else
+{
+ if(storeSettings.GetDBPassword().length() == 0)
+ {
+ errorStr = "Database password must be not empty. Please read Manual.";
+ return -1;
+ }
+
+ if (!(sock = mysql_real_connect(&mysql,storeSettings.GetDBHost().c_str(),
+ storeSettings.GetDBUser().c_str(),storeSettings.GetDBPassword().c_str(),
+ 0,0,NULL,0)))
+ {
+ errorStr = "Couldn't connect to mysql engine! With error:\n";
+ errorStr += mysql_error(&mysql);
+ mysql_close(sock);
+ ret = -1;
+ }
+ else
+ {
+ if(mysql_select_db(sock, storeSettings.GetDBName().c_str()))
+ {
+ string res = "CREATE DATABASE " + storeSettings.GetDBName();
+
+ if(MysqlQuery(res.c_str(),sock))
+ {
+ errorStr = "Couldn't create database! With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ ret = -1;
+ }
+ else
+ {
+ if(mysql_select_db(sock, storeSettings.GetDBName().c_str()))
+ {
+ errorStr = "Couldn't select database! With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ ret = -1;
+ }
+ ret = CheckAllTables(sock);
+ }
+ }
+ else
+ ret = CheckAllTables(sock);
+ mysql_close(sock);
+ }
+
+}
+return ret;
+}
+//-----------------------------------------------------------------------------
+const string & MYSQL_STORE::GetStrError() const
+{
+return errorStr;
+}
+//-----------------------------------------------------------------------------
+const string & MYSQL_STORE::GetVersion() const
+{
+return version;
+}
+//-----------------------------------------------------------------------------
+bool MYSQL_STORE::IsTablePresent(const string & str,MYSQL * sock)
+{
+MYSQL_RES* result;
+
+if (!(result=mysql_list_tables(sock,str.c_str() )))
+{
+ errorStr = "Couldn't get tables list With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+unsigned int num_rows = mysql_num_rows(result);
+
+if(result)
+ mysql_free_result(result);
+
+return (num_rows == 1);
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::CheckAllTables(MYSQL * sock)
+{
+//admins-----------------------------------------------------------------------
+if(!IsTablePresent("admins",sock))
+{
+ sprintf(qbuf,"CREATE TABLE admins (login VARCHAR(40) DEFAULT '' PRIMARY KEY,"\
+ "password VARCHAR(150) DEFAULT '*',ChgConf TINYINT DEFAULT 0,"\
+ "ChgPassword TINYINT DEFAULT 0,ChgStat TINYINT DEFAULT 0,"\
+ "ChgCash TINYINT DEFAULT 0,UsrAddDel TINYINT DEFAULT 0,"\
+ "ChgTariff TINYINT DEFAULT 0,ChgAdmin TINYINT DEFAULT 0)");
+
+ if(MysqlQuery(qbuf,sock))
+ {
+ errorStr = "Couldn't create admin table list With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+
+ sprintf(qbuf,"INSERT INTO admins SET login='admin',"\
+ "password='geahonjehjfofnhammefahbbbfbmpkmkmmefahbbbfbmpkmkmmefahbbbfbmpkmkaa',"\
+ "ChgConf=1,ChgPassword=1,ChgStat=1,ChgCash=1,UsrAddDel=1,ChgTariff=1,ChgAdmin=1");
+
+ if(MysqlQuery(qbuf,sock))
+ {
+ errorStr = "Couldn't create default admin. With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+}
+
+//tariffs-----------------------------------------------------------------------
+string param, res;
+if(!IsTablePresent("tariffs",sock))
+{
+ res = "CREATE TABLE tariffs (name VARCHAR(40) DEFAULT '' PRIMARY KEY,";
+
+ for (int i = 0; i < DIR_NUM; i++)
+ {
+ strprintf(¶m, " PriceDayA%d DOUBLE DEFAULT 0.0,", i);
+ res += param;
+
+ strprintf(¶m, " PriceDayB%d DOUBLE DEFAULT 0.0,", i);
+ res += param;
+
+ strprintf(¶m, " PriceNightA%d DOUBLE DEFAULT 0.0,", i);
+ res += param;
+
+ strprintf(¶m, " PriceNightB%d DOUBLE DEFAULT 0.0,", i);
+ res += param;
+
+ strprintf(¶m, " Threshold%d INT DEFAULT 0,", i);
+ res += param;
+
+ strprintf(¶m, " Time%d VARCHAR(15) DEFAULT '0:0-0:0',", i);
+ res += param;
+
+ strprintf(¶m, " NoDiscount%d INT DEFAULT 0,", i);
+ res += param;
+
+ strprintf(¶m, " SinglePrice%d INT DEFAULT 0,", i);
+ res += param;
+ }
+
+ res += "PassiveCost DOUBLE DEFAULT 0.0, Fee DOUBLE DEFAULT 0.0,"\
+ "Free DOUBLE DEFAULT 0.0, TraffType VARCHAR(10) DEFAULT '')";
+
+ if(MysqlQuery(res.c_str(),sock))
+ {
+ errorStr = "Couldn't create tariffs table list With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+
+ res = "INSERT INTO tariffs SET name='tariff',";
+
+ for (int i = 0; i < DIR_NUM; i++)
+ {
+ strprintf(¶m, " NoDiscount%d=1,", i);
+ res += param;
+
+ strprintf(¶m, " Threshold%d=0,", i);
+ res += param;
+
+ strprintf(¶m, " Time%d='0:0-0:0',", i);
+ res += param;
+
+ if(i != 0 && i != 1)
+ {
+ strprintf(¶m, " SinglePrice%d=0,", i);
+ res += param;
+ }
+
+ if(i != 1)
+ {
+ strprintf(¶m, " PriceDayA%d=0.0,", i);
+ res += param;
+ }
+ if(i != 1)
+ {
+ strprintf(¶m, " PriceDayB%d=0.0,", i);
+ res += param;
+ }
+
+ if(i != 0)
+ {
+ strprintf(¶m, " PriceNightA%d=0.0,", i);
+ res += param;
+ }
+ if(i != 0)
+ {
+ strprintf(¶m, " PriceNightB%d=0.0,", i);
+ res += param;
+ }
+ }
+
+ res += "PassiveCost=0.0, Fee=10.0, Free=0,"\
+ "SinglePrice0=1, SinglePrice1=1,PriceDayA1=0.75,PriceDayB1=0.75,"\
+ "PriceNightA0=1.0,PriceNightB0=1.0,TraffType='up+down'";
+
+ if(MysqlQuery(res.c_str(),sock))
+ {
+ errorStr = "Couldn't create default tariff. With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+}
+
+//users-----------------------------------------------------------------------
+if(!IsTablePresent("users",sock))
+{
+ res = "CREATE TABLE users (login VARCHAR(50) NOT NULL DEFAULT '' PRIMARY KEY, Password VARCHAR(150) NOT NULL DEFAULT '*',"\
+ "Passive INT(3) DEFAULT 0,Down INT(3) DEFAULT 0,DisabledDetailStat INT(3) DEFAULT 0,AlwaysOnline INT(3) DEFAULT 0,Tariff VARCHAR(40) NOT NULL DEFAULT '',"\
+ "Address VARCHAR(254) NOT NULL DEFAULT '',Phone VARCHAR(128) NOT NULL DEFAULT '',Email VARCHAR(50) NOT NULL DEFAULT '',"\
+ "Note TEXT NOT NULL,RealName VARCHAR(254) NOT NULL DEFAULT '',StgGroup VARCHAR(40) NOT NULL DEFAULT '',"\
+ "Credit DOUBLE DEFAULT 0, TariffChange VARCHAR(40) NOT NULL DEFAULT '',";
+
+ for (int i = 0; i < USERDATA_NUM; i++)
+ {
+ strprintf(¶m, " Userdata%d VARCHAR(254) NOT NULL,", i);
+ res += param;
+ }
+
+ param = " CreditExpire INT(11) DEFAULT 0,";
+ res += param;
+
+ strprintf(¶m, " IP VARCHAR(254) DEFAULT '*',");
+ res += param;
+
+ for (int i = 0; i < DIR_NUM; i++)
+ {
+ strprintf(¶m, " D%d BIGINT(30) DEFAULT 0,", i);
+ res += param;
+
+ strprintf(¶m, " U%d BIGINT(30) DEFAULT 0,", i);
+ res += param;
+ }
+
+ strprintf(¶m, "Cash DOUBLE DEFAULT 0,FreeMb DOUBLE DEFAULT 0,LastCashAdd DOUBLE DEFAULT 0,"\
+ "LastCashAddTime INT(11) DEFAULT 0,PassiveTime INT(11) DEFAULT 0,LastActivityTime INT(11) DEFAULT 0,"\
+ "NAS VARCHAR(17) NOT NULL, INDEX (AlwaysOnline), INDEX (IP), INDEX (Address),"\
+ " INDEX (Tariff),INDEX (Phone),INDEX (Email),INDEX (RealName))");
+ res += param;
+
+ if(MysqlQuery(res.c_str(),sock))
+ {
+ errorStr = "Couldn't create users table list With error:\n";
+ errorStr += mysql_error(sock);
+ errorStr += "\n\n" + res;
+ mysql_close(sock);
+ return -1;
+ }
+
+ res = "INSERT INTO users SET login='test',Address='',AlwaysOnline=0,"\
+ "Credit=0.0,CreditExpire=0,Down=0,Email='',DisabledDetailStat=0,"\
+ "StgGroup='',IP='192.168.1.1',Note='',Passive=0,Password='123456',"\
+ "Phone='', RealName='',Tariff='tariff',TariffChange='',Userdata0='',"\
+ "Userdata1='',";
+
+ for (int i = 0; i < DIR_NUM; i++)
+ {
+ strprintf(¶m, " D%d=0,", i);
+ res += param;
+
+ strprintf(¶m, " U%d=0,", i);
+ res += param;
+ }
+
+ res += "Cash=10.0,FreeMb=0.0,LastActivityTime=0,LastCashAdd=0,"\
+ "LastCashAddTime=0, PassiveTime=0";
+
+ if(MysqlQuery(res.c_str(),sock))
+ {
+ errorStr = "Couldn't create default user. With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+}
+/*
+//logs-----------------------------------------------------------------------
+if(!IsTablePresent("logs"))
+{
+ sprintf(qbuf,"CREATE TABLE logs (unid INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, login VARCHAR(40),text TEXT)");
+
+ if(MysqlQuery(qbuf))
+ {
+ errorStr = "Couldn't create admin table list With error:\n";
+ errorStr += mysql_error(sock);
+ return -1;
+ }
+}
+*/
+//messages---------------------------------------------------------------------
+if(!IsTablePresent("messages",sock))
+{
+ sprintf(qbuf,"CREATE TABLE messages (login VARCHAR(40) DEFAULT '', id BIGINT, "\
+ "type INT, lastSendTime INT, creationTime INT, showTime INT,"\
+ "stgRepeat INT, repeatPeriod INT, text TEXT)");
+
+ if(MysqlQuery(qbuf,sock))
+ {
+ errorStr = "Couldn't create messages table. With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+}
+
+//month_stat-------------------------------------------------------------------
+if(!IsTablePresent("stat",sock))
+{
+ res = "CREATE TABLE stat (login VARCHAR(50), month TINYINT, year SMALLINT,";
+
+ for (int i = 0; i < DIR_NUM; i++)
+ {
+ strprintf(¶m, " U%d BIGINT,", i);
+ res += param;
+
+ strprintf(¶m, " D%d BIGINT,", i);
+ res += param;
+ }
+
+ res += " cash DOUBLE, INDEX (login))";
+
+ if(MysqlQuery(res.c_str(),sock))
+ {
+ errorStr = "Couldn't create stat table. With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+int MYSQL_STORE::GetAllParams(vector<string> * ParamList,
+ const string & table, const string & name) const
+{
+MYSQL_RES *res;
+MYSQL_ROW row;
+MYSQL * sock=NULL;
+unsigned int num,i;
+
+ParamList->clear();
+
+sprintf(qbuf,"SELECT %s FROM %s", name.c_str(), table.c_str());
+
+if(MysqlGetQuery(qbuf,sock))
+{
+ errorStr = "Couldn't GetAllParams Query for: ";
+ errorStr += name + " - " + table + "\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+if (!(res=mysql_store_result(sock)))
+{
+ errorStr = "Couldn't GetAllParams Results for: ";
+ errorStr += name + " - " + table + "\n";
+ errorStr += mysql_error(sock);
+ return -1;
+}
+
+num = mysql_num_rows(res);
+
+for(i=0;i<num;i++)
+{
+ row = mysql_fetch_row(res);
+ ParamList->push_back(row[0]);
+}
+
+mysql_free_result(res);
+mysql_close(sock);
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::GetUsersList(vector<string> * usersList) const
+{
+if(GetAllParams(usersList, "users", "login"))
+ return -1;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::GetAdminsList(vector<string> * adminsList) const
+{
+if(GetAllParams(adminsList, "admins", "login"))
+ return -1;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::GetTariffsList(vector<string> * tariffsList) const
+{
+if(GetAllParams(tariffsList, "tariffs", "name"))
+ return -1;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::AddUser(const string & login) const
+{
+sprintf(qbuf,"INSERT INTO users SET login='%s'", login.c_str());
+
+if(MysqlSetQuery(qbuf))
+{
+ errorStr = "Couldn't add user:\n";
+ //errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::DelUser(const string & login) const
+{
+sprintf(qbuf,"DELETE FROM users WHERE login='%s' LIMIT 1", login.c_str());
+
+if(MysqlSetQuery(qbuf))
+{
+ errorStr = "Couldn't delete user:\n";
+ //errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::RestoreUserConf(USER_CONF * conf, const string & login) const
+{
+MYSQL_RES *res;
+MYSQL_ROW row;
+MYSQL * sock;
+string query;
+
+query = "SELECT login, Password, Passive, Down, DisabledDetailStat, \
+ AlwaysOnline, Tariff, Address, Phone, Email, Note, \
+ RealName, StgGroup, Credit, TariffChange, ";
+
+for (int i = 0; i < USERDATA_NUM; i++)
+{
+ sprintf(qbuf, "Userdata%d, ", i);
+ query += qbuf;
+}
+
+query += "CreditExpire, IP FROM users WHERE login='";
+query += login + "' LIMIT 1";
+
+//sprintf(qbuf,"SELECT * FROM users WHERE login='%s' LIMIT 1", login.c_str());
+
+if(MysqlGetQuery(query.c_str(),sock))
+{
+ errorStr = "Couldn't restore Tariff(on query):\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+if (!(res=mysql_store_result(sock)))
+{
+ errorStr = "Couldn't restore Tariff(on getting result):\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+row = mysql_fetch_row(res);
+
+string param;
+
+conf->password = row[1];
+
+if (conf->password.empty())
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' password is blank.";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetInt(row[2],&conf->passive, 0) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' data not read. Parameter Passive.";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetInt(row[3], &conf->disabled, 0) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' data not read. Parameter Down.";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetInt(row[4], &conf->disabledDetailStat, 0) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' data not read. Parameter DisabledDetailStat.";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetInt(row[5], &conf->alwaysOnline, 0) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' data not read. Parameter AlwaysOnline.";
+ mysql_close(sock);
+ return -1;
+ }
+
+conf->tariffName = row[6];
+
+if (conf->tariffName.empty())
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' tariff is blank.";
+ mysql_close(sock);
+ return -1;
+ }
+
+conf->address = row[7];
+conf->phone = row[8];
+conf->email = row[9];
+conf->note = row[10];
+conf->realName = row[11];
+conf->group = row[12];
+
+if (GetDouble(row[13], &conf->credit, 0) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' data not read. Parameter Credit.";
+ mysql_close(sock);
+ return -1;
+ }
+
+conf->nextTariff = row[14];
+
+for (int i = 0; i < USERDATA_NUM; i++)
+ {
+ conf->userdata[i] = row[15+i];
+ }
+
+GetTime(row[15+USERDATA_NUM], &conf->creditExpire, 0);
+
+string ipStr = row[16+USERDATA_NUM];
+USER_IPS i;
+try
+ {
+ i = StrToIPS(ipStr);
+ }
+catch (string s)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' data not read. Parameter IP address. " + s;
+ mysql_close(sock);
+ return -1;
+ }
+conf->ips = i;
+
+mysql_free_result(res);
+mysql_close(sock);
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::RestoreUserStat(USER_STAT * stat, const string & login) const
+{
+MYSQL_RES *res;
+MYSQL_ROW row;
+MYSQL * sock;
+
+string query;
+
+query = "SELECT ";
+
+for (int i = 0; i < DIR_NUM; i++)
+{
+ sprintf(qbuf, "D%d, U%d, ", i, i);
+ query += qbuf;
+}
+
+query += "Cash, FreeMb, LastCashAdd, LastCashAddTime, PassiveTime, LastActivityTime \
+ FROM users WHERE login = '";
+query += login + "'";
+
+//sprintf(qbuf,"SELECT * FROM users WHERE login='%s' LIMIT 1", login.c_str());
+
+if(MysqlGetQuery(query.c_str() ,sock))
+{
+ errorStr = "Couldn't restore UserStat(on query):\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+if (!(res=mysql_store_result(sock)))
+{
+ errorStr = "Couldn't restore UserStat(on getting result):\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+row = mysql_fetch_row(res);
+
+unsigned int startPos=0;
+
+char s[22];
+uint64_t traffU[DIR_NUM];
+uint64_t traffD[DIR_NUM];
+
+for (int i = 0; i < DIR_NUM; i++)
+ {
+ sprintf(s, "D%d", i);
+ if (GetULongLongInt(row[startPos+i*2],&traffD[i], 0) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' stat not read. Parameter " + string(s);
+ mysql_close(sock);
+ return -1;
+ }
+ stat->down = traffD;
+
+ sprintf(s, "U%d", i);
+ if (GetULongLongInt(row[startPos+i*2+1], &traffU[i], 0) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' stat not read. Parameter " + string(s);
+ mysql_close(sock);
+ return -1;
+ }
+ stat->up = traffU;
+ }//for
+
+startPos += (2*DIR_NUM);
+
+if (GetDouble(row[startPos], &stat->cash, 0) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' stat not read. Parameter Cash";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetDouble(row[startPos+1],&stat->freeMb, 0) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' stat not read. Parameter FreeMb";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetDouble(row[startPos+2], &stat->lastCashAdd, 0) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' stat not read. Parameter LastCashAdd";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetTime(row[startPos+3], &stat->lastCashAddTime, 0) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' stat not read. Parameter LastCashAddTime";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetTime(row[startPos+4], &stat->passiveTime, 0) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' stat not read. Parameter PassiveTime";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetTime(row[startPos+5], &stat->lastActivityTime, 0) != 0)
+ {
+ mysql_free_result(res);
+ errorStr = "User \'" + login + "\' stat not read. Parameter LastActivityTime";
+ mysql_close(sock);
+ return -1;
+ }
+
+mysql_free_result(res);
+mysql_close(sock);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::SaveUserConf(const USER_CONF & conf, const string & login) const
+{
+string param;
+string res;
+
+strprintf(&res,"UPDATE users SET Password='%s', Passive=%d, Down=%d, DisabledDetailStat = %d, "\
+ "AlwaysOnline=%d, Tariff='%s', Address='%s', Phone='%s', Email='%s', "\
+ "Note='%s', RealName='%s', StgGroup='%s', Credit=%f, TariffChange='%s', ",
+ conf.password.c_str(),
+ conf.passive,
+ conf.disabled,
+ conf.disabledDetailStat,
+ conf.alwaysOnline,
+ conf.tariffName.c_str(),
+ (ReplaceStr(conf.address,badSyms,repSym)).c_str(),
+ (ReplaceStr(conf.phone,badSyms,repSym)).c_str(),
+ (ReplaceStr(conf.email,badSyms,repSym)).c_str(),
+ (ReplaceStr(conf.note,badSyms,repSym)).c_str(),
+ (ReplaceStr(conf.realName,badSyms,repSym)).c_str(),
+ (ReplaceStr(conf.group,badSyms,repSym)).c_str(),
+ conf.credit,
+ conf.nextTariff.c_str()
+ );
+
+for (int i = 0; i < USERDATA_NUM; i++)
+ {
+ strprintf(¶m, " Userdata%d='%s',", i,
+ (ReplaceStr(conf.userdata[i],badSyms,repSym)).c_str());
+ res += param;
+ }
+
+strprintf(¶m, " CreditExpire=%d,", conf.creditExpire);
+res += param;
+
+stringstream ipStr;
+ipStr << conf.ips;
+
+strprintf(¶m, " IP='%s'", ipStr.str().c_str());
+res += param;
+
+strprintf(¶m, " WHERE login='%s' LIMIT 1", login.c_str());
+res += param;
+
+if(MysqlSetQuery(res.c_str()))
+{
+ errorStr = "Couldn't save user conf:\n";
+ //errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::SaveUserStat(const USER_STAT & stat, const string & login) const
+{
+string param;
+string res;
+
+res = "UPDATE users SET";
+
+for (int i = 0; i < DIR_NUM; i++)
+ {
+ strprintf(¶m, " D%d=%lld,", i, stat.down[i]);
+ res += param;
+
+ strprintf(¶m, " U%d=%lld,", i, stat.up[i]);
+ res += param;
+ }
+
+strprintf(¶m, " Cash=%f, FreeMb=%f, LastCashAdd=%f, LastCashAddTime=%d,"\
+ " PassiveTime=%d, LastActivityTime=%d",
+ stat.cash,
+ stat.freeMb,
+ stat.lastCashAdd,
+ stat.lastCashAddTime,
+ stat.passiveTime,
+ stat.lastActivityTime
+ );
+res += param;
+
+strprintf(¶m, " WHERE login='%s' LIMIT 1", login.c_str());
+res += param;
+
+if(MysqlSetQuery(res.c_str()))
+{
+ errorStr = "Couldn't save user stat:\n";
+// errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::WriteLogString(const string & str, const string & login) const
+{
+string res, tempStr;
+time_t t;
+tm * lt;
+
+t = time(NULL);
+lt = localtime(&t);
+
+MYSQL_RES* result;
+MYSQL * sock;
+strprintf(&tempStr, "logs_%02d_%4d", lt->tm_mon+1, lt->tm_year+1900);
+if (!(sock=MysqlConnect())){
+ errorStr = "Couldn't connect to Server";
+ return -1;
+}
+if (!(result=mysql_list_tables(sock,tempStr.c_str() )))
+{
+ errorStr = "Couldn't get table " + tempStr + ":\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+unsigned int num_rows = mysql_num_rows(result);
+
+mysql_free_result(result);
+
+if (num_rows < 1)
+{
+ sprintf(qbuf,"CREATE TABLE logs_%02d_%4d (unid INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, login VARCHAR(40),text TEXT)",
+ lt->tm_mon+1, lt->tm_year+1900);
+
+ if(MysqlQuery(qbuf,sock))
+ {
+ errorStr = "Couldn't create WriteDetailedStat table:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+}
+
+strprintf(&res, "%s -- %s",LogDate(t), str.c_str());
+
+string send;
+
+strprintf(&send,"INSERT INTO logs_%02d_%4d SET login='%s', text='%s'",
+ lt->tm_mon+1, lt->tm_year+1900,
+ login.c_str(), (ReplaceStr(res,badSyms,repSym)).c_str());
+
+if(MysqlQuery(send.c_str(),sock))
+{
+ errorStr = "Couldn't write log string:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+mysql_close(sock);
+return 0;
+
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::WriteUserChgLog(const string & login,
+ const string & admLogin,
+ uint32_t admIP,
+ const string & paramName,
+ const string & oldValue,
+ const string & newValue,
+ const string & message) const
+{
+string userLogMsg = "Admin \'" + admLogin + "\', " + inet_ntostring(admIP) + ": \'"
+ + paramName + "\' parameter changed from \'" + oldValue +
+ "\' to \'" + newValue + "\'. " + message;
+
+return WriteLogString(userLogMsg, login);
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::WriteUserConnect(const string & login, uint32_t ip) const
+{
+string logStr = "Connect, " + inet_ntostring(ip);
+return WriteLogString(logStr, login);
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::WriteUserDisconnect(const string & login,
+ const DIR_TRAFF & up,
+ const DIR_TRAFF & down,
+ const DIR_TRAFF & sessionUp,
+ const DIR_TRAFF & sessionDown,
+ double cash,
+ double freeMb,
+ const std::string & reason) const
+{
+string logStr = "Disconnect, ";
+stringstream sssu;
+stringstream sssd;
+stringstream ssmu;
+stringstream ssmd;
+stringstream sscash;
+
+ssmu << up;
+ssmd << down;
+
+sssu << sessionUp;
+sssd << sessionDown;
+
+sscash << cash;
+
+logStr += " session upload: \'";
+logStr += sssu.str();
+logStr += "\' session download: \'";
+logStr += sssd.str();
+logStr += "\' month upload: \'";
+logStr += ssmu.str();
+logStr += "\' month download: \'";
+logStr += ssmd.str();
+logStr += "\' cash: \'";
+logStr += sscash.str();
+logStr += "\'";
+
+return WriteLogString(logStr, login);
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::SaveMonthStat(const USER_STAT & stat, int month, int year,
+ const string & login) const
+{
+string param, res;
+
+strprintf(&res, "INSERT INTO stat SET login='%s', month=%d, year=%d,",
+ login.c_str(), month+1, year+1900);
+
+for (int i = 0; i < DIR_NUM; i++)
+ {
+ strprintf(¶m, " U%d=%lld,", i, stat.up[i]);
+ res += param;
+
+ strprintf(¶m, " D%d=%lld,", i, stat.down[i]);
+ res += param;
+ }
+
+strprintf(¶m, " cash=%f", stat.cash);
+res += param;
+
+if(MysqlSetQuery(res.c_str()))
+{
+ errorStr = "Couldn't SaveMonthStat:\n";
+ //errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------*/
+int MYSQL_STORE::AddAdmin(const string & login) const
+{
+sprintf(qbuf,"INSERT INTO admins SET login='%s'", login.c_str());
+
+if(MysqlSetQuery(qbuf))
+{
+ errorStr = "Couldn't add admin:\n";
+ //errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------*/
+int MYSQL_STORE::DelAdmin(const string & login) const
+{
+sprintf(qbuf,"DELETE FROM admins where login='%s' LIMIT 1", login.c_str());
+
+if(MysqlSetQuery(qbuf))
+{
+ errorStr = "Couldn't delete admin:\n";
+ //errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------*/
+int MYSQL_STORE::SaveAdmin(const ADMIN_CONF & ac) const
+{
+char passwordE[2 * ADM_PASSWD_LEN + 2];
+char pass[ADM_PASSWD_LEN + 1];
+char adminPass[ADM_PASSWD_LEN + 1];
+
+memset(pass, 0, sizeof(pass));
+memset(adminPass, 0, sizeof(adminPass));
+
+BLOWFISH_CTX ctx;
+EnDecodeInit(adm_enc_passwd, strlen(adm_enc_passwd), &ctx);
+
+strncpy(adminPass, ac.password.c_str(), ADM_PASSWD_LEN);
+adminPass[ADM_PASSWD_LEN - 1] = 0;
+
+for (int i = 0; i < ADM_PASSWD_LEN/8; i++)
+ {
+ EncodeString(pass + 8*i, adminPass + 8*i, &ctx);
+ }
+
+pass[ADM_PASSWD_LEN - 1] = 0;
+Encode12(passwordE, pass, ADM_PASSWD_LEN);
+
+sprintf(qbuf,"UPDATE admins SET password='%s', ChgConf=%d, ChgPassword=%d, "\
+ "ChgStat=%d, ChgCash=%d, UsrAddDel=%d, ChgTariff=%d, ChgAdmin=%d "\
+ "WHERE login='%s' LIMIT 1",
+ passwordE,
+ ac.priv.userConf,
+ ac.priv.userPasswd,
+ ac.priv.userStat,
+ ac.priv.userCash,
+ ac.priv.userAddDel,
+ ac.priv.tariffChg,
+ ac.priv.adminChg,
+ ac.login.c_str()
+ );
+
+if(MysqlSetQuery(qbuf))
+{
+ errorStr = "Couldn't save admin:\n";
+ //errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::RestoreAdmin(ADMIN_CONF * ac, const string & login) const
+{
+char pass[ADM_PASSWD_LEN + 1];
+char password[ADM_PASSWD_LEN + 1];
+char passwordE[2*ADM_PASSWD_LEN + 2];
+BLOWFISH_CTX ctx;
+
+string p;
+MYSQL_RES *res;
+MYSQL_ROW row;
+MYSQL * sock;
+sprintf(qbuf,"SELECT * FROM admins WHERE login='%s' LIMIT 1", login.c_str());
+
+if(MysqlGetQuery(qbuf,sock))
+{
+ errorStr = "Couldn't restore admin:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+if (!(res=mysql_store_result(sock)))
+{
+ errorStr = "Couldn't restore admin:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+if ( mysql_num_rows(res) == 0)
+{
+ mysql_free_result(res);
+ errorStr = "Couldn't restore admin as couldn't found him in table.\n";
+ mysql_close(sock);
+ return -1;
+}
+
+row = mysql_fetch_row(res);
+
+p = row[1];
+int a;
+
+if(p.length() == 0)
+{
+ mysql_free_result(res);
+ errorStr = "Error in parameter password";
+ mysql_close(sock);
+ return -1;
+}
+
+memset(passwordE, 0, sizeof(passwordE));
+strncpy(passwordE, p.c_str(), 2*ADM_PASSWD_LEN);
+
+memset(pass, 0, sizeof(pass));
+
+if (passwordE[0] != 0)
+ {
+ Decode21(pass, passwordE);
+ EnDecodeInit(adm_enc_passwd, strlen(adm_enc_passwd), &ctx);
+
+ for (int i = 0; i < ADM_PASSWD_LEN/8; i++)
+ {
+ DecodeString(password + 8*i, pass + 8*i, &ctx);
+ }
+ }
+else
+ {
+ password[0] = 0;
+ }
+
+ac->password = password;
+
+if (GetInt(row[2], &a, 0) == 0)
+ ac->priv.userConf = a;
+else
+ {
+ mysql_free_result(res);
+ errorStr = "Error in parameter ChgConf";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetInt(row[3], &a, 0) == 0)
+ ac->priv.userPasswd = a;
+else
+ {
+ mysql_free_result(res);
+ errorStr = "Error in parameter ChgPassword";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetInt(row[4], &a, 0) == 0)
+ ac->priv.userStat = a;
+else
+ {
+ mysql_free_result(res);
+ errorStr = "Error in parameter ChgStat";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetInt(row[5], &a, 0) == 0)
+ ac->priv.userCash = a;
+else
+ {
+ mysql_free_result(res);
+ errorStr = "Error in parameter ChgCash";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetInt(row[6], &a, 0) == 0)
+ ac->priv.userAddDel = a;
+else
+ {
+ mysql_free_result(res);
+ errorStr = "Error in parameter UsrAddDel";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetInt(row[7], &a, 0) == 0)
+ ac->priv.tariffChg = a;
+else
+ {
+ mysql_free_result(res);
+ errorStr = "Error in parameter ChgTariff";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetInt(row[8], &a, 0) == 0)
+ ac->priv.adminChg = a;
+else
+ {
+ mysql_free_result(res);
+ errorStr = "Error in parameter ChgAdmin";
+ mysql_close(sock);
+ return -1;
+ }
+
+mysql_free_result(res);
+mysql_close(sock);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::AddTariff(const string & name) const
+{
+sprintf(qbuf,"INSERT INTO tariffs SET name='%s'", name.c_str());
+
+if(MysqlSetQuery(qbuf))
+{
+ errorStr = "Couldn't add tariff:\n";
+// errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::DelTariff(const string & name) const
+{
+sprintf(qbuf,"DELETE FROM tariffs WHERE name='%s' LIMIT 1", name.c_str());
+
+if(MysqlSetQuery(qbuf))
+{
+ errorStr = "Couldn't delete tariff: ";
+// errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::RestoreTariff(TARIFF_DATA * td, const string & tariffName) const
+{
+MYSQL_RES *res;
+MYSQL_ROW row;
+MYSQL * sock;
+sprintf(qbuf,"SELECT * FROM tariffs WHERE name='%s' LIMIT 1", tariffName.c_str());
+
+if(MysqlGetQuery(qbuf,sock))
+{
+ errorStr = "Couldn't restore Tariff:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+if (!(res=mysql_store_result(sock)))
+{
+ errorStr = "Couldn't restore Tariff:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+string str;
+td->tariffConf.name = tariffName;
+
+row = mysql_fetch_row(res);
+
+string param;
+for (int i = 0; i<DIR_NUM; i++)
+ {
+ strprintf(¶m, "Time%d", i);
+ str = row[6+i*8];
+ if (str.length() == 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ mysql_close(sock);
+ return -1;
+ }
+
+ ParseTariffTimeStr(str.c_str(),
+ td->dirPrice[i].hDay,
+ td->dirPrice[i].mDay,
+ td->dirPrice[i].hNight,
+ td->dirPrice[i].mNight);
+
+ strprintf(¶m, "PriceDayA%d", i);
+ if (GetDouble(row[1+i*8], &td->dirPrice[i].priceDayA, 0.0) < 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ mysql_close(sock);
+ return -1;
+ }
+ td->dirPrice[i].priceDayA /= (1024*1024);
+
+ strprintf(¶m, "PriceDayB%d", i);
+ if (GetDouble(row[2+i*8], &td->dirPrice[i].priceDayB, 0.0) < 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ mysql_close(sock);
+ return -1;
+ }
+ td->dirPrice[i].priceDayB /= (1024*1024);
+
+ strprintf(¶m, "PriceNightA%d", i);
+ if (GetDouble(row[3+i*8], &td->dirPrice[i].priceNightA, 0.0) < 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ mysql_close(sock);
+ return -1;
+ }
+ td->dirPrice[i].priceNightA /= (1024*1024);
+
+ strprintf(¶m, "PriceNightB%d", i);
+ if (GetDouble(row[4+i*8], &td->dirPrice[i].priceNightB, 0.0) < 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ mysql_close(sock);
+ return -1;
+ }
+ td->dirPrice[i].priceNightB /= (1024*1024);
+
+ strprintf(¶m, "Threshold%d", i);
+ if (GetInt(row[5+i*8], &td->dirPrice[i].threshold, 0) < 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ mysql_close(sock);
+ return -1;
+ }
+
+ strprintf(¶m, "SinglePrice%d", i);
+ if (GetInt(row[8+i*8], &td->dirPrice[i].singlePrice, 0) < 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ mysql_close(sock);
+ return -1;
+ }
+
+ strprintf(¶m, "NoDiscount%d", i);
+ if (GetInt(row[7+i*8], &td->dirPrice[i].noDiscount, 0) < 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ mysql_close(sock);
+ return -1;
+ }
+ }//main for
+
+if (GetDouble(row[2+8*DIR_NUM], &td->tariffConf.fee, 0.0) < 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter Fee";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetDouble(row[3+8*DIR_NUM], &td->tariffConf.free, 0.0) < 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter Free";
+ mysql_close(sock);
+ return -1;
+ }
+
+if (GetDouble(row[1+8*DIR_NUM], &td->tariffConf.passiveCost, 0.0) < 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter PassiveCost";
+ mysql_close(sock);
+ return -1;
+ }
+
+ str = row[4+8*DIR_NUM];
+ param = "TraffType";
+
+ if (str.length() == 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ mysql_close(sock);
+ return -1;
+ }
+
+if (!strcasecmp(str.c_str(), "up"))
+ td->tariffConf.traffType = TRAFF_UP;
+else
+ if (!strcasecmp(str.c_str(), "down"))
+ td->tariffConf.traffType = TRAFF_DOWN;
+ else
+ if (!strcasecmp(str.c_str(), "up+down"))
+ td->tariffConf.traffType = TRAFF_UP_DOWN;
+ else
+ if (!strcasecmp(str.c_str(), "max"))
+ td->tariffConf.traffType = TRAFF_MAX;
+ else
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter TraffType incorrect";
+ mysql_close(sock);
+ return -1;
+ }
+
+mysql_free_result(res);
+mysql_close(sock);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::SaveTariff(const TARIFF_DATA & td, const string & tariffName) const
+{
+string param;
+
+string res="UPDATE tariffs SET";
+
+for (int i = 0; i < DIR_NUM; i++)
+ {
+ strprintf(¶m, " PriceDayA%d=%f,", i,
+ td.dirPrice[i].priceDayA * pt_mega);
+ res += param;
+
+ strprintf(¶m, " PriceDayB%d=%f,", i,
+ td.dirPrice[i].priceDayB * pt_mega);
+ res += param;
+
+ strprintf(¶m, " PriceNightA%d=%f,", i,
+ td.dirPrice[i].priceNightA * pt_mega);
+ res += param;
+
+ strprintf(¶m, " PriceNightB%d=%f,", i,
+ td.dirPrice[i].priceNightB * pt_mega);
+ res += param;
+
+ strprintf(¶m, " Threshold%d=%d,", i,
+ td.dirPrice[i].threshold);
+ res += param;
+
+ string s;
+ strprintf(¶m, " Time%d", i);
+
+ strprintf(&s, "%0d:%0d-%0d:%0d",
+ td.dirPrice[i].hDay,
+ td.dirPrice[i].mDay,
+ td.dirPrice[i].hNight,
+ td.dirPrice[i].mNight);
+
+ res += (param + "='" + s + "',");
+
+ strprintf(¶m, " NoDiscount%d=%d,", i,
+ td.dirPrice[i].noDiscount);
+ res += param;
+
+ strprintf(¶m, " SinglePrice%d=%d,", i,
+ td.dirPrice[i].singlePrice);
+ res += param;
+ }
+
+strprintf(¶m, " PassiveCost=%f,", td.tariffConf.passiveCost);
+res += param;
+
+strprintf(¶m, " Fee=%f,", td.tariffConf.fee);
+res += param;
+
+strprintf(¶m, " Free=%f,", td.tariffConf.free);
+res += param;
+
+switch (td.tariffConf.traffType)
+ {
+ case TRAFF_UP:
+ res += " TraffType='up'";
+ break;
+ case TRAFF_DOWN:
+ res += " TraffType='down'";
+ break;
+ case TRAFF_UP_DOWN:
+ res += " TraffType='up+down'";
+ break;
+ case TRAFF_MAX:
+ res += " TraffType='max'";
+ break;
+ }
+strprintf(¶m, " WHERE name='%s' LIMIT 1", tariffName.c_str());
+res += param;
+
+if(MysqlSetQuery(res.c_str()))
+{
+ errorStr = "Couldn't save admin:\n";
+ //errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::WriteDetailedStat(const map<IP_DIR_PAIR, STAT_NODE> * statTree,
+ time_t lastStat,
+ const string & login) const
+{
+string res, stTime, endTime, tempStr;
+time_t t;
+tm * lt;
+
+t = time(NULL);
+lt = localtime(&t);
+
+if (lt->tm_hour == 0 && lt->tm_min <= 5)
+ {
+ t -= 3600 * 24;
+ lt = localtime(&t);
+ }
+
+MYSQL_RES* result;
+MYSQL * sock;
+strprintf(&tempStr, "detailstat_%02d_%4d", lt->tm_mon+1, lt->tm_year+1900);
+
+if (!(sock=MysqlConnect())){
+ mysql_close(sock);
+ return -1;
+}
+
+if (!(result=mysql_list_tables(sock,tempStr.c_str() )))
+{
+ errorStr = "Couldn't get table " + tempStr + ":\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+unsigned int num_rows = mysql_num_rows(result);
+
+mysql_free_result(result);
+
+if (num_rows < 1)
+{
+ sprintf(qbuf,"CREATE TABLE detailstat_%02d_%4d (login VARCHAR(40) DEFAULT '',"\
+ "day TINYINT DEFAULT 0,startTime TIME,endTime TIME,"\
+ "IP VARCHAR(17) DEFAULT '',dir INT DEFAULT 0,"\
+ "down BIGINT DEFAULT 0,up BIGINT DEFAULT 0, cash DOUBLE DEFAULT 0.0, INDEX (login), INDEX(dir), INDEX(day), INDEX(IP))",
+ lt->tm_mon+1, lt->tm_year+1900);
+
+ if(MysqlQuery(qbuf,sock))
+ {
+ errorStr = "Couldn't create WriteDetailedStat table:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+}
+
+struct tm * lt1;
+struct tm * lt2;
+
+lt1 = localtime(&lastStat);
+
+int h1, m1, s1;
+int h2, m2, s2;
+
+h1 = lt1->tm_hour;
+m1 = lt1->tm_min;
+s1 = lt1->tm_sec;
+
+lt2 = localtime(&t);
+
+h2 = lt2->tm_hour;
+m2 = lt2->tm_min;
+s2 = lt2->tm_sec;
+
+strprintf(&stTime, "%02d:%02d:%02d", h1, m1, s1);
+strprintf(&endTime, "%02d:%02d:%02d", h2, m2, s2);
+
+strprintf(&res,"INSERT INTO detailstat_%02d_%4d SET login='%s',"\
+ "day=%d,startTime='%s',endTime='%s',",
+ lt->tm_mon+1, lt->tm_year+1900,
+ login.c_str(),
+ lt->tm_mday,
+ stTime.c_str(),
+ endTime.c_str()
+ );
+
+int retRes;
+map<IP_DIR_PAIR, STAT_NODE>::const_iterator stIter;
+stIter = statTree->begin();
+
+while (stIter != statTree->end())
+ {
+ strprintf(&tempStr,"IP='%s', dir=%d, down=%lld, up=%lld, cash=%f",
+ inet_ntostring(stIter->first.ip).c_str(),
+ stIter->first.dir,
+ stIter->second.down,
+ stIter->second.up,
+ stIter->second.cash
+ );
+
+ if( (retRes = MysqlQuery((res+tempStr).c_str(),sock)) )
+ {
+ errorStr = "Couldn't insert data in WriteDetailedStat:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+
+ result=mysql_store_result(sock);
+ if(result)
+ mysql_free_result(result);
+
+ ++stIter;
+ }
+mysql_close(sock);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::AddMessage(STG_MSG * msg, const string & login) const
+{
+struct timeval tv;
+
+gettimeofday(&tv, NULL);
+
+msg->header.id = ((long long)tv.tv_sec) * 1000000 + ((long long)tv.tv_usec);
+
+sprintf(qbuf,"INSERT INTO messages SET login='%s', id=%lld",
+ login.c_str(),
+ (long long)msg->header.id
+ );
+
+if(MysqlSetQuery(qbuf))
+{
+ errorStr = "Couldn't add message:\n";
+ //errorStr += mysql_error(sock);
+ return -1;
+}
+
+return EditMessage(*msg, login);
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::EditMessage(const STG_MSG & msg, const string & login) const
+{
+string res;
+
+strprintf(&res,"UPDATE messages SET type=%d, lastSendTime=%u, creationTime=%u, "\
+ "showTime=%u, stgRepeat=%d, repeatPeriod=%u, text='%s' "\
+ "WHERE login='%s' AND id=%lld LIMIT 1",
+ msg.header.type,
+ msg.header.lastSendTime,
+ msg.header.creationTime,
+ msg.header.showTime,
+ msg.header.repeat,
+ msg.header.repeatPeriod,
+ (ReplaceStr(msg.text,badSyms,repSym)).c_str(),
+ login.c_str(),
+ (long long)msg.header.id
+ );
+
+if(MysqlSetQuery(res.c_str()))
+{
+ errorStr = "Couldn't edit message:\n";
+ //errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::GetMessage(uint64_t id, STG_MSG * msg, const string & login) const
+{
+MYSQL_RES *res;
+MYSQL_ROW row;
+MYSQL * sock;
+
+sprintf(qbuf,"SELECT * FROM messages WHERE login='%s' AND id=%lld LIMIT 1",
+ login.c_str(), id);
+
+if(MysqlGetQuery(qbuf,sock))
+{
+ errorStr = "Couldn't GetMessage:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+if (!(res=mysql_store_result(sock)))
+{
+ errorStr = "Couldn't GetMessage:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+row = mysql_fetch_row(res);
+
+if(row[2]&&str2x(row[2], msg->header.type))
+{
+ mysql_free_result(res);
+ errorStr = "Invalid value in message header for user: " + login;
+ mysql_close(sock);
+ return -1;
+}
+
+if(row[3] && str2x(row[3], msg->header.lastSendTime))
+{
+ mysql_free_result(res);
+ errorStr = "Invalid value in message header for user: " + login;
+ mysql_close(sock);
+ return -1;
+}
+
+if(row[4] && str2x(row[4], msg->header.creationTime))
+{
+ mysql_free_result(res);
+ errorStr = "Invalid value in message header for user: " + login;
+ mysql_close(sock);
+ return -1;
+}
+
+if(row[5] && str2x(row[5], msg->header.showTime))
+{
+ mysql_free_result(res);
+ errorStr = "Invalid value in message header for user: " + login;
+ mysql_close(sock);
+ return -1;
+}
+
+if(row[6] && str2x(row[6], msg->header.repeat))
+{
+ mysql_free_result(res);
+ errorStr = "Invalid value in message header for user: " + login;
+ mysql_close(sock);
+ return -1;
+}
+
+if(row[7] && str2x(row[7], msg->header.repeatPeriod))
+{
+ mysql_free_result(res);
+ errorStr = "Invalid value in message header for user: " + login;
+ mysql_close(sock);
+ return -1;
+}
+
+msg->header.id = id;
+msg->text = row[8];
+
+mysql_free_result(res);
+mysql_close(sock);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::DelMessage(uint64_t id, const string & login) const
+{
+sprintf(qbuf,"DELETE FROM messages WHERE login='%s' AND id=%lld LIMIT 1",
+ login.c_str(),(long long)id);
+
+if(MysqlSetQuery(qbuf))
+{
+ errorStr = "Couldn't delete Message:\n";
+ //errorStr += mysql_error(sock);
+ return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::GetMessageHdrs(vector<STG_MSG_HDR> * hdrsList, const string & login) const
+{
+MYSQL_RES *res;
+MYSQL_ROW row;
+MYSQL * sock;
+sprintf(qbuf,"SELECT * FROM messages WHERE login='%s'", login.c_str());
+
+if(MysqlGetQuery(qbuf,sock))
+{
+ errorStr = "Couldn't GetMessageHdrs:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+if (!(res=mysql_store_result(sock)))
+{
+ errorStr = "Couldn't GetMessageHdrs:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+}
+
+unsigned int i, num_rows = mysql_num_rows(res);
+long long int unsigned id = 0;
+
+for (i=0; i<num_rows; i++)
+{
+ row = mysql_fetch_row(res);
+ if (str2x(row[1], id))
+ continue;
+
+ STG_MSG_HDR hdr;
+ if (row[2])
+ if(str2x(row[2], hdr.type))
+ continue;
+
+ if (row[3])
+ if(str2x(row[3], hdr.lastSendTime))
+ continue;
+
+ if (row[4])
+ if(str2x(row[4], hdr.creationTime))
+ continue;
+
+ if (row[5])
+ if(str2x(row[5], hdr.showTime))
+ continue;
+
+ if (row[6])
+ if(str2x(row[6], hdr.repeat))
+ continue;
+
+ if (row[7])
+ if(str2x(row[7], hdr.repeatPeriod))
+ continue;
+
+ hdr.id = id;
+ hdrsList->push_back(hdr);
+}
+
+mysql_free_result(res);
+mysql_close(sock);
+return 0;
+}
+//-----------------------------------------------------------------------------
+
+int MYSQL_STORE::MysqlSetQuery(const char * Query) const {
+
+ MYSQL * sock;
+ int ret=MysqlGetQuery(Query,sock);
+ mysql_close(sock);
+ return ret;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::MysqlGetQuery(const char * Query,MYSQL * & sock) const {
+ if (!(sock=MysqlConnect())) {
+ return -1;
+ }
+ return MysqlQuery(Query,sock);
+}
+//-----------------------------------------------------------------------------
+MYSQL * MYSQL_STORE::MysqlConnect() const {
+ MYSQL * sock;
+ if ( !(sock=mysql_init(NULL)) ){
+ errorStr= "mysql init susck\n";
+ return NULL;
+ }
+ if (!(sock = mysql_real_connect(sock,storeSettings.GetDBHost().c_str(),
+ storeSettings.GetDBUser().c_str(),storeSettings.GetDBPassword().c_str(),
+ 0,0,NULL,0)))
+ {
+ errorStr = "Couldn't connect to mysql engine! With error:\n";
+ errorStr += mysql_error(sock);
+ return NULL;
+ }
+ else{
+ if(mysql_select_db(sock, storeSettings.GetDBName().c_str())){
+ errorStr = "Database lost !\n";
+ return NULL;
+ }
+ }
+ return sock;
+}
+//-----------------------------------------------------------------------------
--- /dev/null
+ /*
+ $Revision: 1.4 $
+ $Date: 2010/01/19 11:07:57 $
+ */
+
+
+#ifndef FILE_STORE_H
+#define FILE_STORE_H
+
+#include <string>
+
+#include "base_settings.h"
+#include "base_store.h"
+#include "user_traff.h"
+#include <mysql/mysql.h>
+
+using namespace std;
+//-----------------------------------------------------------------------------
+extern "C" BASE_STORE * GetStore();
+//-----------------------------------------------------------------------------
+class MYSQL_STORE_SETTINGS//: public BASE_SETTINGS
+{
+public:
+ MYSQL_STORE_SETTINGS();
+ virtual ~MYSQL_STORE_SETTINGS();
+ virtual int ParseSettings(const MODULE_SETTINGS & s);
+ virtual const string & GetStrError() const;
+
+ string GetDBUser() const;
+ string GetDBPassword() const;
+ string GetDBHost() const;
+ string GetDBName() const;
+
+private:
+ const MODULE_SETTINGS * settings;
+
+ int ParseParam(const vector<PARAM_VALUE> & moduleParams,
+ const string & name, string & result);
+
+ string errorStr;
+
+ string dbUser;
+ string dbPass;
+ string dbName;
+ string dbHost;
+};
+//-----------------------------------------------------------------------------
+class MYSQL_STORE: public BASE_STORE
+{
+public:
+ MYSQL_STORE();
+ virtual ~MYSQL_STORE();
+ virtual const string & GetStrError() const;
+
+ //User
+ virtual int GetUsersList(vector<string> * usersList) const;
+ virtual int AddUser(const string & login) const;
+ virtual int DelUser(const string & login) const;
+ virtual int SaveUserStat(const USER_STAT & stat, const string & login) const;
+ virtual int SaveUserConf(const USER_CONF & conf, const string & login) const;
+ virtual int RestoreUserStat(USER_STAT * stat, const string & login) const;
+ virtual int RestoreUserConf(USER_CONF * conf, const string & login) const;
+ virtual int WriteUserChgLog(const string & login,
+ const string & admLogin,
+ uint32_t admIP,
+ const string & paramName,
+ const string & oldValue,
+ const string & newValue,
+ const string & message = "") const;
+ virtual int WriteUserConnect(const string & login, uint32_t ip) const;
+ virtual int WriteUserDisconnect(const string & login,
+ const DIR_TRAFF & up,
+ const DIR_TRAFF & down,
+ const DIR_TRAFF & sessionUp,
+ const DIR_TRAFF & sessionDown,
+ double cash,
+ double freeMb,
+ const std::string & reason) const;
+
+ virtual int WriteDetailedStat(const map<IP_DIR_PAIR, STAT_NODE> * statTree,
+ time_t lastStat,
+ const string & login) const;
+
+ virtual int AddMessage(STG_MSG * msg, const string & login) const;
+ virtual int EditMessage(const STG_MSG & msg, const string & login) const;
+ virtual int GetMessage(uint64_t id, STG_MSG * msg, const string & login) const;
+ virtual int DelMessage(uint64_t id, const string & login) const;
+ virtual int GetMessageHdrs(vector<STG_MSG_HDR> * hdrsList, const string & login) const;
+
+ virtual int SaveMonthStat(const USER_STAT & stat, int month, int year, const string & login) const;
+
+ //Admin
+ virtual int GetAdminsList(vector<string> * adminsList) const;
+ virtual int AddAdmin(const string & login) const;
+ virtual int DelAdmin(const string & login) const;
+ virtual int RestoreAdmin(ADMIN_CONF * ac, const string & login) const;
+ virtual int SaveAdmin(const ADMIN_CONF & ac) const;
+
+ //Tariff
+ virtual int GetTariffsList(vector<string> * tariffsList) const;
+ virtual int AddTariff(const string & name) const;
+ virtual int DelTariff(const string & name) const;
+ virtual int SaveTariff(const TARIFF_DATA & td, const string & tariffName) const;
+ virtual int RestoreTariff(TARIFF_DATA * td, const string & tariffName) const;
+
+ //Corparation
+ virtual int GetCorpsList(vector<string> *) const {return 0;};
+ virtual int SaveCorp(const CORP_CONF &) const {return 0;};
+ virtual int RestoreCorp(CORP_CONF *, const string &) const {return 0;};
+ virtual int AddCorp(const string &) const {return 0;};
+ virtual int DelCorp(const string &) const {return 0;};
+
+ // Services
+ virtual int GetServicesList(vector<string> *) const {return 0;};
+ virtual int SaveService(const SERVICE_CONF &) const {return 0;};
+ virtual int RestoreService(SERVICE_CONF *, const string &) const {return 0;};
+ virtual int AddService(const string &) const {return 0;};
+ virtual int DelService(const string &) const {return 0;};
+
+ //virtual BASE_SETTINGS * GetStoreSettings();
+ virtual void SetSettings(const MODULE_SETTINGS & s);
+ virtual int ParseSettings();
+ virtual const string & GetVersion() const;
+
+private:
+ virtual int WriteLogString(const string & str, const string & login) const;
+ int GetAllParams(vector<string> * ParamList, const string & table, const string & name) const;
+ int CheckAllTables(MYSQL * sock);
+ bool IsTablePresent(const string & str,MYSQL * sock);
+ mutable string errorStr;
+// int Reconnect();
+ int MysqlQuery(const char* sQuery,MYSQL * sock) const;
+ int MysqlGetQuery(const char * Query,MYSQL * & sock) const;
+ int MysqlSetQuery(const char * Query) const;
+ MYSQL * MysqlConnect() const ;
+ string version;
+ MYSQL_STORE_SETTINGS storeSettings;
+ MODULE_SETTINGS settings;
+ //mutable MYSQL mysql;
+ //mutable MYSQL* sock;
+};
+//-----------------------------------------------------------------------------
+
+#endif //FILE_STORE_H
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.4 2010/04/26 12:44:42 faust Exp $
+###############################################################################
+
+include ../../../../../Makefile.conf
+
+PROG = mod_store_postgresql.so
+
+SRCS = ./postgresql_store.cpp \
+ ./postgresql_store_admins.cpp \
+ ./postgresql_store_corporations.cpp \
+ ./postgresql_store_messages.cpp \
+ ./postgresql_store_services.cpp \
+ ./postgresql_store_tariffs.cpp \
+ ./postgresql_store_users.cpp \
+ ./postgresql_store_utils.cpp
+
+STGLIBS = -lstg_common -lstg_crypto
+
+PG_CFLAGS = $(shell pg_config --includedir)
+PG_LDFLAGS = $(shell pg_config --libdir)
+
+CXXFLAGS += -I $(PG_CFLAGS)
+LDFLAGS += -L $(PG_LDFLAGS)
+
+LIBS += -lpq
+
+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>
+ */
+
+/*
+ * This file contains a realization of a base postgresql-storage plugin class
+ *
+ * v. 1.3
+ * FreeMb logging on dosconnects added
+ *
+ * v. 1.2
+ * Reconnection on faults added
+ *
+ * v. 1.1
+ * tb_stats removed
+ *
+ * v. 1.0
+ * Initial implementation
+ *
+ * $Revision: 1.5 $
+ * $Date: 2010/01/06 10:43:48 $
+ *
+ */
+
+#include <string>
+#include <vector>
+#include <algorithm>
+
+#include <libpq-fe.h>
+
+#include "postgresql_store.h"
+#include "postgresql_store_utils.h"
+#include "base_settings.h"
+
+class POSTGRESQL_STORE_CREATOR
+{
+public:
+ POSTGRESQL_STORE_CREATOR()
+ : pqStore(new POSTGRESQL_STORE())
+ {
+ };
+ ~POSTGRESQL_STORE_CREATOR()
+ {
+ delete pqStore;
+ };
+ POSTGRESQL_STORE * GetStore() { return pqStore; };
+private:
+ POSTGRESQL_STORE * pqStore;
+} pqStoreeCreator;
+
+//-----------------------------------------------------------------------------
+BASE_STORE * GetStore()
+{
+return pqStoreeCreator.GetStore();
+}
+
+//-----------------------------------------------------------------------------
+POSTGRESQL_STORE::POSTGRESQL_STORE()
+ : connection(NULL)
+{
+server = "localhost";
+database = "stargazer";
+user = "stg";
+password = "123456";
+versionString = "postgresql_store v.1.3";
+pthread_mutex_init(&mutex, NULL);
+}
+//-----------------------------------------------------------------------------
+POSTGRESQL_STORE::~POSTGRESQL_STORE()
+{
+if (connection)
+ {
+ PQfinish(connection);
+ }
+pthread_mutex_destroy(&mutex);
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::ParseSettings()
+{
+std::vector<PARAM_VALUE>::iterator i;
+string s;
+
+for(i = settings.moduleParams.begin(); i != settings.moduleParams.end(); ++i)
+ {
+ s = i->param;
+ std::transform(s.begin(), s.end(), s.begin(), ToLower());
+ if (s == "server")
+ {
+ server = *(i->value.begin());
+ }
+ if (s == "database")
+ {
+ database = *(i->value.begin());
+ }
+ if (s == "user")
+ {
+ user = *(i->value.begin());
+ }
+ if (s == "password")
+ {
+ password = *(i->value.begin());
+ }
+ }
+
+clientEncoding = "KOI8";
+
+return Connect();
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::Connect()
+{
+std::string params;
+params = "host=" + server + " "
+ + "dbname=" + database + " "
+ + "user=" + user + " "
+ + "password=" + password;
+
+connection = PQconnectdb(params.c_str());
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ strError = PQerrorMessage(connection);
+ printfd(__FILE__, "POSTGRESQL_STORE::Connect(): '%s'\n", strError.c_str());
+ return 1;
+ }
+
+if (PQsetClientEncoding(connection, clientEncoding.c_str()))
+ {
+ strError = PQerrorMessage(connection);
+ printfd(__FILE__, "POSTGRESQL_STORE::Connect(): '%s'\n", strError.c_str());
+ return 1;
+ }
+
+return CheckVersion();
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::Reset() const
+{
+PQreset(connection);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ strError = PQerrorMessage(connection);
+ printfd(__FILE__, "POSTGRESQL_STORE::Reset(): '%s'\n", strError.c_str());
+ return 1;
+ }
+
+if (PQsetClientEncoding(connection, clientEncoding.c_str()))
+ {
+ strError = PQerrorMessage(connection);
+ printfd(__FILE__, "POSTGRESQL_STORE::Reset(): '%s'\n", strError.c_str());
+ return 1;
+ }
+
+return CheckVersion();
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::CheckVersion() const
+{
+
+if (StartTransaction())
+ {
+ strError = "Failed to start transaction";
+ printfd(__FILE__, "POSTGRESQL_STORE::CheckVersion(): '%s'\n", strError.c_str());
+ return -1;
+ }
+
+PGresult * result = PQexec(connection, "SELECT MAX(version) FROM tb_info");
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::CheckVersion(): '%s'\n");
+ RollbackTransaction();
+ return -1;
+ }
+
+if (str2x(PQgetvalue(result, 0, 0), version))
+ {
+ strError = "Invalid DB version";
+ PQclear(result);
+ RollbackTransaction();
+ printfd(__FILE__, "POSTGRESQL_STORE::CheckVersion(): '%s'\n", strError.c_str());
+ return -1;
+ }
+
+PQclear(result);
+
+if (version < DB_MIN_VERSION)
+ {
+ strError = "DB version too old";
+ RollbackTransaction();
+ printfd(__FILE__, "POSTGRESQL_STORE::CheckVersion(): '%s'\n", strError.c_str());
+ return -1;
+ }
+
+if (version < 6)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::CheckVersion(): I recommend you to upgrade your DB to higher version to support FreeMb logging on disconnect. Current version is %d\n", version);
+ }
+
+if (CommitTransaction())
+ {
+ strError = "Failed to commit transaction";
+ printfd(__FILE__, "POSTGRESQL_STORE::CheckVersion(): '%s'\n", strError.c_str());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
--- /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>
+ */
+
+/*
+ * PostgreSQL storage class definition
+ *
+ * $Revision: 1.8 $
+ * $Date: 2010/01/19 11:06:53 $
+ *
+ */
+
+#ifndef POSTGRESQL_STORE_H
+#define POSTGRESQL_STORE_H
+
+#include <libpq-fe.h>
+
+#include <string>
+#include <vector>
+#include <map>
+
+#include "base_store.h"
+
+// Minimal DB version is 5
+// Recommended DB version is 6 (support FreeMb logging on disconnects)
+#define DB_MIN_VERSION 5
+
+extern "C" BASE_STORE * GetStore();
+
+class POSTGRESQL_STORE : public BASE_STORE {
+public:
+ POSTGRESQL_STORE();
+ virtual ~POSTGRESQL_STORE();
+
+ // Users
+ int GetUsersList(std::vector<std::string> * usersList) const;
+ int AddUser(const std::string & login) const;
+ int DelUser(const std::string & login) const;
+ int SaveUserStat(const USER_STAT & stat, const std::string & login) const;
+ int SaveUserConf(const USER_CONF & conf, const std::string & login) const;
+ int RestoreUserStat(USER_STAT * stat, const std::string & login) const;
+ int RestoreUserConf(USER_CONF * conf, const std::string & login) const;
+ int WriteUserChgLog(const std::string & login,
+ const std::string & admLogin,
+ uint32_t admIP,
+ const std::string & paramName,
+ const std::string & oldValue,
+ const std::string & newValue,
+ const std::string & message) const;
+ int WriteUserConnect(const std::string & login, uint32_t ip) const;
+ int WriteUserDisconnect(const std::string & login,
+ const DIR_TRAFF & up,
+ const DIR_TRAFF & down,
+ const DIR_TRAFF & sessionUp,
+ const DIR_TRAFF & sessionDown,
+ double cash,
+ double freeMb,
+ const std::string & reason) const;
+ int WriteDetailedStat(const std::map<IP_DIR_PAIR, STAT_NODE> * statTree,
+ time_t lastStat,
+ const std::string & login) const;
+
+ // Messages
+ int AddMessage(STG_MSG * msg, const std::string & login) const;
+ int EditMessage(const STG_MSG & msg, const std::string & login) const;
+ int GetMessage(uint64_t id, STG_MSG * msg, const std::string & login) const;
+ int DelMessage(uint64_t id, const std::string & login) const;
+ int GetMessageHdrs(std::vector<STG_MSG_HDR> * hdrsList, const std::string & login) const;
+
+ // Stats
+ int SaveMonthStat(const USER_STAT & stat, int month, int year, const std::string & login) const;
+
+ // Admins
+ int GetAdminsList(std::vector<std::string> * adminsList) const;
+ int SaveAdmin(const ADMIN_CONF & ac) const;
+ int RestoreAdmin(ADMIN_CONF * ac, const std::string & login) const;
+ int AddAdmin(const std::string & login) const;
+ int DelAdmin(const std::string & login) const;
+
+ // Tariffs
+ int GetTariffsList(std::vector<std::string> * tariffsList) const;
+ int AddTariff(const std::string & name) const;
+ int DelTariff(const string & name) const;
+ int SaveTariff(const TARIFF_DATA & td, const std::string & tariffName) const;
+ int RestoreTariff(TARIFF_DATA * td, const std::string & tariffName) const;
+
+ // Corporations
+ int GetCorpsList(std::vector<std::string> * corpsList) const;
+ int SaveCorp(const CORP_CONF & cc) const;
+ int RestoreCorp(CORP_CONF * cc, const std::string & name) const;
+ int AddCorp(const std::string & name) const;
+ int DelCorp(const std::string & name) const;
+
+ // Services
+ int GetServicesList(std::vector<std::string> * servicesList) const;
+ int SaveService(const SERVICE_CONF & sc) const;
+ int RestoreService(SERVICE_CONF * sc, const std::string & name) const;
+ int AddService(const std::string & name) const;
+ int DelService(const std::string & name) const;
+
+ // Settings
+ inline void SetSettings(const MODULE_SETTINGS & s) { settings = s; };
+ int ParseSettings();
+
+ inline const string & GetStrError() const { return strError; };
+ inline const string & GetVersion() const { return versionString; };
+private:
+ std::string versionString;
+ mutable std::string strError;
+ std::string server;
+ std::string database;
+ std::string user;
+ std::string password;
+ std::string clientEncoding;
+ MODULE_SETTINGS settings;
+ mutable pthread_mutex_t mutex;
+ mutable int version;
+
+ PGconn * connection;
+
+ int StartTransaction() const;
+ int CommitTransaction() const;
+ int RollbackTransaction() const;
+
+ int EscapeString(std::string & value) const;
+
+ std::string Int2TS(uint32_t value) const;
+ uint32_t TS2Int(const std::string & value) const;
+
+ int SaveStat(const USER_STAT & stat, const std::string & login, int year = 0, int month = 0) const;
+
+ int SaveUserServices(uint32_t uid, const std::vector<std::string> & services) const;
+ int SaveUserData(uint32_t uid, const std::vector<std::string> & data) const;
+ int SaveUserIPs(uint32_t uid, const USER_IPS & ips) const;
+
+ void MakeDate(std::string & date, int year = 0, int month = 0) const;
+
+ int Connect();
+ int Reset() const;
+ int CheckVersion() const;
+};
+
+extern const volatile time_t stgTime;
+
+#endif //POSTGRESQL_STORE_H
+
--- /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>
+ */
+
+/*
+ * Administrators manipulation methods
+ *
+ * $Revision: 1.2 $
+ * $Date: 2009/06/09 12:32:39 $
+ *
+ */
+
+#include <string>
+#include <vector>
+#include <sstream>
+
+#include <libpq-fe.h>
+
+#include "postgresql_store.h"
+#include "stg_locker.h"
+#include "admin_conf.h"
+#include "blowfish.h"
+
+#define adm_enc_passwd "cjeifY8m3"
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::GetAdminsList(std::vector<std::string> * adminsList) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetAdminsList(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::GetAdminsList(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetAdminsList(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+result = PQexec(connection, "SELECT login FROM tb_admins");
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::GetAdminsList(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetAdminsList(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+int tuples = PQntuples(result);
+
+for (int i = 0; i < tuples; ++i)
+ {
+ adminsList->push_back(PQgetvalue(result, i, 0));
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetAdminsList(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::SaveAdmin(const ADMIN_CONF & ac) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+char encodedPass[2 * ADM_PASSWD_LEN + 2];
+char cryptedPass[ADM_PASSWD_LEN + 1];
+char adminPass[ADM_PASSWD_LEN + 1];
+BLOWFISH_CTX ctx;
+
+memset(cryptedPass, 0, ADM_PASSWD_LEN + 1);
+strncpy(adminPass, ac.password.c_str(), ADM_PASSWD_LEN);
+EnDecodeInit(adm_enc_passwd, sizeof(adm_enc_passwd), &ctx);
+
+for (int i = 0; i < ADM_PASSWD_LEN / 8; i++)
+ EncodeString(cryptedPass + 8 * i, adminPass + 8 * i, &ctx);
+
+cryptedPass[ADM_PASSWD_LEN] = 0;
+Encode12(encodedPass, cryptedPass, ADM_PASSWD_LEN);
+
+std::string password = encodedPass;
+std::string login = ac.login;
+
+if (EscapeString(password))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Failed to escape password'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (EscapeString(login))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Failed to escape login'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::stringstream query;
+query << "UPDATE tb_admins SET "
+ << "passwd = '" << password << "', "
+ << "chg_conf = " << ac.priv.userConf << ", "
+ << "chg_password = " << ac.priv.userPasswd << ", "
+ << "chg_stat = " << ac.priv.userStat << ", "
+ << "chg_cash = " << ac.priv.userCash << ", "
+ << "usr_add_del = " << ac.priv.userAddDel << ", "
+ << "chg_tariff = " << ac.priv.tariffChg << ", "
+ << "chg_admin = " << ac.priv.adminChg << " "
+ << "WHERE login = '" << login << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::RestoreAdmin(ADMIN_CONF * ac, const string & login) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+char cryptedPass[ADM_PASSWD_LEN + 1];
+char adminPass[ADM_PASSWD_LEN + 1];
+BLOWFISH_CTX ctx;
+
+std::string elogin = login;
+
+if (EscapeString(elogin))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Failed to escape login'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::stringstream query;
+query << "SELECT login, passwd, \
+ chg_conf, chg_password, chg_stat, \
+ chg_cash, usr_add_del, chg_tariff, \
+ chg_admin, chg_service, chg_corporation \
+ FROM tb_admins \
+ WHERE login = '" << elogin << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): '%s'\n", strError.c_str());
+ PQclear(result);
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+int tuples = PQntuples(result);
+
+if (tuples != 1)
+ {
+ strError = "Failed to fetch admin's data";
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
+ PQclear(result);
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+ac->login = PQgetvalue(result, 0, 0);
+ac->password = PQgetvalue(result, 0, 1);
+
+std::stringstream tuple;
+tuple << PQgetvalue(result, 0, 2) << " "
+ << PQgetvalue(result, 0, 3) << " "
+ << PQgetvalue(result, 0, 4) << " "
+ << PQgetvalue(result, 0, 5) << " "
+ << PQgetvalue(result, 0, 6) << " "
+ << PQgetvalue(result, 0, 7) << " "
+ << PQgetvalue(result, 0, 8) << " "
+ << PQgetvalue(result, 0, 9) << " "
+ << PQgetvalue(result, 0, 10);
+
+PQclear(result);
+
+tuple >> ac->priv.userConf
+ >> ac->priv.userPasswd
+ >> ac->priv.userStat
+ >> ac->priv.userCash
+ >> ac->priv.userAddDel
+ >> ac->priv.tariffChg
+ >> ac->priv.adminChg;
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Failed to commit transacion'\n");
+ return -1;
+ }
+
+if (ac->password == "")
+ {
+ return 0;
+ }
+
+Decode21(cryptedPass, ac->password.c_str());
+EnDecodeInit(adm_enc_passwd, sizeof(adm_enc_passwd), &ctx);
+for (int i = 0; i < ADM_PASSWD_LEN / 8; i++)
+ {
+ DecodeString(adminPass + 8 * i, cryptedPass + 8 * i, &ctx);
+ }
+ac->password = adminPass;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::AddAdmin(const string & login) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string elogin = login;
+
+if (EscapeString(elogin))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): 'Failed to escape login'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::stringstream query;
+query << "INSERT INTO tb_admins \
+ (login, passwd, \
+ chg_conf, chg_password, chg_stat, \
+ chg_cash, usr_add_del, chg_tariff, \
+ chg_admin, chg_service, chg_corporation) \
+ VALUES "
+ << "('" << elogin << "', \
+ '', 0, 0, 0, 0, 0, 0, 0, 0, 0)";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::DelAdmin(const string & login) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string elogin = login;
+
+if (EscapeString(elogin))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): 'Failed to escape login'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::stringstream query;
+query << "DELETE FROM tb_admins WHERE login = '" << elogin << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
--- /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>
+ */
+
+/*
+ * Corporations manipulation methods
+ *
+ * $Revision: 1.2 $
+ * $Date: 2009/06/09 12:32:39 $
+ *
+ */
+
+#include <string>
+#include <vector>
+#include <sstream>
+
+#include <libpq-fe.h>
+
+#include "postgresql_store.h"
+#include "stg_locker.h"
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::GetCorpsList(vector<string> * corpsList) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetCorpsList(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::GetCorpsList(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetCorpsList(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+result = PQexec(connection, "SELECT name FROM tb_corporations");
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::GetCorpsList(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetCorpsList(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+int tuples = PQntuples(result);
+
+for (int i = 0; i < tuples; ++i)
+ {
+ corpsList->push_back(PQgetvalue(result, i, 0));
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetCorpsList(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::SaveCorp(const CORP_CONF & cc) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string ename = cc.name;
+
+if (EscapeString(ename))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): 'Failed to escape name'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::stringstream query;
+query << "UPDATE tb_corporations SET "
+ << "cash = " << cc.cash
+ << "WHERE name = '" << ename << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::RestoreCorp(CORP_CONF * cc, const string & name) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string ename = name;
+
+if (EscapeString(ename))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Failed to escape name'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::stringstream query;
+query << "SELECT cash FROM tb_corporations WHERE name = '" << ename << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+int tuples = PQntuples(result);
+
+if (tuples != 1)
+ {
+ strError = "Failed to fetch corp's data";
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
+ PQclear(result);
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::stringstream tuple;
+tuple << PQgetvalue(result, 0, 0);
+
+PQclear(result);
+
+tuple >> cc->cash;
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::AddCorp(const string & name) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string ename = name;
+
+if (EscapeString(ename))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): 'Failed to escape name'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::stringstream query;
+query << "INSERT INTO tb_corporations \
+ (name, cash) \
+ VALUES \
+ ('" << ename << "', 0)";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::DelCorp(const string & name) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string ename = name;
+
+if (EscapeString(ename))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): 'Failed to escape name'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::stringstream query;
+query << "DELETE FROM tb_corporations WHERE name = '" << ename << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
--- /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>
+ */
+
+
+/*
+ * Messages manipualtion methods
+ *
+ * $Revision: 1.6 $
+ * $Date: 2009/07/15 11:19:42 $
+ *
+ */
+
+#include <string>
+#include <vector>
+#include <sstream>
+
+#include <libpq-fe.h>
+
+#include "postgresql_store.h"
+#include "stg_locker.h"
+#include "stg_message.h"
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::AddMessage(STG_MSG * msg, const string & login) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string elogin = login;
+std::string etext = msg->text;
+
+if (EscapeString(elogin))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to escape login'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (EscapeString(etext))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to escape message text'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::stringstream query;
+query << "SELECT sp_add_message("
+ << "'" << elogin << "', "
+ << "CAST(1 AS SMALLINT), " // Here need to be a version, but, it's uninitiated actually
+ << "CAST(" << msg->header.type << " AS SMALLINT), "
+ << "CAST('" << Int2TS(msg->header.lastSendTime) << "' AS TIMESTAMP), "
+ << "CAST('" << Int2TS(msg->header.creationTime) << "' AS TIMESTAMP), "
+ << msg->header.showTime << ", "
+ << "CAST(" << msg->header.repeat << " AS SMALLINT), "
+ << msg->header.repeatPeriod << ", "
+ << "'" << etext << "')";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+int tuples = PQntuples(result);
+
+if (tuples != 1)
+ {
+ strError = "Failed to fetch newlly added message ID";
+ printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
+ PQclear(result);
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::stringstream tuple;
+tuple << PQgetvalue(result, 0, 0);
+
+PQclear(result);
+
+tuple >> msg->header.id;
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::EditMessage(const STG_MSG & msg,
+ const string & login) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string elogin = login;
+std::string etext = msg.text;
+
+if (EscapeString(elogin))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Failed to escape login'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (EscapeString(etext))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Failed to escape message text'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::stringstream query;
+query << "UPDATE tb_messages SET "
+ << "fk_user = (SELECT pk_user FROM tb_users WHERE name = '" << elogin << "'), "
+ << "ver = " << msg.header.ver << ", "
+ << "msg_type = " << msg.header.type << ", "
+ << "last_send_time = CAST('" << Int2TS(msg.header.lastSendTime) << "' AS TIMESTAMP), "
+ << "creation_time = CAST('" << Int2TS(msg.header.creationTime) << "' AS TIMESTAMP), "
+ << "show_time = " << msg.header.showTime << ", "
+ << "repeat = " << msg.header.repeat << ", "
+ << "repeat_period = " << msg.header.repeatPeriod << ", "
+ << "msg_text = '" << etext << "' "
+ << "WHERE pk_message = " << msg.header.id;
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::GetMessage(uint64_t id,
+ STG_MSG * msg,
+ const string &) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+string login;
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::stringstream query;
+query << "SELECT ver, msg_type, last_send_time, \
+ creation_time, show_time, repeat, \
+ repeat_period, msg_text \
+ FROM tb_messages \
+ WHERE pk_message = " << id;
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+int tuples = PQntuples(result);
+
+if (tuples != 1)
+ {
+ strError = "Failed to fetch message data";
+ printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
+ PQclear(result);
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+/*std::stringstream tuple;
+
+for (int i = 0; i < 8; ++i)
+ {
+ tuple << PQgetvalue(result, 0, i) << " ";
+ }*/
+
+str2x(PQgetvalue(result, 0, 0), msg->header.ver);
+str2x(PQgetvalue(result, 0, 1), msg->header.type);
+msg->header.lastSendTime = TS2Int(PQgetvalue(result, 0, 2));
+msg->header.creationTime = TS2Int(PQgetvalue(result, 0, 3));
+str2x(PQgetvalue(result, 0, 4), msg->header.showTime);
+str2x(PQgetvalue(result, 0, 5), msg->header.repeat);
+str2x(PQgetvalue(result, 0, 6), msg->header.repeatPeriod);
+msg->text = PQgetvalue(result, 0, 7);
+
+PQclear(result);
+
+/*tuple >> msg->header.ver;
+tuple >> msg->header.type;
+tuple >> msg->header.lastSendTime;
+tuple >> msg->header.creationTime;
+tuple >> msg->header.showTime;
+tuple >> msg->header.repeat;
+tuple >> msg->header.repeatPeriod;
+tuple >> msg->text;*/
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::DelMessage(uint64_t id, const string &) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelMessage(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::DelMessage(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelMessage(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::stringstream query;
+query << "DELETE FROM tb_messages WHERE pk_message = " << id;
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::DelMessage(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelMessage(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelMessage(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::GetMessageHdrs(vector<STG_MSG_HDR> * hdrsList,
+ const string & login) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string elogin = login;
+
+if (EscapeString(elogin))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): 'Failed to escape login'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::stringstream query;
+query << "SELECT pk_message, ver, msg_type, \
+ last_send_time, creation_time, show_time, \
+ repeat, repeat_period \
+ FROM tb_messages \
+ WHERE fk_user IN \
+ (SELECT pk_user FROM tb_users \
+ WHERE name = '" << elogin << "')";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+int tuples = PQntuples(result);
+
+for (int i = 0; i < tuples; ++i)
+ {
+ std::stringstream tuple;
+ STG_MSG_HDR header;
+ tuple << PQgetvalue(result, i, 0) << " ";
+ tuple << PQgetvalue(result, i, 1) << " ";
+ tuple << PQgetvalue(result, i, 2) << " ";
+ header.lastSendTime = TS2Int(PQgetvalue(result, i, 3));
+ header.creationTime = TS2Int(PQgetvalue(result, i, 4));
+ tuple << PQgetvalue(result, i, 5) << " ";
+ tuple << PQgetvalue(result, i, 6) << " ";
+ tuple << PQgetvalue(result, i, 7) << " ";
+
+ tuple >> header.id;
+ tuple >> header.ver;
+ tuple >> header.type;
+ tuple >> header.showTime;
+ tuple >> header.repeat;
+ tuple >> header.repeatPeriod;
+ hdrsList->push_back(header);
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
--- /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>
+ */
+
+
+/*
+ * Services manipulation methods
+ *
+ * $Revision: 1.2 $
+ * $Date: 2009/06/09 12:32:40 $
+ *
+ */
+
+#include <string>
+#include <vector>
+#include <sstream>
+
+#include <libpq-fe.h>
+
+#include "postgresql_store.h"
+#include "stg_locker.h"
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::GetServicesList(vector<string> * servicesList) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetServicesList(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::GetServicesList(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetServicesList(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+result = PQexec(connection, "SELECT name FROM tb_services");
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::GetServicesList(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetServicesList(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+int tuples = PQntuples(result);
+
+for (int i = 0; i < tuples; ++i)
+ {
+ servicesList->push_back(PQgetvalue(result, i, 0));
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetServicesList(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::SaveService(const SERVICE_CONF & sc) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string ename = sc.name;
+std::string ecomment = sc.comment;
+
+if (EscapeString(ename))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to escape name'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (EscapeString(ecomment))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to escape comment'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::stringstream query;
+query << "UPDATE tb_services SET "
+ << "comment = '" << ecomment << "', "
+ << "cost = " << sc.cost << ", "
+ << "pay_day = " << sc.payDay << " "
+ << "WHERE name = '" << ename << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::RestoreService(SERVICE_CONF * sc,
+ const string & name) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string ename = name;
+
+if (EscapeString(ename))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Failed to escape name'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::stringstream query;
+query << "SELECT comment, cost, pay_day FROM tb_services WHERE name = '" << ename << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+int tuples = PQntuples(result);
+
+if (tuples != 1)
+ {
+ strError = "Failed to fetch service's data";
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
+ PQclear(result);
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::stringstream tuple;
+tuple << PQgetvalue(result, 0, 0) << " "
+ << PQgetvalue(result, 0, 1) << " "
+ << PQgetvalue(result, 0, 2);
+
+PQclear(result);
+
+tuple >> sc->comment
+ >> sc->cost
+ >> sc->payDay;
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::AddService(const string & name) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddService(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::AddService(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddService(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string ename = name;
+
+if (EscapeString(ename))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddService(): 'Failed to escape name'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddService(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::stringstream query;
+query << "INSERT INTO tb_services \
+ (name, comment, cost, pay_day) \
+ VALUES \
+ ('" << ename << "', '', 0, 0)";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::AddService(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddService(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddService(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::DelService(const string & name) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelService(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::DelService(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelService(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string ename = name;
+
+if (EscapeString(ename))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelService(): 'Failed to escape name'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelService(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::stringstream query;
+query << "DELETE FROM tb_services WHERE name = '" << ename << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::DelService(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelService(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelService(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
--- /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>
+ */
+
+/*
+ * Tariffs manipulation methods
+ *
+ * $Revision: 1.2 $
+ * $Date: 2009/06/09 12:32:40 $
+ *
+ */
+
+#include <string>
+#include <vector>
+#include <sstream>
+
+#include <libpq-fe.h>
+
+#include "postgresql_store.h"
+#include "stg_locker.h"
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::GetTariffsList(vector<string> * tariffsList) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+result = PQexec(connection, "SELECT name FROM tb_tariffs");
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+int tuples = PQntuples(result);
+
+for (int i = 0; i < tuples; ++i)
+ {
+ tariffsList->push_back(PQgetvalue(result, i, 0));
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::AddTariff(const string & name) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string ename = name;
+
+if (EscapeString(ename))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to escape name'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::stringstream query;
+query << "SELECT sp_add_tariff('" << ename << "', " << DIR_NUM << ")";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::DelTariff(const string & name) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string ename = name;
+
+if (EscapeString(ename))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to escape name'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::stringstream query;
+query << "DELETE FROM tb_tariffs WHERE name = '" << ename << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::SaveTariff(const TARIFF_DATA & td,
+ const string & tariffName) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string ename = tariffName;
+
+if (EscapeString(ename))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to escape name'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+int32_t id, i;
+double pda, pdb, pna, pnb;
+int threshold;
+
+std::stringstream query;
+query << "SELECT pk_tariff FROM tb_tariffs WHERE name = '" << ename << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+int tuples = PQntuples(result);
+
+if (tuples != 1)
+ {
+ strError = "Failed to fetch tariff ID";
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
+ PQclear(result);
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::stringstream tuple;
+tuple << PQgetvalue(result, 0, 0);
+
+PQclear(result);
+
+tuple >> id;
+
+query.str("");
+query << "UPDATE tb_tariffs SET \
+ fee = " << td.tariffConf.fee << ", \
+ free = " << td.tariffConf.free << ", \
+ passive_cost = " << td.tariffConf.passiveCost << ", \
+ traff_type = " << td.tariffConf.traffType << " \
+ WHERE pk_tariff = " << id;
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+for(i = 0; i < DIR_NUM; i++)
+ {
+
+ pda = td.dirPrice[i].priceDayA * 1024 * 1024;
+ pdb = td.dirPrice[i].priceDayB * 1024 * 1024;
+
+ if (td.dirPrice[i].singlePrice)
+ {
+ pna = pda;
+ pnb = pdb;
+ }
+ else
+ {
+ pna = td.dirPrice[i].priceNightA * 1024 * 1024;
+ pnb = td.dirPrice[i].priceNightB * 1024 * 1024;
+ }
+
+ if (td.dirPrice[i].noDiscount)
+ {
+ threshold = 0xffFFffFF;
+ }
+ else
+ {
+ threshold = td.dirPrice[i].threshold;
+ }
+
+ std::stringstream query;
+ query << "UPDATE tb_tariffs_params SET \
+ price_day_a = " << pda << ", \
+ price_day_b = " << pdb << ", \
+ price_night_a = " << pna << ", \
+ price_night_b = " << pnb << ", \
+ threshold = " << threshold << ", \
+ time_day_begins = CAST('" << td.dirPrice[i].hDay
+ << ":"
+ << td.dirPrice[i].mDay << "' AS TIME), \
+ time_day_ends = CAST('" << td.dirPrice[i].hNight
+ << ":"
+ << td.dirPrice[i].mNight << "' AS TIME) \
+ WHERE fk_tariff = " << id << " AND dir_num = " << i;
+
+ result = PQexec(connection, query.str().c_str());
+
+ if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+ PQclear(result);
+ }
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::RestoreTariff(TARIFF_DATA * td,
+ const string & tariffName) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string ename = tariffName;
+
+if (EscapeString(ename))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to escape name'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+td->tariffConf.name = tariffName;
+
+std::stringstream query;
+query << "SELECT pk_tariff, \
+ fee, \
+ free, \
+ passive_cost, \
+ traff_type \
+ FROM tb_tariffs WHERE name = '" << ename << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+int tuples = PQntuples(result);
+
+if (tuples != 1)
+ {
+ strError = "Failed to fetch tariff data";
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
+ PQclear(result);
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::stringstream tuple;
+tuple << PQgetvalue(result, 0, 0) << " ";
+tuple << PQgetvalue(result, 0, 1) << " ";
+tuple << PQgetvalue(result, 0, 2) << " ";
+tuple << PQgetvalue(result, 0, 3) << " ";
+tuple << PQgetvalue(result, 0, 4) << " ";
+
+int id;
+tuple >> id;
+tuple >> td->tariffConf.fee;
+tuple >> td->tariffConf.free;
+tuple >> td->tariffConf.passiveCost;
+tuple >> td->tariffConf.traffType;
+
+PQclear(result);
+
+query.str("");
+query << "SELECT dir_num, \
+ price_day_a, \
+ price_day_b, \
+ price_night_a, \
+ price_night_b, \
+ threshold, \
+ EXTRACT(hour FROM time_day_begins), \
+ EXTRACT(minute FROM time_day_begins), \
+ EXTRACT(hour FROM time_day_ends), \
+ EXTRACT(minute FROM time_day_ends) \
+ FROM tb_tariffs_params \
+ WHERE fk_tariff = " << id;
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+tuples = PQntuples(result);
+
+if (tuples != DIR_NUM)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Tariff params count and DIR_NUM does not feet (wanted %d, actually %d)'\n", DIR_NUM, tuples);
+ }
+
+for (int i = 0; i < std::min(tuples, DIR_NUM); ++i)
+ {
+ std::stringstream tuple;
+ tuple << PQgetvalue(result, i, 0) << " ";
+ tuple << PQgetvalue(result, i, 1) << " ";
+ tuple << PQgetvalue(result, i, 2) << " ";
+ tuple << PQgetvalue(result, i, 3) << " ";
+ tuple << PQgetvalue(result, i, 4) << " ";
+ tuple << PQgetvalue(result, i, 5) << " ";
+ tuple << PQgetvalue(result, i, 6) << " ";
+ tuple << PQgetvalue(result, i, 7) << " ";
+ tuple << PQgetvalue(result, i, 8) << " ";
+ tuple << PQgetvalue(result, i, 9) << " ";
+
+ int dir;
+
+ tuple >> dir;
+ tuple >> td->dirPrice[dir].priceDayA;
+ td->dirPrice[dir].priceDayA /= 1024 * 1024;
+ tuple >> td->dirPrice[dir].priceDayB;
+ td->dirPrice[dir].priceDayB /= 1024 * 1024;
+ tuple >> td->dirPrice[dir].priceNightA;
+ td->dirPrice[dir].priceNightA /= 1024 * 1024;
+ tuple >> td->dirPrice[dir].priceNightB;
+ td->dirPrice[dir].priceNightB /= 1024 * 1024;
+ tuple >> td->dirPrice[dir].threshold;
+ tuple >> td->dirPrice[dir].hDay;
+ tuple >> td->dirPrice[dir].mDay;
+ tuple >> td->dirPrice[dir].hNight;
+ tuple >> td->dirPrice[dir].mNight;
+
+ if (td->dirPrice[dir].priceDayA == td->dirPrice[dir].priceNightA &&
+ td->dirPrice[dir].priceDayB == td->dirPrice[dir].priceNightB)
+ {
+ td->dirPrice[dir].singlePrice = true;
+ }
+ else
+ {
+ td->dirPrice[dir].singlePrice = false;
+ }
+ if (td->dirPrice[dir].threshold == (int)0xffFFffFF)
+ {
+ td->dirPrice[dir].noDiscount = true;
+ }
+ else
+ {
+
+ td->dirPrice[dir].noDiscount = false;
+ }
+
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
--- /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>
+ */
+
+/*
+ * User manipulation methods
+ *
+ * $Revision: 1.14 $
+ * $Date: 2010/05/07 07:26:36 $
+ *
+ */
+
+#include <string>
+#include <vector>
+#include <sstream>
+#include <ctime>
+
+#include <libpq-fe.h>
+
+#include "stg_const.h"
+#include "postgresql_store.h"
+#include "stg_locker.h"
+#include "../../../stg_timer.h"
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::GetUsersList(vector<string> * usersList) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetUsersList(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::GetUsersList(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetUsersList(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+result = PQexec(connection, "SELECT name FROM tb_users");
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::GetUsersList(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetUsersList(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+int tuples = PQntuples(result);
+
+for (int i = 0; i < tuples; ++i)
+ {
+ usersList->push_back(PQgetvalue(result, i, 0));
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::GetUsersList(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::AddUser(const string & name) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string elogin = name;
+
+if (EscapeString(elogin))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): 'Failed to escape login'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::stringstream query;
+query << "SELECT sp_add_user('" << elogin << "')";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::DelUser(const string & login) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string elogin = login;
+
+if (EscapeString(elogin))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): 'Failed to escape login'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::stringstream query;
+query << "DELETE FROM tb_users WHERE name = '" << elogin << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::SaveUserStat(const USER_STAT & stat,
+ const string & login) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+return SaveStat(stat, login);
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::SaveStat(const USER_STAT & stat,
+ const string & login,
+ int year,
+ int month) const
+{
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string elogin = login;
+
+if (EscapeString(elogin))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Failed to escape login'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::stringstream query;
+query << "UPDATE tb_users SET "
+ "cash = " << stat.cash << ", "
+ "free_mb = " << stat.freeMb << ", "
+ "last_activity_time = CAST('" << Int2TS(stat.lastActivityTime) << "' AS TIMESTAMP), "
+ "last_cash_add = " << stat.lastCashAdd << ", "
+ "last_cash_add_time = CAST('" << Int2TS(stat.lastCashAddTime) << "' AS TIMESTAMP), "
+ "passive_time = " << stat.passiveTime << " "
+ "WHERE name = '" << elogin << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+std::string date;
+
+MakeDate(date, year, month);
+
+for (int dir = 0; dir < DIR_NUM; ++dir)
+ {
+ query.str("");
+ query << "SELECT sp_add_stats_traffic ("
+ "'" << elogin << "', "
+ "CAST('" << date << "' AS DATE), "
+ "CAST(" << dir << " AS SMALLINT), "
+ "CAST(" << stat.up[dir] << " AS BIGINT), "
+ "CAST(" << stat.down[dir] << " AS BIGINT))";
+
+ result = PQexec(connection, query.str().c_str());
+
+ if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+ PQclear(result);
+ }
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::SaveUserConf(const USER_CONF & conf,
+ const string & login) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string elogin = login;
+
+if (EscapeString(elogin))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape login'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::stringstream query;
+query << "SELECT pk_user FROM tb_users WHERE name = '" << elogin << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+int tuples = PQntuples(result);
+
+if (tuples != 1)
+ {
+ strError = "Failed to fetch user's ID";
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
+ PQclear(result);
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::stringstream tuple;
+tuple << PQgetvalue(result, 0, 0);
+
+PQclear(result);
+
+uint32_t uid;
+
+tuple >> uid;
+
+std::string eaddress = conf.address;
+std::string eemail = conf.email;
+std::string egroup = conf.group;
+std::string enote = conf.note;
+std::string epassword = conf.password;
+std::string ephone = conf.phone;
+std::string erealname = conf.realName;
+std::string etariffname = conf.tariffName;
+std::string enexttariff = conf.nextTariff;
+std::string ecorporation = conf.corp;
+
+if (EscapeString(eaddress))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape address'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (EscapeString(eemail))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape email'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (EscapeString(egroup))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape group'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (EscapeString(enote))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape note'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (EscapeString(epassword))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape password'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (EscapeString(ephone))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape phone'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (EscapeString(erealname))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape real name'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (EscapeString(etariffname))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape tariff name'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (EscapeString(enexttariff))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape next tariff name'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (EscapeString(ecorporation))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape corporation name'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+query.str("");
+query << "UPDATE tb_users SET "
+ "address = '" << eaddress << "', "
+ "always_online = " << (conf.alwaysOnline ? "'t'" : "'f'") << ", "
+ "credit = " << conf.credit << ", "
+ "credit_expire = CAST('" << Int2TS(conf.creditExpire) << "' AS TIMESTAMP), "
+ "disabled = " << (conf.disabled ? "'t'" : "'f'") << ", "
+ "disabled_detail_stat = " << (conf.disabledDetailStat ? "'t'" : "'f'") << ", "
+ "email = '" << eemail << "', "
+ "grp = '" << egroup << "', "
+ "note = '" << enote << "', "
+ "passive = " << (conf.passive ? "'t'" : "'f'") << ", "
+ "passwd = '" << epassword << "', "
+ "phone = '" << ephone << "', "
+ "real_name = '" << erealname << "', "
+ "fk_tariff = (SELECT pk_tariff "
+ "FROM tb_tariffs "
+ "WHERE name = '" << etariffname << "'), "
+ "fk_tariff_change = (SELECT pk_tariff "
+ "FROM tb_tariffs "
+ "WHERE name = '" << enexttariff << "'), "
+ "fk_corporation = (SELECT pk_corporation "
+ "FROM tb_corporations "
+ "WHERE name = '" << ecorporation << "') "
+ "WHERE pk_user = " << uid;
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+if (SaveUserServices(uid, conf.service))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to save user's services'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (SaveUserData(uid, conf.userdata))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to save user's data'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (SaveUserIPs(uid, conf.ips))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to save user's IPs'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::RestoreUserStat(USER_STAT * stat,
+ const string & login) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string elogin = login;
+
+if (EscapeString(elogin))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to escape login'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::stringstream query;
+query << "SELECT cash, free_mb, "
+ "last_activity_time, last_cash_add, "
+ "last_cash_add_time, passive_time "
+ "FROM tb_users "
+ "WHERE name = '" << elogin << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): '%s'\n", strError.c_str());
+ PQclear(result);
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+int tuples = PQntuples(result);
+
+if (tuples != 1)
+ {
+ strError = "Failed to fetch user's stat";
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
+ PQclear(result);
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::stringstream tuple;
+tuple << PQgetvalue(result, 0, 0) << " ";
+tuple << PQgetvalue(result, 0, 1) << " ";
+stat->lastActivityTime = TS2Int(PQgetvalue(result, 0, 2));
+tuple << PQgetvalue(result, 0, 3) << " ";
+stat->lastCashAddTime = TS2Int(PQgetvalue(result, 0, 4));
+tuple << PQgetvalue(result, 0, 5) << " ";
+
+PQclear(result);
+
+tuple >> stat->cash
+ >> stat->freeMb
+ >> stat->lastCashAdd
+ >> stat->passiveTime;
+
+query.str("");
+
+query << "SELECT dir_num, upload, download "
+ "FROM tb_stats_traffic "
+ "WHERE fk_user IN (SELECT pk_user FROM tb_users WHERE name = '" << elogin << "') AND "
+ "DATE_TRUNC('month', stats_date) = DATE_TRUNC('month', CAST('" << Int2TS(stgTime) << "' AS TIMESTAMP))";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): '%s'\n", strError.c_str());
+ PQclear(result);
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+tuples = PQntuples(result);
+
+for (int i = 0; i < tuples; ++i)
+ {
+ std::stringstream tuple;
+ tuple << PQgetvalue(result, i, 0) << " ";
+ tuple << PQgetvalue(result, i, 1) << " ";
+ tuple << PQgetvalue(result, i, 2) << " ";
+
+ int dir;
+
+ tuple >> dir;
+ tuple >> stat->up[dir];
+ tuple >> stat->down[dir];
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::RestoreUserConf(USER_CONF * conf,
+ const string & login) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string elogin = login;
+
+if (EscapeString(elogin))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to escape login'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::stringstream query;
+query << "SELECT tb_users.pk_user, tb_users.address, tb_users.always_online, "
+ "tb_users.credit, tb_users.credit_expire, tb_users.disabled, "
+ "tb_users.disabled_detail_stat, tb_users.email, tb_users.grp, "
+ "tb_users.note, tb_users.passive, tb_users.passwd, tb_users.phone, "
+ "tb_users.real_name, tf1.name, tf2.name, tb_corporations.name "
+ "FROM tb_users LEFT JOIN tb_tariffs AS tf1 "
+ "ON tf1.pk_tariff = tb_users.fk_tariff "
+ "LEFT JOIN tb_tariffs AS tf2 "
+ "ON tf2.pk_tariff = tb_users.fk_tariff_change "
+ "LEFT JOIN tb_corporations "
+ "ON tb_corporations.pk_corporation = tb_users.fk_corporation "
+ "WHERE tb_users.name = '" << elogin << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): '%s'\n", strError.c_str());
+ PQclear(result);
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+int tuples = PQntuples(result);
+
+if (tuples != 1)
+ {
+ strError = "Failed to fetch user's stat";
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
+ PQclear(result);
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+uint32_t uid;
+
+std::stringstream tuple;
+
+tuple << PQgetvalue(result, 0, 0) << " "; // uid
+conf->address = PQgetvalue(result, 0, 1); // address
+conf->alwaysOnline = !strncmp(PQgetvalue(result, 0, 2), "t", 1);
+tuple << PQgetvalue(result, 0, 3) << " "; // credit
+conf->creditExpire = TS2Int(PQgetvalue(result, 0, 4)); // creditExpire
+conf->disabled = !strncmp(PQgetvalue(result, 0, 5), "t", 1);
+conf->disabledDetailStat = !strncmp(PQgetvalue(result, 0, 6), "t", 1);
+conf->email = PQgetvalue(result, 0, 7); // email
+conf->group = PQgetvalue(result, 0, 8); // group
+conf->note = PQgetvalue(result, 0, 9); // note
+conf->passive = !strncmp(PQgetvalue(result, 0, 10), "t", 1);
+conf->password = PQgetvalue(result, 0, 11); // password
+conf->phone = PQgetvalue(result, 0, 12); // phone
+conf->realName = PQgetvalue(result, 0, 13); // realName
+conf->tariffName = PQgetvalue(result, 0, 14); // tariffName
+conf->nextTariff = PQgetvalue(result, 0, 15); // nextTariff
+conf->corp = PQgetvalue(result, 0, 16); // corp
+
+PQclear(result);
+
+if (conf->tariffName == "")
+ conf->tariffName = NO_TARIFF_NAME;
+if (conf->corp == "")
+ conf->corp = NO_CORP_NAME;
+
+tuple >> uid
+ >> conf->credit;
+
+query.str("");
+query << "SELECT name FROM tb_services "
+ "WHERE pk_service IN (SELECT fk_service "
+ "FROM tb_users_services "
+ "WHERE fk_user = " << uid << ")";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): '%s'\n", strError.c_str());
+ PQclear(result);
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+tuples = PQntuples(result);
+
+for (int i = 0; i < tuples; ++i)
+ {
+ conf->service.push_back(PQgetvalue(result, i, 0));
+ }
+
+PQclear(result);
+
+query.str("");
+query << "SELECT num, data "
+ "FROM tb_users_data "
+ "WHERE fk_user = " << uid;
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): '%s'\n", strError.c_str());
+ PQclear(result);
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+tuples = PQntuples(result);
+
+for (int i = 0; i < tuples; ++i)
+ {
+ int num;
+ if (str2x(PQgetvalue(result, i, 0), num))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to convert string to int'\n");
+ }
+ else
+ {
+ conf->userdata[i] = PQgetvalue(result, i, 1);
+ }
+ }
+
+PQclear(result);
+
+query.str("");
+query << "SELECT host(ip), masklen(ip) "
+ "FROM tb_allowed_ip "
+ "WHERE fk_user = " << uid;
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): '%s'\n", strError.c_str());
+ PQclear(result);
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+tuples = PQntuples(result);
+
+conf->ips.Erase();
+for (int i = 0; i < tuples; ++i)
+ {
+ IP_MASK ipm;
+
+ int ip, mask;
+
+ ip = inet_strington(PQgetvalue(result, i, 0));
+
+ if (str2x(PQgetvalue(result, i, 1), mask))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to fetch mask'\n");
+ continue;
+ }
+
+ ipm.ip = ip;
+ ipm.mask = mask;
+
+ conf->ips.Add(ipm);
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::WriteUserChgLog(const string & login,
+ const string & admLogin,
+ uint32_t admIP,
+ const string & paramName,
+ const string & oldValue,
+ const string & newValue,
+ const string & message = "") const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string elogin(login);
+std::string eadminLogin(admLogin);
+std::string eparam(paramName);
+std::string eold(oldValue);
+std::string enew(newValue);
+std::string emessage(message);
+
+if (EscapeString(elogin))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to escape login'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (EscapeString(eadminLogin))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to escape admin's login'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (EscapeString(eparam))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to escape param's name'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (EscapeString(eold))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to escape old value'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+if (EscapeString(enew))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to escape new value'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::stringstream query;
+query << "SELECT sp_add_param_log_entry("
+ "'" << elogin << "', "
+ "'" << eadminLogin << "', CAST('"
+ << inet_ntostring(admIP) << "/24' AS INET), "
+ "'" << eparam << "', "
+ "CAST('" << Int2TS(stgTime) << "' AS TIMESTAMP), "
+ "'" << eold << "', "
+ "'" << enew << "', "
+ "'" << emessage << "')";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::WriteUserConnect(const string & login, uint32_t ip) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string elogin(login);
+
+if (EscapeString(elogin))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): 'Failed to escape login'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::stringstream query;
+if (version < 6)
+ {
+ query << "SELECT sp_add_session_log_entry("
+ "'" << elogin << "', "
+ "CAST('" << Int2TS(stgTime) << "' AS TIMESTAMP), "
+ "'c', CAST('"
+ << inet_ntostring(ip) << "/32' AS INET), 0)";
+ }
+else
+ {
+ query << "SELECT sp_add_session_log_entry("
+ "'" << elogin << "', "
+ "CAST('" << Int2TS(stgTime) << "' AS TIMESTAMP), "
+ "'c', CAST('"
+ << inet_ntostring(ip) << "/32' AS INET), 0, 0, '')";
+ }
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::WriteUserDisconnect(const string & login,
+ const DIR_TRAFF & up,
+ const DIR_TRAFF & down,
+ const DIR_TRAFF & sessionUp,
+ const DIR_TRAFF & sessionDown,
+ double cash,
+ double freeMb,
+ const std::string & reason) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string elogin(login);
+
+if (EscapeString(elogin))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to escape login'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::string ereason(reason);
+
+if (EscapeString(ereason))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to escape reason'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+std::stringstream query;
+if (version < 6)
+ {
+ // Old database version - no freeMb logging support
+ query << "SELECT sp_add_session_log_entry("
+ "'" << elogin << "', "
+ "CAST('" << Int2TS(stgTime) << "' AS TIMESTAMP), "
+ "'d', CAST('0.0.0.0/0' AS INET), "
+ << cash << ")";
+ }
+else
+ {
+ query << "SELECT sp_add_session_log_entry("
+ "'" << elogin << "', "
+ "CAST('" << Int2TS(stgTime) << "' AS TIMESTAMP), "
+ "'d', CAST('0.0.0.0/0' AS INET), "
+ << cash << ", " << freeMb << ", '" << ereason << "')";
+ }
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+int tuples = PQntuples(result);
+
+if (tuples != 1)
+ {
+ strError = "Failed to fetch session's log ID";
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
+ PQclear(result);
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+uint32_t lid;
+
+if (str2x(PQgetvalue(result, 0, 0), lid))
+ {
+ strError = "Failed to convert string to int";
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): '%s'\n", strError.c_str());
+ PQclear(result);
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+PQclear(result);
+
+for (int i = 0; i < DIR_NUM; ++i)
+ {
+ std::stringstream query;
+ query << "INSERT INTO tb_sessions_data "
+ "(fk_session_log, "
+ "dir_num, "
+ "session_upload, "
+ "session_download, "
+ "month_upload, "
+ "month_download)"
+ "VALUES ("
+ << lid << ", "
+ << i << ", "
+ << sessionUp[i] << ", "
+ << sessionDown[i] << ", "
+ << up[i] << ", "
+ << down[i] << ")";
+
+ result = PQexec(connection, query.str().c_str());
+
+ if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+ PQclear(result);
+ }
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::WriteDetailedStat(const map<IP_DIR_PAIR, STAT_NODE> * statTree,
+ time_t lastStat,
+ const string & login) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (PQstatus(connection) != CONNECTION_OK)
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+ if (Reset())
+ {
+ strError = "Connection lost";
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): '%s'\n", strError.c_str());
+ return -1;
+ }
+ }
+
+PGresult * result;
+
+if (StartTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): 'Failed to start transaction'\n");
+ return -1;
+ }
+
+std::string elogin(login);
+
+if (EscapeString(elogin))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): 'Failed to escape login'\n");
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+map<IP_DIR_PAIR, STAT_NODE>::const_iterator it;
+time_t currTime = time(NULL);
+
+for (it = statTree->begin(); it != statTree->end(); ++it)
+ {
+ std::stringstream query;
+ query << "INSERT INTO tb_detail_stats "
+ "(till_time, from_time, fk_user, "
+ "dir_num, ip, download, upload, cost) "
+ "VALUES ("
+ "CAST('" << Int2TS(currTime) << "' AS TIMESTAMP), "
+ "CAST('" << Int2TS(lastStat) << "' AS TIMESTAMP), "
+ "(SELECT pk_user FROM tb_users WHERE name = '" << elogin << "'), "
+ << it->first.dir << ", "
+ << "CAST('" << inet_ntostring(it->first.ip) << "' AS INET), "
+ << it->second.down << ", "
+ << it->second.up << ", "
+ << it->second.cash << ")";
+
+ result = PQexec(connection, query.str().c_str());
+
+ if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): '%s'\n", strError.c_str());
+ if (RollbackTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): 'Failed to rollback transaction'\n");
+ }
+ return -1;
+ }
+
+ PQclear(result);
+ }
+
+if (CommitTransaction())
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): 'Failed to commit transaction'\n");
+ return -1;
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::SaveMonthStat(const USER_STAT & stat, int month, int year, const string & login) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+return SaveStat(stat, login, year, month);
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::SaveUserServices(uint32_t uid,
+ const std::vector<std::string> & services) const
+{
+PGresult * result;
+
+std::stringstream query;
+query << "DELETE FROM tb_users_services WHERE fk_user = " << uid;
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserServices(): '%s'\n", strError.c_str());
+ return -1;
+ }
+
+PQclear(result);
+
+std::vector<std::string>::const_iterator it;
+
+for (it = services.begin(); it != services.end(); ++it)
+ {
+ std::string ename = *it;
+
+ if (EscapeString(ename))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserServices(): 'Failed to escape service name'\n");
+ return -1;
+ }
+
+ std::stringstream query;
+ query << "INSERT INTO tb_users_services "
+ "(fk_user, fk_service) "
+ "VALUES "
+ "(" << uid << ", "
+ "(SELECT pk_service "
+ "FROM tb_services "
+ "WHERE name = '" << ename << "'))";
+
+ result = PQexec(connection, query.str().c_str());
+
+ if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserServices(): '%s'\n", strError.c_str());
+ return -1;
+ }
+
+ PQclear(result);
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::SaveUserIPs(uint32_t uid,
+ const USER_IPS & ips) const
+{
+PGresult * result;
+
+std::stringstream query;
+query << "DELETE FROM tb_allowed_ip WHERE fk_user = " << uid;
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserIPs(): '%s'\n", strError.c_str());
+ return -1;
+ }
+
+PQclear(result);
+
+for (int i = 0; i < ips.Count(); ++i)
+ {
+ std::stringstream query;
+ query << "INSERT INTO tb_allowed_ip "
+ "(fk_user, ip) "
+ "VALUES "
+ "(" << uid << ", CAST('"
+ << inet_ntostring(ips[i].ip) << "/"
+ << static_cast<int>(ips[i].mask) << "' AS INET))";
+
+ result = PQexec(connection, query.str().c_str());
+
+ if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserIPs(): '%s'\n", strError.c_str());
+ return -1;
+ }
+
+ PQclear(result);
+ }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::SaveUserData(uint32_t uid,
+ const std::vector<std::string> & data) const
+{
+for (unsigned i = 0; i < data.size(); ++i)
+ {
+ std::string edata = data[i];
+
+ if (EscapeString(edata))
+ {
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserData(): 'Failed to escape userdata field'\n");
+ return -1;
+ }
+
+ PGresult * result;
+
+ std::stringstream query;
+ query << "SELECT sp_set_user_data("
+ << uid << ", "
+ << "CAST(" << i << " AS SMALLINT), "
+ << "'" << edata << "')";
+
+ result = PQexec(connection, query.str().c_str());
+
+ if (PQresultStatus(result) != PGRES_TUPLES_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::SaveUserData(): '%s'\n", strError.c_str());
+ return -1;
+ }
+
+ PQclear(result);
+ }
+
+return 0;
+}
+
--- /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>
+ */
+
+/*
+ * Vairous utility methods
+ *
+ * $Revision: 1.3 $
+ * $Date: 2009/10/22 10:01:08 $
+ *
+ */
+
+#include <string>
+#include <ctime>
+
+#include <libpq-fe.h>
+
+#include "common.h"
+
+#include "postgresql_store.h"
+
+int POSTGRESQL_STORE::StartTransaction() const
+{
+PGresult * result = PQexec(connection, "BEGIN");
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::StartTransaction(): '%s'\n", strError.c_str());
+ return -1;
+ }
+
+PQclear(result);
+
+return 0;
+}
+
+int POSTGRESQL_STORE::CommitTransaction() const
+{
+PGresult * result = PQexec(connection, "COMMIT");
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::CommitTransaction(): '%s'\n", strError.c_str());
+ return -1;
+ }
+
+PQclear(result);
+
+return 0;
+}
+
+int POSTGRESQL_STORE::RollbackTransaction() const
+{
+PGresult * result = PQexec(connection, "ROLLBACK");
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ strError = PQresultErrorMessage(result);
+ PQclear(result);
+ printfd(__FILE__, "POSTGRESQL_STORE::RollbackTransaction(): '%s'\n", strError.c_str());
+ return -1;
+ }
+
+PQclear(result);
+
+return 0;
+}
+
+int POSTGRESQL_STORE::EscapeString(std::string & value) const
+{
+int error = 0;
+char * buf = new char[(value.length() << 1) + 1];
+
+PQescapeStringConn(connection,
+ buf,
+ value.c_str(),
+ value.length(),
+ &error);
+
+if (error)
+ {
+ strError = PQerrorMessage(connection);
+ printfd(__FILE__, "POSTGRESQL_STORE::EscapeString(): '%s'\n", strError.c_str());
+ delete buf;
+ return -1;
+ }
+
+value = buf;
+
+delete[] buf;
+return 0;
+}
+
+std::string POSTGRESQL_STORE::Int2TS(uint32_t ts) const
+{
+char buf[32];
+struct tm brokenTime;
+time_t tt = ts;
+
+brokenTime.tm_wday = 0;
+brokenTime.tm_yday = 0;
+brokenTime.tm_isdst = 0;
+
+gmtime_r(&tt, &brokenTime);
+
+strftime(buf, 32, "%Y-%m-%d %H:%M:%S", &brokenTime);
+
+return buf;
+}
+
+uint32_t POSTGRESQL_STORE::TS2Int(const std::string & ts) const
+{
+struct tm brokenTime;
+
+brokenTime.tm_wday = 0;
+brokenTime.tm_yday = 0;
+brokenTime.tm_isdst = 0;
+
+stg_strptime(ts.c_str(), "%Y-%m-%d %H:%M:%S", &brokenTime);
+
+return stg_timegm(&brokenTime);
+}
+
+void POSTGRESQL_STORE::MakeDate(std::string & date, int year, int month) const
+{
+struct tm brokenTime;
+
+brokenTime.tm_wday = 0;
+brokenTime.tm_yday = 0;
+brokenTime.tm_isdst = 0;
+
+if (year)
+ {
+ brokenTime.tm_hour = 0;
+ brokenTime.tm_min = 0;
+ brokenTime.tm_sec = 0;
+ brokenTime.tm_year = year;
+ brokenTime.tm_mon = month;
+ }
+else
+ {
+ time_t curTime = stgTime;
+ /*time(&curTime);*/
+
+ localtime_r(&curTime, &brokenTime);
+ }
+
+brokenTime.tm_mday = DaysInMonth(brokenTime.tm_year + 1900, brokenTime.tm_mon);
+
+char buf[32];
+
+strftime(buf, 32, "%Y-%m-%d", &brokenTime);
+
+date = buf;
+}
+
--- /dev/null
+#ifndef POSTGRESQL_UTILS_STORE_H
+#define POSTGRESQL_UTILS_STORE_H
+
+#include <functional>
+
+struct ToLower : public std::unary_function<char, char>
+{
+char operator() (char c) const { return std::tolower(c); }
+};
+
+#endif
--- /dev/null
+#!/bin/bash
+
+sandbox_dir=$1
+
+export LD_LIBRARY_PATH=$sandbox_dir/libs/
+
+$sandbox_dir/sbin/stargazer $sandbox_dir/etc/stargazer
+
+if [ $? == 0 ]
+then
+ echo "Start successfull"
+ exit 0
+else
+ echo "Start failed"
+ exit 1
+fi
+
--- /dev/null
+#include <stdlib.h>
+#include <unistd.h>
+#include <string>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+
+#include "common.h"
+
+using namespace std;
+
+#define MAX_SCRIPT_LEN (256)
+
+static int msgid;
+static bool nonstop;
+
+//-----------------------------------------------------------------------------
+struct SCRIPT_DATA
+{
+ long mtype;
+ char script[MAX_SCRIPT_LEN];
+} sd;
+//-----------------------------------------------------------------------------
+static void CatchUSR1Executer(int)
+{
+//printfd(__FILE__, "CatchUSR1Executer\n");
+exit(0);
+nonstop = false;
+}
+//-----------------------------------------------------------------------------
+int ScriptExec(const string & str)
+{
+if (str.length() >= MAX_SCRIPT_LEN)
+ return -1;
+
+/*printfd(__FILE__, "2 Script schedule: %s\n", str.c_str());
+
+if (access(str.c_str(), X_OK))
+ return -1;*/
+
+struct msgbuf * mbuf;
+int ret;
+strncpy(sd.script, str.c_str(), MAX_SCRIPT_LEN);
+sd.mtype = 1;
+mbuf = (struct msgbuf * )&sd;
+ret = msgsnd(msgid, mbuf, MAX_SCRIPT_LEN, 0);
+if (ret < 0)
+ {
+ printfd(__FILE__, "snd ERROR!\n");
+ return -1;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+void Executer(int msgKey, int msgID, pid_t pid, char * procName)
+{
+msgid = msgID;
+if (pid)
+ return;
+nonstop = true;
+//printfd(__FILE__, "close(pipeOut) %d pid=%d\n", pipeOut, getpid());
+
+//printfd(__FILE__, "Executer started %d\n", getpid());
+#ifdef LINUX
+memset(procName, 0, strlen(procName));
+strcpy(procName, "stg-exec");
+#else
+setproctitle("stg-exec");
+#endif
+
+struct sigaction newsa, oldsa;
+sigset_t sigmask;
+
+sigemptyset(&sigmask);
+sigaddset(&sigmask, SIGTERM);
+newsa.sa_handler = SIG_IGN;
+newsa.sa_mask = sigmask;
+newsa.sa_flags = 0;
+sigaction(SIGTERM, &newsa, &oldsa);
+
+sigemptyset(&sigmask);
+sigaddset(&sigmask, SIGINT);
+newsa.sa_handler = SIG_IGN;
+newsa.sa_mask = sigmask;
+newsa.sa_flags = 0;
+sigaction(SIGINT, &newsa, &oldsa);
+
+sigemptyset(&sigmask);
+sigaddset(&sigmask, SIGUSR1);
+newsa.sa_handler = CatchUSR1Executer;
+newsa.sa_mask = sigmask;
+newsa.sa_flags = 0;
+sigaction(SIGUSR1, &newsa, &oldsa);
+
+int ret;
+
+SCRIPT_DATA sd;
+
+while (nonstop)
+ {
+ sd.mtype = 1;
+ //printfd(__FILE__, "Waiting for msgrcv... msgid=%d pid=%d\n", msgid, getpid());
+ ret = msgrcv(msgid, &sd, MAX_SCRIPT_LEN, 0, 0);
+
+ if (ret < 0)
+ {
+ usleep(20000);
+ continue;
+ }
+ //printfd(__FILE__, "Script execute: %s\n", sd.script);
+ system(sd.script);
+ }
+exit(0);
+}
+//-----------------------------------------------------------------------------
+
+
--- /dev/null
+#!/bin/bash
+
+# Этот скрипт производит очистку файловой БД stargazer-а.
+# Его можно вызывать вручную или покрону, к примеру раз в неделю или раз в месяц.
+
+
+# Эта переменная задает сколько месяцев детальной статистики оставить в БД
+SAVE_MONTHS=3
+
+# Эта переменная задает сколько строк оставить в логах юзеров
+MAX_LOG_LINES=5000
+
+# Тут определяется путь к БД
+DB=/var/stargazer/
+
+
+
+
+declare -i NOW=`date +%s`
+declare -i DT=SAVE_MONTHS*31*24*3600
+declare -i stat_time=0
+
+for usr in $DB/users/*
+do
+ echo cleaning `basename $usr`
+ for ys in $usr/detail_stat/*
+ do
+ year=`basename $ys`
+
+ for ms in $ys/*
+ do
+ month=`basename $ms`
+ stat_time=`date --date="$year/$month/01" +%s`
+
+ if (( $NOW - $stat_time > $DT ))
+ then
+ rm -fr $ms
+ fi
+ done
+ done
+ tail -n $MAX_LOG_LINES $usr/log > /tmp/stg_usr_log.`basename $usr`
+ mv -f /tmp/stg_usr_log.`basename $usr` $usr/log
+done
+
--- /dev/null
+#!/bin/bash
+
+# Данный скрипт производит мониторинг СТГ-сервера на зависание и в
+# случае его зависания перезапускает.
+# Для работы скрипта в настройках СТГ должен быть указан параметер
+# MonitorDir
+# Скрипт отрабатывает один раз и выходит. Т.е. он не работает постоянно
+# и следит за СТГ. Его нужно вызывать по крону или как-то еще с нужной
+# периодичностью!!!
+
+
+# Путь к файлам монитора. Должен совпадать со значением MonitorDir
+# в настройках сервера
+MONITOR_DIR=/var/stargazer/monitor/
+
+
+# Максимальная задержка обновления файлов монитора в секундах.
+# При привышении этого значения сервер считается зависшим и будет
+# перезапущен
+DT=300
+
+
+
+
+declare -i now=`date +%s`
+declare -i DT=300
+declare -i file_time=0
+
+stg_running=`ps ax | grep stargazer`
+if [ -z "$stg_running" ]
+then
+ echo "Stargazer is not running"
+ exit 0
+fi
+
+#wakeuper for traffcounter
+ping -c 1 127.0.0.1 > /dev/null
+sleep 1
+
+for mon in $MONITOR_DIR/*
+do
+ if [ ! -r $mon ]
+ then
+ echo "no monitor files"
+ exit 0
+ fi
+ file_time=`stat -c%Y $mon`
+
+ if (( $now - $file_time > $DT ))
+ then
+ echo "Stargazer is deadlocked!"
+
+ # Команда остаовки СТГ
+ killall -KILL stargazer
+
+ rm -f $MONITOR_DIR/*
+ sleep 15
+
+ # Команда запуска СТГ
+ /etc/init.d/stargazer start
+
+ fi
+
+done
+
+
--- /dev/null
+#!/bin/bash
+
+int_iface=eth1
+
+# Login
+LOGIN=$1
+
+#user IP
+IP=$2
+
+#cash
+CASH=$3
+
+#user ID
+ID=$4
+
+#Selected dirs to connect
+DIRS=$5
+
+default_speed=32kbit
+
+# =========== shaping by tariff ===========
+#tariff=$(grep -i "^tariff=" /var/stargazer/users/$LOGIN/conf | cut -f 2 -d"=")
+#echo "tariff=$tariff" > /var/stargazer/users/$LOGIN/connect.log
+#case $tariff in
+# minimum) speedkb=128kbit;; # 128 kbit
+# middle) speedkb=256kbit;; # 256 kbi
+# maximum) speedkb=512kbit;; # 512 kbit
+# *) speedkb=$default_speed;; # default speed
+#esac
+# ========= shaping by tariff end =========
+
+# ========= shaping by userdata0 ==========
+speedR=$(grep -i "^Userdata0=" /var/stargazer/users/$LOGIN/conf | cut -f 2 -d"=")
+speed=$(echo $speedR | grep "^[0-9]*[0-9]$")
+
+if [ -z "$speed" ]
+then
+ speedkb=$default_speed
+else
+ speedkb="$speed"kbit
+fi
+# ======= shaping by userdata0 end ========
+
+declare -i mark=$ID+10
+
+echo "$mark" > /var/stargazer/users/$LOGIN/shaper_mark
+echo "$speedkb" > /var/stargazer/users/$LOGIN/shaper_rate
+
+iptables -t mangle -A FORWARD -d $IP -j MARK --set-mark $mark
+
+tc class add dev $int_iface parent 1:1 classid 1:$mark htb rate $speedkb burst 40k
+tc filter add dev $int_iface parent 1: protocol ip prio 3 handle $mark fw classid 1:$mark
+
--- /dev/null
+#!/bin/bash
+
+int_iface=eth1
+
+# Login
+LOGIN=$1
+
+#user IP
+IP=$2
+
+#cash
+CASH=$3
+
+#user ID
+ID=$4
+
+#Selected dirs to disconnect
+DIRS=$4
+
+mark=$(cat /var/stargazer/users/$LOGIN/shaper_mark)
+rate=$(cat /var/stargazer/users/$LOGIN/shaper_rate)
+
+if [ -n "$mark" ]
+then
+ iptables -t mangle -D FORWARD -d $IP -j MARK --set-mark $mark
+ while [ $? == 0 ]
+ do
+ iptables -t mangle -D FORWARD -d $IP -j MARK --set-mark $mark
+ done
+fi
+
+tc filter del dev $int_iface parent 1: protocol ip prio 3 handle $mark fw classid 1:$mark
+tc class del dev $int_iface parent 1:1 classid 1:$mark htb rate $rate burst 40k
+
+#echo "D `date +%Y.%m.%d-%H.%M.%S` $IP $CASH" >> /var/stargazer/users/$LOGIN/connect.log
+
+
--- /dev/null
+Настройка шейпера для STG в Linux.
+
+По мотивам форума:
+http://local.com.ua/forum/index.php?showtopic=7920
+
+Настройка сводится к указанию сетевого интерфейса, обращенного к пользователю
+в скриптах shaper.sh, shaper.stop.sh, OnConnect и OnDisconnect, и уточнению
+скоростоей и тарифов в скрипте OnConnect (если нужно).
+
+Скрипты сделаны для БД на файлах, однако, сделать их для БД на Firebird или
+MySQL не составит большого труда.
+
+В OnConnect есть два типа шейпинга.
+1. На основании тарифа. Т.е. для каждого тарифа у задана скорость и задано
+дефолтное значение, на случай отсутсвия тарифа в списке скоростей или
+забывчивости админа.
+2. На основании Userdata0. В этом поле просто прописывается число равное
+скорости в kbit/sec. Также есть дефолтное значение скорости в 32 kbit/sec
+на случай отсутсвия в Userdata0 корректного значения.
+
+В скрипте первый способ закомментирован. Для того чтобы выбрать один из них нужно
+либо удалить, либо закомментировать строчики между
+
+# ========= shaping by tariff ==========
+.........
+# ======= shaping by tariff end ========
+
+и
+
+# ========= shaping by userdata0 ==========
+.........
+# ======= shaping by userdata0 end ========
+
+
+и нужную часть расскоментировать, если она закомментрована.
+
+Скрипт shaper.sh должен быть выполнен один раз при загрузке системы.
+
+Интерфейс обращенный к пользователю определяется в переменной
+int_iface=
+(присутствует во всех 4-х файлах shaper.sh, shaper.stop.sh, OnConnect и
+OnDisconnect !!!)
+
+Скорость по умолчанию в OnConnect в переменной default_speed
+
+Зависимость скорости от тарифа задается в следующем фрагменте кода:
+case $tariff in
+ minimum) speedkb=128kbit;;
+ middle) speedkb=256kbit;;
+ maximum) speedkb=512kbit;;
+ *) speedkb=$default_speed;;
+esac
+
+Т.е. тут нужно вместо minimum, ... maximum подставить имена ваших тарифов
+и соотв. скорость. Пользователи с тарифами не указанными в списке будут иметь
+дефолтную скорость.
+
+Скорость ограничевается только для входящего тарафика, однако расширить
+эти скрипты для исходящего не составит труда.
--- /dev/null
+#!/bin/bash
+
+int_iface=eth1
+
+iptables -t mangle --flush
+
+tc qdisc add dev $int_iface root handle 1: htb
+tc class add dev $int_iface parent 1: classid 1:1 htb rate 100mbit ceil 100mbit burst 200k
+
--- /dev/null
+#!/bin/bash
+
+int_iface=eth1
+
+#iptables -t mangle --flush
+
+tc qdisc del dev $int_iface root handle 1: htb
+
--- /dev/null
+Настройка такой конфигурации происходит в 3 этапа:
+1. Настройка VPN с использованием pptpd;
+2. Настройка авторизации VPN через FreeRADIUS;
+3. Настройка шейпера;
+
+1. Настройка VPN
+
+Необходимо установить пакеты ppp и pptpd. Также необходима поддержка PPP в ядре:
+ Device Drivers --->
+ Network device support --->
+ <M> PPP (point-to-point protocol) support
+ <M> PPP support for sync tty ports
+ <M> PPP Deflate compression
+ <M> PPP BSD-Compress compression
+ <M> PPP MPPE compression (encryption) (EXPERIMENTAL)
+ <M> PPP over Ethernet (EXPERIMENTAL)
+В файле /etc/pptpd.conf прописываем файл настроек PPP (параметр option). Также
+указываем адреса сервера внутри сети VPN (параметр localip) и диапазон адресов
+клиентов (параметр remoteip). См. пример файла конфигурации.
+В настройках PPP указываем имя сервера (параметр name), параметры шифрования.
+Для использования шифрования MPPE необходима его поддержка в ядре. Кроме того,
+в процессе аутентификации MPPE использует MS-CHAPv2. По этому при
+использовании шифрования MPPE также необходимо указать необходимость
+поддержки MS-CHAPv2 клиентом. По желанию указываем proxyarp (для того чтобы
+клиенты в сети VPN "видели" друг друга) и defaultroute. Прописываем в файле
+/etc/ppp/chap-secrets тестового пользователя и проверяем работоспособность
+VPN.
+
+2. Настройка авторизации VPN через FreeRADIUS
+
+Необходимо установить пакет freeradius.
+Настройку сервера (файл radiusd.conf) проводим в соответствии с документацией
+на модуль rlm_stg.so (см. документацию на систему Stargazer).
+Настройку Stargazer с плагином для FreeRADIUS проводим в соответствиии с
+документацией на модуль mod_radius.so (см. документацию на систему Stargazer).
+В файле clients.conf, расположенном в дирректории с конфигурационными файлами
+FreeRADIUS, описываем, какие клиенты могут использовать FreeRADIUS.
+Рекомендуется заменить стандартный пароль, которым шифруется обмен информации
+с клиентом, "testing123" на что-то более приемлимое с точки зрения безопасности.
+После этого запускаем FreeRADIUS и удостоверяемся, что он работает строчкой
+"Mon Mar 31 16:06:17 2008 : Info: Ready to process requests." в журнале
+(обычно, /var/log/radius/radius.log). Если журнал FreeRADIUS не позволяет
+определить проблему - можно запустить сервер в отладочном режме с ключем -X.
+В этом режиме более детальное журналирование проводится в консоль.
+Если на данном этапе все работает - в файл насттроек PPP прописываем строчку
+plugin radius.so. После этого VPN должен нормально авторизоваться
+пользователями системы Stargazer.
+
+3. Настройка шейпера
+
+Собственно настройки шейпер не требует. Всё, что нужно прописано в скриптах
+OnConnect и OnDisconnect. Шейпер предназначен для работы с хранилищем на
+файлах, однако, переделать скипт под MySQL или Firebird не составит труда.
+Скорость для пользоватлея задается в поле Userdata0 в kbit/sec. В этом поле
+должно быть прописано просто число без всяких kbit/sec и т.п. Если в этом поле
+у пользователя нет данных или стоит некорректное значение, пользователь будет
+ограничен скоростью определенной в переменной default_speed в скрипте
+OnConnect.
--- /dev/null
+#!/bin/bash
+
+#adsl-start
+
+modprobe ip_queue
+
+int_addr=10.0.0.2
+ext_addr=192.168.1.34
+
+int_net=10.0.0.0/16
+ext_net=192.168.1.0/24
+
+echo 1 > /proc/sys/net/ipv4/ip_forward
+
+iptables -P INPUT DROP
+iptables -P OUTPUT ACCEPT
+iptables -P FORWARD ACCEPT
+
+iptables -t nat -F
+iptables -t filter -F
+
+#
+#iptables -A INPUT -d $ip1 -j ACCEPT
+#iptables -A OUTPUT -s $ip1 -j ACCEPT
+
+# Разрешам говорить самому с собой
+iptables -A INPUT -d 127.0.0.1 -j ACCEPT
+iptables -A OUTPUT -s 127.0.0.1 -j ACCEPT
+
+#iptables -A INPUT -d $ip4 -j ACCEPT
+#iptables -A INPUT -s $ip4 -j ACCEPT
+#iptables -A OUTPUT -s $ip4 -j ACCEPT
+#iptables -A OUTPUT -d $ip4 -j ACCEPT
+
+iptables -A INPUT -p icmp -j ACCEPT
+iptables -A OUTPUT -p icmp -j ACCEPT
+
+iptables -A INPUT -p 47 -j ACCEPT
+iptables -A FORWARD -p 47 -j ACCEPT
+iptables -A OUTPUT -p 47 -j ACCEPT
+
+#SSH On this machine
+iptables -A INPUT -p tcp -d $int_addr --dport 22 -j ACCEPT
+iptables -A OUTPUT -p tcp -s $int_addr --sport 22 -j ACCEPT
+iptables -A INPUT -p tcp -d $ext_addr --dport 22 -j ACCEPT
+iptables -A OUTPUT -p tcp -s $ext_addr --sport 22 -j ACCEPT
+
+#WEB On this machine
+#iptables -A INPUT -p tcp -d $ip2 --dport 80 -j ACCEPT
+#iptables -A OUTPUT -p tcp -s $ip2 --sport 80 -j ACCEPT
+#iptables -A INPUT -p tcp -d $ip3 --dport 80 -j ACCEPT
+#iptables -A OUTPUT -p tcp -s $ip3 --sport 80 -j ACCEPT
+
+#PPTP
+iptables -A INPUT -p tcp --dport 1723 -j ACCEPT
+iptables -A OUTPUT -p tcp --sport 1723 -j ACCEPT
+iptables -A INPUT -p udp --dport 1723 -j ACCEPT
+iptables -A OUTPUT -p udp --sport 1723 -j ACCEPT
+
+#FTP
+#iptables -A INPUT -p tcp -d $ip2 -j ACCEPT
+#iptables -A OUTPUT -p tcp -s $ip2 -j ACCEPT
+#iptables -A INPUT -p tcp -d $ip3 -j ACCEPT
+#iptables -A OUTPUT -p tcp -s $ip3 -j ACCEPT
+
+#iptables -A INPUT -p tcp -d $ip2 --dport 20:21 -j ACCEPT
+#iptables -A OUTPUT -p tcp -s $ip2 --sport 20:21 -j ACCEPT
+#iptables -A INPUT -p tcp -d $ip3 --dport 20:21 -j ACCEPT
+#iptables -A OUTPUT -p tcp -s $ip3 --sport 20:21 -j ACCEPT
+
+#iptables -A INPUT -p tcp -d $ip2 --dport 1024:65535 --sport 1024:65535 -j ACCEPT
+#iptables -A INPUT -p tcp -d $ip3 --dport 1024:65535 --sport 1024:65535 -j ACCEPT
+#iptables -A OUTPUT -p tcp -s $ip2 --sport 1024:65535 --dport 1024:65535 -j ACCEPT
+#iptables -A OUTPUT -p tcp -s $ip3 --sport 1024:65535 --dport 1024:65535 -j ACCEPT
+
+#DNS
+iptables -A INPUT -p tcp --sport 53 -j ACCEPT
+iptables -A OUTPUT -p tcp --dport 53 -j ACCEPT
+iptables -A INPUT -p udp --sport 53 -j ACCEPT
+iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
+
+#iptables -t nat -A PREROUTING -p tcp -d $ip1 --dport 80 -j ACCEPT
+#iptables -t nat -A PREROUTING -p tcp -d $ip2 --dport 80 -j ACCEPT
+#iptables -t nat -A PREROUTING -p tcp -d $ip3 --dport 80 -j ACCEPT
+#iptables -t nat -A PREROUTING -p tcp -d $ip4 --dport 80 -j ACCEPT
+
+#iptables -t nat -A PREROUTING -p tcp -s 192.168.1.7 -j ACCEPT
+#iptables -t nat -A PREROUTING -p tcp -s 192.168.1.16 -j ACCEPT
+#iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 3128
+
+iptables -t nat -A POSTROUTING -d 0.0.0.0/0 -s 192.168.2.0/24 -j MASQUERADE
+
+
+
--- /dev/null
+#
+# clients.conf - client configuration directives
+#
+#######################################################################
+
+#######################################################################
+#
+# Definition of a RADIUS client (usually a NAS).
+#
+# The information given here over rides anything given in the
+# 'clients' file, or in the 'naslist' file. The configuration here
+# contains all of the information from those two files, and allows
+# for more configuration items.
+#
+# The "shortname" is be used for logging. The "nastype", "login" and
+# "password" fields are mainly used for checkrad and are optional.
+#
+
+#
+# Defines a RADIUS client. The format is 'client [hostname|ip-address]'
+#
+# '127.0.0.1' is another name for 'localhost'. It is enabled by default,
+# to allow testing of the server after an initial installation. If you
+# are not going to be permitting RADIUS queries from localhost, we suggest
+# that you delete, or comment out, this entry.
+#
+client 127.0.0.1 {
+ #
+ # The shared secret use to "encrypt" and "sign" packets between
+ # the NAS and FreeRADIUS. You MUST change this secret from the
+ # default, otherwise it's not a secret any more!
+ #
+ # The secret can be any string, up to 31 characters in length.
+ #
+ secret = testing123
+
+ #
+ # The short name is used as an alias for the fully qualified
+ # domain name, or the IP address.
+ #
+ shortname = localhost
+
+ #
+ # the following three fields are optional, but may be used by
+ # checkrad.pl for simultaneous use checks
+ #
+
+ #
+ # The nastype tells 'checkrad.pl' which NAS-specific method to
+ # use to query the NAS for simultaneous use.
+ #
+ # Permitted NAS types are:
+ #
+ # cisco
+ # computone
+ # livingston
+ # max40xx
+ # multitech
+ # netserver
+ # pathras
+ # patton
+ # portslave
+ # tc
+ # usrhiper
+ # other # for all other types
+
+ #
+ nastype = other # localhost isn't usually a NAS...
+
+ #
+ # The following two configurations are for future use.
+ # The 'naspasswd' file is currently used to store the NAS
+ # login name and password, which is used by checkrad.pl
+ # when querying the NAS for simultaneous use.
+ #
+# login = !root
+# password = someadminpas
+}
--- /dev/null
+##
+## radiusd.conf -- FreeRADIUS server configuration file.
+##
+## http://www.freeradius.org/
+## $Id: radiusd.conf,v 1.1 2008/03/31 13:54:59 faust Exp $
+##
+
+# The location of other config files and
+# logfiles are declared in this file
+#
+# Also general configuration for modules can be done
+# in this file, it is exported through the API to
+# modules that ask for it.
+#
+# The configuration variables defined here are of the form ${foo}
+# They are local to this file, and do not change from request to
+# request.
+#
+# The per-request variables are of the form %{Attribute-Name}, and
+# are taken from the values of the attribute in the incoming
+# request. See 'doc/variables.txt' for more information.
+
+prefix = /usr
+exec_prefix = /usr
+sysconfdir = /etc
+localstatedir = /var
+sbindir = ${exec_prefix}/sbin
+logdir = /var/log/freeradius
+raddbdir = /etc/freeradius
+radacctdir = ${logdir}/radacct
+
+# Location of config and logfiles.
+confdir = ${raddbdir}
+run_dir = ${localstatedir}/run/freeradius
+
+#
+# The logging messages for the server are appended to the
+# tail of this file.
+#
+log_file = ${logdir}/radius.log
+
+#
+# libdir: Where to find the rlm_* modules.
+#
+# This should be automatically set at configuration time.
+#
+# If the server builds and installs, but fails at execution time
+# with an 'undefined symbol' error, then you can use the libdir
+# directive to work around the problem.
+#
+# The cause is usually that a library has been installed on your
+# system in a place where the dynamic linker CANNOT find it. When
+# executing as root (or another user), your personal environment MAY
+# be set up to allow the dynamic linker to find the library. When
+# executing as a daemon, FreeRADIUS MAY NOT have the same
+# personalized configuration.
+#
+# To work around the problem, find out which library contains that symbol,
+# and add the directory containing that library to the end of 'libdir',
+# with a colon separating the directory names. NO spaces are allowed.
+#
+# e.g. libdir = /usr/local/lib:/opt/package/lib
+#
+# You can also try setting the LD_LIBRARY_PATH environment variable
+# in a script which starts the server.
+#
+# If that does not work, then you can re-configure and re-build the
+# server to NOT use shared libraries, via:
+#
+# ./configure --disable-shared
+# make
+# make install
+#
+libdir = /usr/lib/freeradius
+
+# pidfile: Where to place the PID of the RADIUS server.
+#
+# The server may be signalled while it's running by using this
+# file.
+#
+# This file is written when ONLY running in daemon mode.
+#
+# e.g.: kill -HUP `cat /var/run/freeradius/freeradius.pid`
+#
+pidfile = ${run_dir}/freeradius.pid
+
+
+# user/group: The name (or #number) of the user/group to run radiusd as.
+#
+# If these are commented out, the server will run as the user/group
+# that started it. In order to change to a different user/group, you
+# MUST be root ( or have root privleges ) to start the server.
+#
+# We STRONGLY recommend that you run the server with as few permissions
+# as possible. That is, if you're not using shadow passwords, the
+# user and group items below should be set to 'nobody'.
+#
+# On SCO (ODT 3) use "user = nouser" and "group = nogroup".
+#
+# NOTE that some kernels refuse to setgid(group) when the value of
+# (unsigned)group is above 60000; don't use group nobody on these systems!
+#
+# On systems with shadow passwords, you might have to set 'group = shadow'
+# for the server to be able to read the shadow password file. If you can
+# authenticate users while in debug mode, but not in daemon mode, it may be
+# that the debugging mode server is running as a user that can read the
+# shadow info, and the user listed below can not.
+#
+user = freerad
+group = freerad
+
+# max_request_time: The maximum time (in seconds) to handle a request.
+#
+# Requests which take more time than this to process may be killed, and
+# a REJECT message is returned.
+#
+# WARNING: If you notice that requests take a long time to be handled,
+# then this MAY INDICATE a bug in the server, in one of the modules
+# used to handle a request, OR in your local configuration.
+#
+# This problem is most often seen when using an SQL database. If it takes
+# more than a second or two to receive an answer from the SQL database,
+# then it probably means that you haven't indexed the database. See your
+# SQL server documentation for more information.
+#
+# Useful range of values: 5 to 120
+#
+max_request_time = 30
+
+# delete_blocked_requests: If the request takes MORE THAN 'max_request_time'
+# to be handled, then maybe the server should delete it.
+#
+# If you're running in threaded, or thread pool mode, this setting
+# should probably be 'no'. Setting it to 'yes' when using a threaded
+# server MAY cause the server to crash!
+#
+delete_blocked_requests = no
+
+# cleanup_delay: The time to wait (in seconds) before cleaning up
+# a reply which was sent to the NAS.
+#
+# The RADIUS request is normally cached internally for a short period
+# of time, after the reply is sent to the NAS. The reply packet may be
+# lost in the network, and the NAS will not see it. The NAS will then
+# re-send the request, and the server will respond quickly with the
+# cached reply.
+#
+# If this value is set too low, then duplicate requests from the NAS
+# MAY NOT be detected, and will instead be handled as seperate requests.
+#
+# If this value is set too high, then the server will cache too many
+# requests, and some new requests may get blocked. (See 'max_requests'.)
+#
+# Useful range of values: 2 to 10
+#
+cleanup_delay = 5
+
+# max_requests: The maximum number of requests which the server keeps
+# track of. This should be 256 multiplied by the number of clients.
+# e.g. With 4 clients, this number should be 1024.
+#
+# If this number is too low, then when the server becomes busy,
+# it will not respond to any new requests, until the 'cleanup_delay'
+# time has passed, and it has removed the old requests.
+#
+# If this number is set too high, then the server will use a bit more
+# memory for no real benefit.
+#
+# If you aren't sure what it should be set to, it's better to set it
+# too high than too low. Setting it to 1000 per client is probably
+# the highest it should be.
+#
+# Useful range of values: 256 to infinity
+#
+max_requests = 1024
+
+# bind_address: Make the server listen on a particular IP address, and
+# send replies out from that address. This directive is most useful
+# for machines with multiple IP addresses on one interface.
+#
+# It can either contain "*", or an IP address, or a fully qualified
+# Internet domain name. The default is "*"
+#
+# As of 1.0, you can also use the "listen" directive. See below for
+# more information.
+#
+bind_address = *
+
+# port: Allows you to bind FreeRADIUS to a specific port.
+#
+# The default port that most NAS boxes use is 1645, which is historical.
+# RFC 2138 defines 1812 to be the new port. Many new servers and
+# NAS boxes use 1812, which can create interoperability problems.
+#
+# The port is defined here to be 0 so that the server will pick up
+# the machine's local configuration for the radius port, as defined
+# in /etc/services.
+#
+# If you want to use the default RADIUS port as defined on your server,
+# (usually through 'grep radius /etc/services') set this to 0 (zero).
+#
+# A port given on the command-line via '-p' over-rides this one.
+#
+# As of 1.0, you can also use the "listen" directive. See below for
+# more information.
+#
+port = 0
+
+#
+# By default, the server uses "bind_address" to listen to all IP's
+# on a machine, or just one IP. The "port" configuration is used
+# to select the authentication port used when listening on those
+# addresses.
+#
+# If you want the server to listen on additional addresses, you can
+# use the "listen" section. A sample section (commented out) is included
+# below. This "listen" section duplicates the functionality of the
+# "bind_address" and "port" configuration entries, but it only listens
+# for authentication packets.
+#
+# If you comment out the "bind_address" and "port" configuration entries,
+# then it becomes possible to make the server accept only accounting,
+# or authentication packets. Previously, it always listened for both
+# types of packets, and it was impossible to make it listen for only
+# one type of packet.
+#
+#listen {
+ # IP address on which to listen.
+ # Allowed values are:
+ # dotted quad (1.2.3.4)
+ # hostname (radius.example.com)
+ # wildcard (*)
+# ipaddr = *
+
+ # Port on which to listen.
+ # Allowed values are:
+ # integer port number (1812)
+ # 0 means "use /etc/services for the proper port"
+# port = 0
+
+ # Type of packets to listen for.
+ # Allowed values are:
+ # auth listen for authentication packets
+ # acct listen for accounting packets
+ #
+# type = auth
+#}
+
+
+# hostname_lookups: Log the names of clients or just their IP addresses
+# e.g., www.freeradius.org (on) or 206.47.27.232 (off).
+#
+# The default is 'off' because it would be overall better for the net
+# if people had to knowingly turn this feature on, since enabling it
+# means that each client request will result in AT LEAST one lookup
+# request to the nameserver. Enabling hostname_lookups will also
+# mean that your server may stop randomly for 30 seconds from time
+# to time, if the DNS requests take too long.
+#
+# Turning hostname lookups off also means that the server won't block
+# for 30 seconds, if it sees an IP address which has no name associated
+# with it.
+#
+# allowed values: {no, yes}
+#
+hostname_lookups = no
+
+# Core dumps are a bad thing. This should only be set to 'yes'
+# if you're debugging a problem with the server.
+#
+# allowed values: {no, yes}
+#
+allow_core_dumps = no
+
+# Regular expressions
+#
+# These items are set at configure time. If they're set to "yes",
+# then setting them to "no" turns off regular expression support.
+#
+# If they're set to "no" at configure time, then setting them to "yes"
+# WILL NOT WORK. It will give you an error.
+#
+regular_expressions = yes
+extended_expressions = yes
+
+# Log the full User-Name attribute, as it was found in the request.
+#
+# allowed values: {no, yes}
+#
+log_stripped_names = no
+
+# Log authentication requests to the log file.
+#
+# allowed values: {no, yes}
+#
+log_auth = no
+
+# Log passwords with the authentication requests.
+# log_auth_badpass - logs password if it's rejected
+# log_auth_goodpass - logs password if it's correct
+#
+# allowed values: {no, yes}
+#
+log_auth_badpass = no
+log_auth_goodpass = no
+
+# usercollide: Turn "username collision" code on and off. See the
+# "doc/duplicate-users" file
+#
+# WARNING
+# !!!!!!! Setting this to "yes" may result in the server behaving
+# !!!!!!! strangely. The "username collision" code will ONLY work
+# !!!!!!! with clear-text passwords. Even then, it may not do what
+# !!!!!!! you want, or what you expect.
+# !!!!!!!
+# !!!!!!! We STRONGLY RECOMMEND that you do not use this feature,
+# !!!!!!! and that you find another way of acheiving the same goal.
+# !!!!!!!
+# !!!!!!! e,g. module fail-over. See 'doc/configurable_failover'
+# WARNING
+#
+usercollide = no
+
+# lower_user / lower_pass:
+# Lower case the username/password "before" or "after"
+# attempting to authenticate.
+#
+# If "before", the server will first modify the request and then try
+# to auth the user. If "after", the server will first auth using the
+# values provided by the user. If that fails it will reprocess the
+# request after modifying it as you specify below.
+#
+# This is as close as we can get to case insensitivity. It is the
+# admin's job to ensure that the username on the auth db side is
+# *also* lowercase to make this work
+#
+# Default is 'no' (don't lowercase values)
+# Valid values = "before" / "after" / "no"
+#
+lower_user = no
+lower_pass = no
+
+# nospace_user / nospace_pass:
+#
+# Some users like to enter spaces in their username or password
+# incorrectly. To save yourself the tech support call, you can
+# eliminate those spaces here:
+#
+# Default is 'no' (don't remove spaces)
+# Valid values = "before" / "after" / "no" (explanation above)
+#
+nospace_user = no
+nospace_pass = no
+
+# The program to execute to do concurrency checks.
+checkrad = ${sbindir}/checkrad
+
+# SECURITY CONFIGURATION
+#
+# There may be multiple methods of attacking on the server. This
+# section holds the configuration items which minimize the impact
+# of those attacks
+#
+security {
+ #
+ # max_attributes: The maximum number of attributes
+ # permitted in a RADIUS packet. Packets which have MORE
+ # than this number of attributes in them will be dropped.
+ #
+ # If this number is set too low, then no RADIUS packets
+ # will be accepted.
+ #
+ # If this number is set too high, then an attacker may be
+ # able to send a small number of packets which will cause
+ # the server to use all available memory on the machine.
+ #
+ # Setting this number to 0 means "allow any number of attributes"
+ max_attributes = 200
+
+ #
+ # reject_delay: When sending an Access-Reject, it can be
+ # delayed for a few seconds. This may help slow down a DoS
+ # attack. It also helps to slow down people trying to brute-force
+ # crack a users password.
+ #
+ # Setting this number to 0 means "send rejects immediately"
+ #
+ # If this number is set higher than 'cleanup_delay', then the
+ # rejects will be sent at 'cleanup_delay' time, when the request
+ # is deleted from the internal cache of requests.
+ #
+ # Useful ranges: 1 to 5
+ reject_delay = 1
+
+ #
+ # status_server: Whether or not the server will respond
+ # to Status-Server requests.
+ #
+ # Normally this should be set to "no", because they're useless.
+ # See: http://www.freeradius.org/rfc/rfc2865.html#Keep-Alives
+ #
+ # However, certain NAS boxes may require them.
+ #
+ # When sent a Status-Server message, the server responds with
+ # an Access-Accept packet, containing a Reply-Message attribute,
+ # which is a string describing how long the server has been
+ # running.
+ #
+ status_server = no
+}
+
+# PROXY CONFIGURATION
+#
+# proxy_requests: Turns proxying of RADIUS requests on or off.
+#
+# The server has proxying turned on by default. If your system is NOT
+# set up to proxy requests to another server, then you can turn proxying
+# off here. This will save a small amount of resources on the server.
+#
+# If you have proxying turned off, and your configuration files say
+# to proxy a request, then an error message will be logged.
+#
+# To disable proxying, change the "yes" to "no", and comment the
+# $INCLUDE line.
+#
+# allowed values: {no, yes}
+#
+proxy_requests = yes
+$INCLUDE ${confdir}/proxy.conf
+
+
+# CLIENTS CONFIGURATION
+#
+# Client configuration is defined in "clients.conf".
+#
+
+# The 'clients.conf' file contains all of the information from the old
+# 'clients' and 'naslist' configuration files. We recommend that you
+# do NOT use 'client's or 'naslist', although they are still
+# supported.
+#
+# Anything listed in 'clients.conf' will take precedence over the
+# information from the old-style configuration files.
+#
+$INCLUDE ${confdir}/clients.conf
+
+
+# SNMP CONFIGURATION
+#
+# Snmp configuration is only valid if SNMP support was enabled
+# at compile time.
+#
+# To enable SNMP querying of the server, set the value of the
+# 'snmp' attribute to 'yes'
+#
+snmp = no
+$INCLUDE ${confdir}/snmp.conf
+
+
+# THREAD POOL CONFIGURATION
+#
+# The thread pool is a long-lived group of threads which
+# take turns (round-robin) handling any incoming requests.
+#
+# You probably want to have a few spare threads around,
+# so that high-load situations can be handled immediately. If you
+# don't have any spare threads, then the request handling will
+# be delayed while a new thread is created, and added to the pool.
+#
+# You probably don't want too many spare threads around,
+# otherwise they'll be sitting there taking up resources, and
+# not doing anything productive.
+#
+# The numbers given below should be adequate for most situations.
+#
+thread pool {
+ # Number of servers to start initially --- should be a reasonable
+ # ballpark figure.
+ start_servers = 5
+
+ # Limit on the total number of servers running.
+ #
+ # If this limit is ever reached, clients will be LOCKED OUT, so it
+ # should NOT BE SET TOO LOW. It is intended mainly as a brake to
+ # keep a runaway server from taking the system with it as it spirals
+ # down...
+ #
+ # You may find that the server is regularly reaching the
+ # 'max_servers' number of threads, and that increasing
+ # 'max_servers' doesn't seem to make much difference.
+ #
+ # If this is the case, then the problem is MOST LIKELY that
+ # your back-end databases are taking too long to respond, and
+ # are preventing the server from responding in a timely manner.
+ #
+ # The solution is NOT do keep increasing the 'max_servers'
+ # value, but instead to fix the underlying cause of the
+ # problem: slow database, or 'hostname_lookups=yes'.
+ #
+ # For more information, see 'max_request_time', above.
+ #
+ max_servers = 32
+
+ # Server-pool size regulation. Rather than making you guess
+ # how many servers you need, FreeRADIUS dynamically adapts to
+ # the load it sees, that is, it tries to maintain enough
+ # servers to handle the current load, plus a few spare
+ # servers to handle transient load spikes.
+ #
+ # It does this by periodically checking how many servers are
+ # waiting for a request. If there are fewer than
+ # min_spare_servers, it creates a new spare. If there are
+ # more than max_spare_servers, some of the spares die off.
+ # The default values are probably OK for most sites.
+ #
+ min_spare_servers = 3
+ max_spare_servers = 10
+
+ # There may be memory leaks or resource allocation problems with
+ # the server. If so, set this value to 300 or so, so that the
+ # resources will be cleaned up periodically.
+ #
+ # This should only be necessary if there are serious bugs in the
+ # server which have not yet been fixed.
+ #
+ # '0' is a special value meaning 'infinity', or 'the servers never
+ # exit'
+ max_requests_per_server = 0
+}
+
+# MODULE CONFIGURATION
+#
+# The names and configuration of each module is located in this section.
+#
+# After the modules are defined here, they may be referred to by name,
+# in other sections of this configuration file.
+#
+modules {
+ #
+ # Each module has a configuration as follows:
+ #
+ # name [ instance ] {
+ # config_item = value
+ # ...
+ # }
+ #
+ # The 'name' is used to load the 'rlm_name' library
+ # which implements the functionality of the module.
+ #
+ # The 'instance' is optional. To have two different instances
+ # of a module, it first must be referred to by 'name'.
+ # The different copies of the module are then created by
+ # inventing two 'instance' names, e.g. 'instance1' and 'instance2'
+ #
+ # The instance names can then be used in later configuration
+ # INSTEAD of the original 'name'. See the 'radutmp' configuration
+ # below for an example.
+ #
+
+ # PAP module to authenticate users based on their stored password
+ #
+ # Supports multiple encryption schemes
+ # clear: Clear text
+ # crypt: Unix crypt
+ # md5: MD5 ecnryption
+ # sha1: SHA1 encryption.
+ # DEFAULT: crypt
+ pap {
+ encryption_scheme = crypt
+ }
+
+ # CHAP module
+ #
+ # To authenticate requests containing a CHAP-Password attribute.
+ #
+ chap {
+ authtype = CHAP
+ }
+
+ # Extensible Authentication Protocol
+ #
+ # For all EAP related authentications.
+ # Now in another file, because it is very large.
+ #
+$INCLUDE ${confdir}/eap.conf
+
+ # Microsoft CHAP authentication
+ #
+ # This module supports MS-CHAP and MS-CHAPv2 authentication.
+ # It also enforces the SMB-Account-Ctrl attribute.
+ #
+ mschap {
+ #
+ # As of 0.9, the mschap module does NOT support
+ # reading from /etc/smbpasswd.
+ #
+ # If you are using /etc/smbpasswd, see the 'passwd'
+ # module for an example of how to use /etc/smbpasswd
+
+ # if use_mppe is not set to no mschap will
+ # add MS-CHAP-MPPE-Keys for MS-CHAPv1 and
+ # MS-MPPE-Recv-Key/MS-MPPE-Send-Key for MS-CHAPv2
+ #
+ use_mppe = yes
+ authtype = MS-CHAP
+
+ # if mppe is enabled require_encryption makes
+ # encryption moderate
+ #
+ #require_encryption = yes
+
+ # require_strong always requires 128 bit key
+ # encryption
+ #
+ #require_strong = yes
+
+ # Windows sends us a username in the form of
+ # DOMAIN\user, but sends the challenge response
+ # based on only the user portion. This hack
+ # corrects for that incorrect behavior.
+ #
+ #with_ntdomain_hack = no
+
+ # The module can perform authentication itself, OR
+ # use a Windows Domain Controller. This configuration
+ # directive tells the module to call the ntlm_auth
+ # program, which will do the authentication, and return
+ # the NT-Key. Note that you MUST have "winbindd" and
+ # "nmbd" running on the local machine for ntlm_auth
+ # to work. See the ntlm_auth program documentation
+ # for details.
+ #
+ # Be VERY careful when editing the following line!
+ #
+ #ntlm_auth = "/path/to/ntlm_auth --request-nt-key --username=%{Stripped-User-Name:-%{User-Name:-None}} --challenge=%{mschap:Challenge:-00} --nt-response=%{mschap:NT-Response:-00}"
+ }
+
+ # Preprocess the incoming RADIUS request, before handing it off
+ # to other modules.
+ #
+ # This module processes the 'huntgroups' and 'hints' files.
+ # In addition, it re-writes some weird attributes created
+ # by some NASes, and converts the attributes into a form which
+ # is a little more standard.
+ #
+ preprocess {
+ huntgroups = ${confdir}/huntgroups
+ hints = ${confdir}/hints
+
+ # This hack changes Ascend's wierd port numberings
+ # to standard 0-??? port numbers so that the "+" works
+ # for IP address assignments.
+ with_ascend_hack = no
+ ascend_channels_per_line = 23
+
+ # Windows NT machines often authenticate themselves as
+ # NT_DOMAIN\username
+ #
+ # If this is set to 'yes', then the NT_DOMAIN portion
+ # of the user-name is silently discarded.
+ #
+ # This configuration entry SHOULD NOT be used.
+ # See the "realms" module for a better way to handle
+ # NT domains.
+ with_ntdomain_hack = no
+
+ # Specialix Jetstream 8500 24 port access server.
+ #
+ # If the user name is 10 characters or longer, a "/"
+ # and the excess characters after the 10th are
+ # appended to the user name.
+ #
+ # If you're not running that NAS, you don't need
+ # this hack.
+ with_specialix_jetstream_hack = no
+
+ # Cisco (and Quintum in Cisco mode) sends it's VSA attributes
+ # with the attribute name *again* in the string, like:
+ #
+ # H323-Attribute = "h323-attribute=value".
+ #
+ # If this configuration item is set to 'yes', then
+ # the redundant data in the the attribute text is stripped
+ # out. The result is:
+ #
+ # H323-Attribute = "value"
+ #
+ # If you're not running a Cisco or Quintum NAS, you don't
+ # need this hack.
+ with_cisco_vsa_hack = no
+ }
+
+ # Write a detailed log of all accounting records received.
+ #
+ detail {
+ # Note that we do NOT use NAS-IP-Address here, as
+ # that attribute MAY BE from the originating NAS, and
+ # NOT from the proxy which actually sent us the
+ # request. The Client-IP-Address attribute is ALWAYS
+ # the address of the client which sent us the
+ # request.
+ #
+ # The following line creates a new detail file for
+ # every radius client (by IP address or hostname).
+ # In addition, a new detail file is created every
+ # day, so that the detail file doesn't have to go
+ # through a 'log rotation'
+ #
+ # If your detail files are large, you may also want
+ # to add a ':%H' (see doc/variables.txt) to the end
+ # of it, to create a new detail file every hour, e.g.:
+ #
+ # ..../detail-%Y%m%d:%H
+ #
+ # This will create a new detail file for every hour.
+ #
+ detailfile = ${radacctdir}/%{Client-IP-Address}/detail-%Y%m%d
+
+ #
+ # The Unix-style permissions on the 'detail' file.
+ #
+ # The detail file often contains secret or private
+ # information about users. So by keeping the file
+ # permissions restrictive, we can prevent unwanted
+ # people from seeing that information.
+ detailperm = 0600
+
+ #
+ # Certain attributes such as User-Password may be
+ # "sensitive", so they should not be printed in the
+ # detail file. This section lists the attributes
+ # that should be suppressed.
+ #
+ # The attributes should be listed one to a line.
+ #
+ #suppress {
+ # User-Password
+ #}
+ }
+
+ #
+ # Create a unique accounting session Id. Many NASes re-use
+ # or repeat values for Acct-Session-Id, causing no end of
+ # confusion.
+ #
+ # This module will add a (probably) unique session id
+ # to an accounting packet based on the attributes listed
+ # below found in the packet. See doc/rlm_acct_unique for
+ # more information.
+ #
+ acct_unique {
+ key = "User-Name, Acct-Session-Id, NAS-IP-Address, Client-IP-Address, NAS-Port"
+ }
+
+ # Write a 'utmp' style file, of which users are currently
+ # logged in, and where they've logged in from.
+ #
+ # This file is used mainly for Simultaneous-Use checking,
+ # and also 'radwho', to see who's currently logged in.
+ #
+ radutmp {
+ # Where the file is stored. It's not a log file,
+ # so it doesn't need rotating.
+ #
+ filename = ${logdir}/radutmp
+
+ # The field in the packet to key on for the
+ # 'user' name, If you have other fields which you want
+ # to use to key on to control Simultaneous-Use,
+ # then you can use them here.
+ #
+ # Note, however, that the size of the field in the
+ # 'utmp' data structure is small, around 32
+ # characters, so that will limit the possible choices
+ # of keys.
+ #
+ # You may want instead: %{Stripped-User-Name:-%{User-Name}}
+ username = %{User-Name}
+
+
+ # Whether or not we want to treat "user" the same
+ # as "USER", or "User". Some systems have problems
+ # with case sensitivity, so this should be set to
+ # 'no' to enable the comparisons of the key attribute
+ # to be case insensitive.
+ #
+ case_sensitive = yes
+
+ # Accounting information may be lost, so the user MAY
+ # have logged off of the NAS, but we haven't noticed.
+ # If so, we can verify this information with the NAS,
+ #
+ # If we want to believe the 'utmp' file, then this
+ # configuration entry can be set to 'no'.
+ #
+ check_with_nas = yes
+
+ # Set the file permissions, as the contents of this file
+ # are usually private.
+ perm = 0600
+
+ callerid = "yes"
+ }
+
+ # "Safe" radutmp - does not contain caller ID, so it can be
+ # world-readable, and radwho can work for normal users, without
+ # exposing any information that isn't already exposed by who(1).
+ #
+ # This is another 'instance' of the radutmp module, but it is given
+ # then name "sradutmp" to identify it later in the "accounting"
+ # section.
+ radutmp sradutmp {
+ filename = ${logdir}/sradutmp
+ perm = 0644
+ callerid = "no"
+ }
+
+ # attr_filter - filters the attributes received in replies from
+ # proxied servers, to make sure we send back to our RADIUS client
+ # only allowed attributes.
+ attr_filter {
+ attrsfile = ${confdir}/attrs
+ }
+
+ # counter module:
+ # This module takes an attribute (count-attribute).
+ # It also takes a key, and creates a counter for each unique
+ # key. The count is incremented when accounting packets are
+ # received by the server. The value of the increment depends
+ # on the attribute type.
+ # If the attribute is Acct-Session-Time or of an integer type we add the
+ # value of the attribute. If it is anything else we increase the
+ # counter by one.
+ #
+ # The 'reset' parameter defines when the counters are all reset to
+ # zero. It can be hourly, daily, weekly, monthly or never.
+ #
+ # hourly: Reset on 00:00 of every hour
+ # daily: Reset on 00:00:00 every day
+ # weekly: Reset on 00:00:00 on sunday
+ # monthly: Reset on 00:00:00 of the first day of each month
+ #
+ # It can also be user defined. It should be of the form:
+ # num[hdwm] where:
+ # h: hours, d: days, w: weeks, m: months
+ # If the letter is ommited days will be assumed. In example:
+ # reset = 10h (reset every 10 hours)
+ # reset = 12 (reset every 12 days)
+ #
+ #
+ # The check-name attribute defines an attribute which will be
+ # registered by the counter module and can be used to set the
+ # maximum allowed value for the counter after which the user
+ # is rejected.
+ # Something like:
+ #
+ # DEFAULT Max-Daily-Session := 36000
+ # Fall-Through = 1
+ #
+ # You should add the counter module in the instantiate
+ # section so that it registers check-name before the files
+ # module reads the users file.
+ #
+ # If check-name is set and the user is to be rejected then we
+ # send back a Reply-Message and we log a Failure-Message in
+ # the radius.log
+ # If the count attribute is Acct-Session-Time then on each login
+ # we send back the remaining online time as a Session-Timeout attribute
+ #
+ # The counter-name can also be used instead of using the check-name
+ # like below:
+ #
+ # DEFAULT Daily-Session-Time > 3600, Auth-Type = Reject
+ # Reply-Message = "You've used up more than one hour today"
+ #
+ # The allowed-servicetype attribute can be used to only take
+ # into account specific sessions. For example if a user first
+ # logs in through a login menu and then selects ppp there will
+ # be two sessions. One for Login-User and one for Framed-User
+ # service type. We only need to take into account the second one.
+ #
+ # The module should be added in the instantiate, authorize and
+ # accounting sections. Make sure that in the authorize
+ # section it comes after any module which sets the
+ # 'check-name' attribute.
+ #
+ counter daily {
+ filename = ${raddbdir}/db.daily
+ key = User-Name
+ count-attribute = Acct-Session-Time
+ reset = daily
+ counter-name = Daily-Session-Time
+ check-name = Max-Daily-Session
+ allowed-servicetype = Framed-User
+ cache-size = 5000
+ }
+
+ #
+ # The "always" module is here for debugging purposes. Each
+ # instance simply returns the same result, always, without
+ # doing anything.
+ always fail {
+ rcode = fail
+ }
+ always reject {
+ rcode = reject
+ }
+ always ok {
+ rcode = ok
+ simulcount = 0
+ mpp = no
+ }
+
+ stg {
+ local_port = 6667
+ server = localhost
+ port = 6666
+ password = 123456
+ }
+
+}
+
+# Instantiation
+#
+# This section orders the loading of the modules. Modules
+# listed here will get loaded BEFORE the later sections like
+# authorize, authenticate, etc. get examined.
+#
+# This section is not strictly needed. When a section like
+# authorize refers to a module, it's automatically loaded and
+# initialized. However, some modules may not be listed in any
+# of the following sections, so they can be listed here.
+#
+# Also, listing modules here ensures that you have control over
+# the order in which they are initalized. If one module needs
+# something defined by another module, you can list them in order
+# here, and ensure that the configuration will be OK.
+#
+instantiate {
+ stg
+}
+
+# Authorization. First preprocess (hints and huntgroups files),
+# then realms, and finally look in the "users" file.
+#
+# The order of the realm modules will determine the order that
+# we try to find a matching realm.
+#
+# Make *sure* that 'preprocess' comes before any realm if you
+# need to setup hints for the remote radius server
+authorize {
+ #
+ # The preprocess module takes care of sanitizing some bizarre
+ # attributes in the request, and turning them into attributes
+ # which are more standard.
+ #
+ # It takes care of processing the 'raddb/hints' and the
+ # 'raddb/huntgroups' files.
+ #
+ # It also adds the %{Client-IP-Address} attribute to the request.
+ preprocess
+
+ #
+ # The chap module will set 'Auth-Type := CHAP' if we are
+ # handling a CHAP request and Auth-Type has not already been set
+ chap
+
+ #
+ # If the users are logging in with an MS-CHAP-Challenge
+ # attribute for authentication, the mschap module will find
+ # the MS-CHAP-Challenge attribute, and add 'Auth-Type := MS-CHAP'
+ # to the request, which will cause the server to then use
+ # the mschap module for authentication.
+ mschap
+
+ #
+ # This module takes care of EAP-MD5, EAP-TLS, and EAP-LEAP
+ # authentication.
+ #
+ # It also sets the EAP-Type attribute in the request
+ # attribute list to the EAP type from the packet.
+ eap
+
+ stg
+}
+
+
+# Authentication.
+#
+#
+# This section lists which modules are available for authentication.
+# Note that it does NOT mean 'try each module in order'. It means
+# that a module from the 'authorize' section adds a configuration
+# attribute 'Auth-Type := FOO'. That authentication type is then
+# used to pick the apropriate module from the list below.
+#
+
+# In general, you SHOULD NOT set the Auth-Type attribute. The server
+# will figure it out on its own, and will do the right thing. The
+# most common side effect of erroneously setting the Auth-Type
+# attribute is that one authentication method will work, but the
+# others will not.
+#
+# The common reasons to set the Auth-Type attribute by hand
+# is to either forcibly reject the user, or forcibly accept him.
+#
+authenticate {
+ #
+ # PAP authentication, when a back-end database listed
+ # in the 'authorize' section supplies a password. The
+ # password can be clear-text, or encrypted.
+ Auth-Type PAP {
+ stg
+ pap
+ }
+
+ #
+ # Most people want CHAP authentication
+ # A back-end database listed in the 'authorize' section
+ # MUST supply a CLEAR TEXT password. Encrypted passwords
+ # won't work.
+ Auth-Type CHAP {
+ stg
+ chap
+ }
+
+ #
+ # MSCHAP authentication.
+ Auth-Type MS-CHAP {
+ stg
+ mschap
+ }
+
+ #
+ # Allow EAP authentication.
+ eap
+}
+
+
+#
+# Pre-accounting. Decide which accounting type to use.
+#
+preacct {
+ preprocess
+
+ #
+ # Ensure that we have a semi-unique identifier for every
+ # request, and many NAS boxes are broken.
+ acct_unique
+}
+
+#
+# Accounting. Log the accounting data.
+#
+accounting {
+ #
+ # Create a 'detail'ed log of the packets.
+ # Note that accounting requests which are proxied
+ # are also logged in the detail file.
+ detail
+# daily
+
+ #
+ # For Simultaneous-Use tracking.
+ #
+ # Due to packet losses in the network, the data here
+ # may be incorrect. There is little we can do about it.
+ radutmp
+
+ stg
+
+}
+
+
+# Session database, used for checking Simultaneous-Use. Either the radutmp
+# or rlm_sql module can handle this.
+# The rlm_sql module is *much* faster
+session {
+ radutmp
+}
+
+
+# Post-Authentication
+# Once we KNOW that the user has been authenticated, there are
+# additional steps we can take.
+post-auth {
+ stg
+}
+
+#
+# When the server decides to proxy a request to a home server,
+# the proxied request is first passed through the pre-proxy
+# stage. This stage can re-write the request, or decide to
+# cancel the proxy.
+#
+# Only a few modules currently have this method.
+#
+pre-proxy {
+}
+
+#
+# When the server receives a reply to a request it proxied
+# to a home server, the request may be massaged here, in the
+# post-proxy stage.
+#
+post-proxy {
+ #
+ # If you are proxying LEAP, you MUST configure the EAP
+ # module, and you MUST list it here, in the post-proxy
+ # stage.
+ #
+ # You MUST also use the 'nostrip' option in the 'realm'
+ # configuration. Otherwise, the User-Name attribute
+ # in the proxied request will not match the user name
+ # hidden inside of the EAP packet, and the end server will
+ # reject the EAP request.
+ #
+ eap
+}
--- /dev/null
+#!/bin/sh
+
+rm -f /var/stargazer/ifaces/$PPP_REMOTE
\ No newline at end of file
--- /dev/null
+#!/bin/sh
+
+echo $PPP_IFACE > /var/stargazer/ifaces/$PPP_REMOTE
\ No newline at end of file
--- /dev/null
+###############################################################################
+# $Id: pptpd-options,v 1.1 2008/03/31 13:55:20 faust Exp $
+#
+# Sample Poptop PPP options file /etc/ppp/pptpd-options
+# Options used by PPP when a connection arrives from a client.
+# This file is pointed to by /etc/pptpd.conf option keyword.
+# Changes are effective on the next connection. See "man pppd".
+#
+# You are expected to change this file to suit your system. As
+# packaged, it requires PPP 2.4.2 and the kernel MPPE module.
+###############################################################################
+
+
+# Authentication
+
+# Name of the local system for authentication purposes
+# (must match the second field in /etc/ppp/chap-secrets entries)
+name pptpd
+
+# Optional: domain name to use for authentication
+# domain mydomain.net
+
+# Strip the domain prefix from the username before authentication.
+# (applies if you use pppd with chapms-strip-domain patch)
+#chapms-strip-domain
+
+
+# Encryption
+# Debian: on systems with a kernel built with the package
+# kernel-patch-mppe >= 2.4.2 and using ppp >= 2.4.2, ...
+# {{{
+refuse-pap
+refuse-chap
+refuse-mschap
+# Require the peer to authenticate itself using MS-CHAPv2 [Microsoft
+# Challenge Handshake Authentication Protocol, Version 2] authentication.
+require-mschap-v2
+# Require MPPE 128-bit encryption
+# (note that MPPE requires the use of MSCHAP-V2 during authentication)
+require-mppe-128
+# }}}
+
+
+
+
+# Network and Routing
+
+# If pppd is acting as a server for Microsoft Windows clients, this
+# option allows pppd to supply one or two DNS (Domain Name Server)
+# addresses to the clients. The first instance of this option
+# specifies the primary DNS address; the second instance (if given)
+# specifies the secondary DNS address.
+# Attention! This information may not be taken into account by a Windows
+# client. See KB311218 in Microsoft's knowledge base for more information.
+#ms-dns 10.0.0.1
+#ms-dns 10.0.0.2
+
+# If pppd is acting as a server for Microsoft Windows or "Samba"
+# clients, this option allows pppd to supply one or two WINS (Windows
+# Internet Name Services) server addresses to the clients. The first
+# instance of this option specifies the primary WINS address; the
+# second instance (if given) specifies the secondary WINS address.
+#ms-wins 10.0.0.3
+#ms-wins 10.0.0.4
+
+# Add an entry to this system's ARP [Address Resolution Protocol]
+# table with the IP address of the peer and the Ethernet address of this
+# system. This will have the effect of making the peer appear to other
+# systems to be on the local ethernet.
+# (you do not need this if your PPTP server is responsible for routing
+# packets to the clients -- James Cameron)
+proxyarp
+
+# Debian: do not replace the default route
+defaultroute
+
+
+# Logging
+
+# Enable connection debugging facilities.
+# (see your syslog configuration for where pppd sends to)
+#debug
+
+# Print out all the option values which have been set.
+# (often requested by mailing list to verify options)
+#dump
+
+
+# Miscellaneous
+
+# Create a UUCP-style lock file for the pseudo-tty to ensure exclusive
+# access.
+lock
+
+# Disable BSD-Compress compression
+nobsdcomp
+plugin radius.so
\ No newline at end of file
--- /dev/null
+###############################################################################
+# $Id: pptpd.conf,v 1.1 2008/03/31 13:54:13 faust Exp $
+#
+# Sample Poptop configuration file /etc/pptpd.conf
+#
+# Changes are effective when pptpd is restarted.
+###############################################################################
+
+# TAG: ppp
+# Path to the pppd program, default '/usr/sbin/pppd' on Linux
+#
+#ppp /usr/sbin/pppd
+
+# TAG: option
+# Specifies the location of the PPP options file.
+# By default PPP looks in '/etc/ppp/options'
+#
+option /etc/ppp/pptpd-options
+
+# TAG: debug
+# Turns on (more) debugging to syslog
+#
+#debug
+
+# TAG: stimeout
+# Specifies timeout (in seconds) on starting ctrl connection
+#
+# stimeout 10
+
+# TAG: noipparam
+# Suppress the passing of the client's IP address to PPP, which is
+# done by default otherwise.
+#
+#noipparam
+
+# TAG: logwtmp
+# Use wtmp(5) to record client connections and disconnections.
+#
+logwtmp
+
+# TAG: bcrelay <if>
+# Turns on broadcast relay to clients from interface <if>
+#
+#bcrelay eth1
+
+# TAG: localip
+# TAG: remoteip
+# Specifies the local and remote IP address ranges.
+#
+# Any addresses work as long as the local machine takes care of the
+# routing. But if you want to use MS-Windows networking, you should
+# use IP addresses out of the LAN address space and use the proxyarp
+# option in the pppd options file, or run bcrelay.
+#
+# You can specify single IP addresses seperated by commas or you can
+# specify ranges, or both. For example:
+#
+# 192.168.0.234,192.168.0.245-249,192.168.0.254
+#
+# IMPORTANT RESTRICTIONS:
+#
+# 1. No spaces are permitted between commas or within addresses.
+#
+# 2. If you give more IP addresses than MAX_CONNECTIONS, it will
+# start at the beginning of the list and go until it gets
+# MAX_CONNECTIONS IPs. Others will be ignored.
+#
+# 3. No shortcuts in ranges! ie. 234-8 does not mean 234 to 238,
+# you must type 234-238 if you mean this.
+#
+# 4. If you give a single localIP, that's ok - all local IPs will
+# be set to the given one. You MUST still give at least one remote
+# IP for each simultaneous client.
+#
+# (Recommended)
+#localip 192.168.0.1
+#remoteip 192.168.0.234-238,192.168.0.245
+# or
+#localip 192.168.0.234-238,192.168.0.245
+#remoteip 192.168.1.234-238,192.168.1.245
+localip 192.168.2.1
+remoteip 192.168.2.2-254
--- /dev/null
+localhost testing123
--- /dev/null
+login=$1
+param=$2
+oldValue=$3
+newValue=$4
+
+#echo "User: '$login'. Parameter $param changed from '$oldValue' to '$newValue'" >> /var/stargazer/users.chg.log
\ No newline at end of file
--- /dev/null
+#!/bin/bash
+
+#Этот скрипт вызывается в момент, когда пользователь
+#успешно прошел авторизацию на сервере. Задача скрипта - перестроить
+#файрвол так, что бы пользователь получил доступ в интернет
+
+# Login
+LOGIN=$1
+
+#user IP
+IP=$2
+
+#cash
+CASH=$3
+
+#user ID
+ID=$4
+
+#Selected dirs to connect
+DIRS=$5
+
+iptables -A INPUT -s $IP -j QUEUE
+iptables -A OUTPUT -d $IP -j QUEUE
+iptables -A FORWARD -s $IP -j QUEUE
+iptables -A FORWARD -d $IP -j QUEUE
+
+# shaper
+
+default_speed=32
+
+speedR=$(grep -i "^Userdata0=" /var/stargazer/users/$LOGIN/conf | cut -f 2 -d"=")
+#echo "speedR=$speedR" >> /var/stargazer/users/$LOGIN/connect.log
+speed=$(echo $speedR | grep "^[0-9]*[0-9]$")
+
+if [ -z "$speed" ]
+then
+ speed=$default_speed
+fi
+
+speedkbit=$speed"kbit"
+
+#echo "speed=$speedkbit" >> /var/stargazer/users/$LOGIN/connect.log
+declare -i mark=$ID+1
+
+iptables -t mangle -A FORWARD -d $IP -j MARK --set-mark $mark
+
+sleep 1
+
+if [ -f "/var/stargazer/ifaces/$IP" ]
+then
+ #echo "1" >> /var/stargazer/users/$LOGIN/connect.log
+ ppp_iface=$(cat /var/stargazer/ifaces/$IP)
+else
+ #echo "2" >> /var/stargazer/users/$LOGIN/connect.log
+ exit 0
+fi
+
+tc qdisc add dev $ppp_iface root handle 1: htb
+tc class add dev $ppp_iface parent 1: classid 1:1 htb rate 100mbit ceil 100mbit burst 200k
+tc class add dev $ppp_iface parent 1:1 classid 1:10 htb rate $speedkbit burst 20k
+tc filter add dev $ppp_iface parent 1: protocol ip prio 3 handle $mark fw classid 1:10
+
+#echo "C `date +%Y.%m.%d-%H.%M.%S` $IP $CASH $ID $mark $speed $ppp_iface" >> /var/stargazer/users/$LOGIN/connect.log
+
--- /dev/null
+#!/bin/bash
+
+# Этот скрипт вызывается в момент, когда пользователь
+# желает отключится от интернета или вышел таймаут у пользователя
+# и сервер сам отключает пользователя
+# Задача скрипта подобна задаче скрипта OnConnect - перестроить
+# файрвол так, что бы пользователю закрыть доступ в интернет
+
+# Login
+LOGIN=$1
+
+#user IP
+IP=$2
+
+#cash
+CASH=$3
+
+#user ID
+ID=$4
+
+#Selected dirs to disconnect
+DIRS=$4
+
+#echo "D `date +%Y.%m.%d-%H.%M.%S` $IP $CASH" >> /var/stargazer/users/$LOGIN/connect.log
+
+iptables -D INPUT -s $IP -j QUEUE
+while [ $? == 0 ]
+do
+ iptables -D INPUT -s $IP -j QUEUE
+done
+
+iptables -D OUTPUT -d $IP -j QUEUE
+while [ $? == 0 ]
+do
+ iptables -D OUTPUT -d $IP -j QUEUE
+done
+
+iptables -D FORWARD -s $IP -j QUEUE
+while [ $? == 0 ]
+do
+ iptables -D FORWARD -s $IP -j QUEUE
+done
+
+iptables -D FORWARD -d $IP -j QUEUE
+while [ $? == 0 ]
+do
+ iptables -D FORWARD -d $IP -j QUEUE
+done
+
+
+
+declare -i mark=$ID+1
+
+iptables -t mangle -D FORWARD -d $IP -j MARK --set-mark $mark
+while [ $? == 0 ]
+do
+ iptables -t mangle -D FORWARD -d $IP -j MARK --set-mark $mark
+done
+
+
+if [ -f /var/stargazer/ifaces/$IP ]
+ ppp_iface=$(cat /var/stargazer/ifaces/$IP)
+else
+ exit 0
+fi
+
+tc qdisc del dev $ppp_iface root
+
+
--- /dev/null
+# Использование (неиспользование) этого скрипта дело вкуса.
+# Он не выполняет критических функций. Его задача автматизировать
+# действия характерные при добавлении пользователя сети, например добавлекние
+# пользователю почты
+
+# Login
+login=$1
+
+#echo "added user $login" >> /var/stargazer/add_del.log
+
+
+
--- /dev/null
+# Login
+login=$1
+
+#echo "deleted user $login" >> /var/stargazer/add_del.log
+
--- /dev/null
+ALL 192.168.0.0/16 DIR1
+ALL 10.0.0.0/8 DIR2
+ALL 0.0.0.0/0 DIR0
\ No newline at end of file
--- /dev/null
+
+# Имя лог-файла куда пишутся события
+LogFile = /var/log/stargazer.log
+
+
+
+# Имя файла в котором определяются правила подсчета трафика
+Rules = /etc/stargazer/rules
+
+
+
+# Время через которое пишется d БД детальная статистика пользователя
+# Значения: 1, 1/2, 1/4, 1/6.
+# 1 - раз в чаc, 1/2 - раз в пол часа, 1/4 - раз в 15 мин, 1/6 - раз в 10 мин
+DetailStatWritePeriod=1/6
+
+
+
+# Периодичность записи записи в БД информации о статистике пользователя (минуты)
+# При большом кол-ве пользователей эту величину стоит увеличить, т.к.
+# запись в БД может занимать длительное время.
+# Значения: 1...1440 (минуты)
+StatWritePeriod = 10
+
+
+
+# День снятия абонплаты
+# Значения: 0...31. 0 - Последний день месяца
+DayFee = 1
+
+
+
+# Абонплата снимается в последний (yes) или первый (no) день учетного периода.
+# Это влияет на то, как будет снята абонплата (АП) при переходе на новый тариф.
+# Если у пользователя был тариф A с АП=100 и он хочет перейти на тариф B с АП=200,
+# то при переходе на новый тариф со счета пользователя снимется 100, если
+# DayFeeIsLastDay = yes и 200, если DayFeeIsLastDay = no
+DayFeeIsLastDay = yes
+
+
+
+# День сброса данных о трафике за месяц и день перехода пользователей на новые тарифы
+# Значения: 0...31. 0 - Последний день месяца
+DayResetTraff = 1
+
+
+
+# "Размазанное" снятие абонплаты. Снятие АП не раз в месяц, а каждый
+# день 1/30 или 1/31 части АП
+# Значения: yes, no
+SpreadFee = no
+
+
+
+# Данная опция определяет может ли пользователь получить доступ в интерент
+# если у него на счету нет денег, но остался предоплаченный трафик
+# Значения: yes, no
+FreeMbAllowInet = no
+
+
+
+# Эта опция определяет что будет писаться в стоимость трафика в detail_stat.
+# Если у пользователя еще есть предоплаченный трафик и WriteFreeMbTraffCost = no,
+# то в detail_stat стоимость будет 0. Если у пользователя уже нет
+# предоплаченного трафика и WriteFreeMbTraffCost = no, то в detail_stat
+# будет записана стоиость трафика. При WriteFreeMbTraffCost = yes стоимость
+# трафика будет записана в любом случае.
+WriteFreeMbTraffCost = no
+
+
+
+# Необязательный параметр. Указывает снимать полную абонплату у пользователя даже
+# если он быз заморожен только часть учетного периода.
+# По умолчанию установлен в no
+# FullFee=no
+
+# Необязательный параметр указывающий показывать на счету и позволять
+# использовать пользователю абонплату. По умолчанию установлен в yes
+# ShowFeeInCash=yes
+
+
+
+# Названия направлений. Направления без названий не будут отображаться в
+# авторизаторе и конфигураторе. Названия состоящие из нескольких слов должны
+# быть взяты в кавычки
+<DirNames>
+ DirName0 = Local
+ DirName1 = City
+ DirName2 = World
+ DirName3 =
+ DirName4 =
+ DirName5 =
+ DirName6 =
+ DirName7 =
+ DirName8 =
+ DirName9 =
+</DirNames>
+
+
+
+# Кол-во запускаемых процессов stg-exec.
+# Эти процессы отвечают за выполнение скриптов OnConnect, OnDisconnect, ...
+# Кол-во процессов означает сколько скриптов могут выполнятся одновременно.
+# Значения: 1...1024
+ExecutersNum = 2
+
+
+
+# Message Key для stg-exec.
+# Идентификатор очереди сообщений для выполнятеля скриптов.
+# Его изменение может понадобится если есть необходимость запустить несколько
+# экземпляров stg. Если вы не понимаете, что это, не трогайте этот параметр!
+# Значения: 0...2^32
+# Значение по умолчанию: 5555
+# ExecMsgKey = 5555
+
+
+
+# Путь к директории, в которой находятся модули сервера
+ModulesPath = /usr/lib/stg
+
+# Определяет директорию, в которой будут находится файлы "монитора"
+# работы сервера. В этой директории будут созданы пустые файлы, время
+# модификации которых будет меняться примерно раз в минуту. Если какой-то
+# компонент сервера зависнет, файл(ы) перестанет обновлятся, и по этому
+# признаку можно определить сбой в работе сервера и при надобности
+# перезапустить. Если параметр не указан или пустой, мониторинг производится
+# не будет. Параметр не является обязательным, по умолчанию пустой.
+# MonitorDir=/var/stargazer/monitor
+
+
+################################################################################
+# Store module
+# Настройки плагина работающего с БД сервера
+
+# Второй параметр - это имя модуля без mod_ в начале и .so в конце
+# Т.е. полное имя модуля mod_store_files.so
+<StoreModule store_files>
+
+ # Рабочая директория сервера, тут содержатся данные о тарифах, пользователях,
+ # администраторах и т.д.
+ WorkDir = /var/stargazer
+
+
+ # Владелец, группа и права доступа на файлы статистики (stat) пользователя
+ ConfOwner = root
+ ConfGroup = root
+ ConfMode = 600
+
+
+ # Владелец, группа и права доступа на файлы конфигурации (conf) пользователя
+ StatOwner = root
+ StatGroup = root
+ StatMode = 640
+
+ # Владелец, группа и права доступа на лог-файлы (log) пользователя
+ UserLogOwner = root
+ UserLogGroup = root
+ UserLogMode = 640
+
+</StoreModule>
+
+#<StoreModule store_firebird>
+# # Адрес сервера БД
+# server=localhost
+#
+# # Путь к БД на сервере или ее алиас
+# path=/var/stg/stargazer.fdb
+#
+# # Имя пользователя БД
+# user=stg
+#
+# # Пароль пользователя БД
+# password=123456
+#</StoreModule>
+
+#<StoreModule store_mysql>
+# # Имя пользователя БД
+# dbuser = stg
+#
+# # Пароль пользователя БД
+# rootdbpass = 123456
+#
+# # Имя БД на сервере
+# dbname = stg
+#
+# # Адрес сервера БД
+# dbhost = localhost
+#</StoreModule>
+
+
+
+################################################################################
+# Прочие модули
+
+<Modules>
+
+ # Настройки плагина авторизации Always Online "mod_auth_ao.so"
+ # Второй параметр - это имя модуля без mod_ в начале и .so в конце
+ # Т.е. полное имя модуля mod_auth_ao.so
+ #<Module auth_ao>
+ #</Module>
+
+
+
+ # Настройки плагина авторизации InetAccess "mod_auth_ia.so"
+ # Второй параметр - это имя модуля без mod_ в начале и .so в конце
+ # Т.е. полное имя модуля mod_auth_ia.so
+ #<Module auth_ia>
+ # Port = 5555
+ # UserDelay = 15
+ # UserTimeout = 65
+ # FreeMb = 0
+ #</Module>
+
+
+
+ # Настройки модуля конфигурации SgConfig "mod_conf_sg.so"
+ # Второй параметр - это имя модуля без mod_ в начале и .so в конце
+ <Module conf_sg>
+
+ # Порт по которому сервер взаимодействует с конфигуратором
+ # Значения: 1...65535
+ Port = 5555
+
+ </Module>
+
+
+
+ # Модуль захвата трафика "mod_cap_ether.so"
+ # Второй параметер - это имя модуля без mod_ в начале и .so в конце
+ # Без параметров. Только имя модуля.
+ <Module cap_ipq>
+ # Модуль без параметров
+ </Module>
+
+
+
+ # Настройки модуля пингующего пользователей "mod_ping.so"
+ # Второй параметр - это имя модуля без mod_ в начале и .so в конце
+ <Module ping>
+
+ # Время, в секундах, между пингами одного и того же пользователя
+ # Значения: 10...3600
+ PingDelay = 15
+
+ </Module>
+
+ <Module radius>
+ Password = 123456
+ ServerIP = 127.0.0.1
+ Port = 6666
+ AuthServices = Login-User
+ AcctServices = Framed-User
+ </Module>
+
+# # Настройки модуля для удаленного выполнения скриптов OnConnect и
+# # OnDisconnect "mod_remote_script.so"
+# # Второй параметр - это имя модуля без mod_ в начале и .so в конце
+# <Module remote_script>
+#
+# # Время, в секундах, между посылками подтверждений, того, что пользователь
+# # всё еще онлайн
+# # Значения: 10...600
+# SendPeriod = 15
+#
+# # Соответствие подсетей, в которой находится пользователь и
+# # соответствующего роутера. Первая часть строки - подсеть, заданная
+# # как IP-адрес и маска, через пробел - IP-адрес роутера на котором
+# # должны выполняться скрипты
+# # Например эта запись "192.168.1.0/24 192.168.1.1" означает, что для
+# # всех пользователей из подсети 192.168.1.0/24, скрипты будут
+# # выполняться на роутере с адресом 192.168.1.1
+# # Subnet0...Subnet100
+# Subnet0 = 192.168.1.0/24 192.168.1.7
+# Subnet1 = 192.168.2.0/24 192.168.2.5
+# Subnet2 = 192.168.3.0/24 192.168.2.5
+# Subnet3 = 192.168.4.0/24 192.168.2.5
+#
+# # Пароль для шифрования пакетов между stg-сервером и сервером,
+# # выполняющим скрипты
+# Password = 123456
+#
+# # Этот параметр определяет какие параметры пользователя передаются
+# # на удаленный сервер
+# # Cash, FreeMb, Passive, Disabled, AlwaysOnline, TariffName, NextTariff, Address,
+# # Note, Group, Email, RealName, Credit, EnabledDirs, Userdata0...Userdata9
+# UserParams=Cash Tariff EnabledDirs
+#
+# # Порт по которому сервер отсылает сообщения на роутер
+# # Значения: 1...65535
+# Port = 9999
+#
+# </Module>
+
+</Modules>
+################################################################################
+
--- /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>
+ */
+
+/*
+$Revision: 1.45 $
+$Date: 2010/08/19 13:42:30 $
+$Author: faust $
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <string>
+
+using namespace std;
+
+#include "settings.h"
+#include "common.h"
+
+//-----------------------------------------------------------------------------
+SETTINGS::SETTINGS()
+ : confDir("/etc/stargazer"),
+ scriptDir("/etc/stargazer"),
+ pidFile("/var/run/stargazer.pid"),
+ monitoring(false),
+ detailStatWritePeriod(dsPeriod_1_6),
+ statWritePeriod(10),
+ stgExecMsgKey(5555),
+ executersNum(1),
+ fullFee(false),
+ dayFee(0),
+ dayResetTraff(0),
+ spreadFee(false),
+ freeMbAllowInet(false),
+ dayFeeIsLastDay(false),
+ writeFreeMbTraffCost(false),
+ showFeeInCash(true),
+ logger(GetStgLogger())
+{
+}
+//-----------------------------------------------------------------------------
+SETTINGS::SETTINGS(const std::string & cd)
+ : confDir(cd),
+ scriptDir(cd),
+ pidFile(),
+ monitoring(false),
+ detailStatWritePeriod(dsPeriod_1_6),
+ statWritePeriod(10),
+ stgExecMsgKey(5555),
+ executersNum(1),
+ fullFee(false),
+ dayFee(0),
+ dayResetTraff(0),
+ spreadFee(false),
+ freeMbAllowInet(false),
+ dayFeeIsLastDay(false),
+ writeFreeMbTraffCost(false),
+ showFeeInCash(true),
+ logger(GetStgLogger())
+{
+}
+//-----------------------------------------------------------------------------
+SETTINGS::SETTINGS(const SETTINGS & rval)
+ : confDir(rval.confDir),
+ scriptDir(rval.scriptDir),
+ detailStatWritePeriod(dsPeriod_1_6),
+ statWritePeriod(10),
+ dayFee(0),
+ dayResetTraff(0),
+ freeMbAllowInet(false),
+ dayFeeIsLastDay(false),
+ writeFreeMbTraffCost(false),
+ logger(GetStgLogger())
+{
+spreadFee = rval.spreadFee;
+pidFile = rval.pidFile;
+stgExecMsgKey = rval.stgExecMsgKey;
+executersNum = rval.executersNum;
+showFeeInCash = rval.showFeeInCash;
+fullFee = rval.fullFee;
+monitoring = rval.monitoring;
+}
+//-----------------------------------------------------------------------------
+SETTINGS::~SETTINGS()
+{
+}
+//-----------------------------------------------------------------------------
+int SETTINGS::ParseYesNo(const string & value, bool * val)
+{
+if (0 == strcasecmp(value.c_str(), "yes"))
+ {
+ *val = true;
+ return 0;
+ }
+if (0 == strcasecmp(value.c_str(), "no"))
+ {
+ *val = false;
+ return 0;
+ }
+
+strError = "Incorrect value \'" + value + "\'.";
+return -1;
+}
+//-----------------------------------------------------------------------------
+int SETTINGS::ParseInt(const string & value, int * val)
+{
+/*char *res;
+*val = strtol(value.c_str(), &res, 10);*/
+if (str2x<int>(value, *val))
+ {
+ strError = "Cannot convert \'" + value + "\' to integer.";
+ return -1;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int SETTINGS::ParseIntInRange(const string & value, int min, int max, int * val)
+{
+if (ParseInt(value, val) != 0)
+ return -1;
+
+if (*val < min || *val > max)
+ {
+ strError = "Value \'" + value + "\' out of range.";
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int SETTINGS::ParseModuleSettings(const DOTCONFDocumentNode * node, vector<PARAM_VALUE> * params)
+{
+/*if (!node)
+ return 0;*/
+const DOTCONFDocumentNode * childNode;
+PARAM_VALUE pv;
+const char * value;
+
+pv.param = node->getName();
+
+if (node->getValue(1))
+ {
+ strError = "Unexpected value \'" + string(node->getValue(1)) + "\'.";
+ return -1;
+ }
+
+value = node->getValue(0);
+
+if (!value)
+ {
+ strError = "Module name expected.";
+ return -1;
+ }
+
+childNode = node->getChildNode();
+while (childNode)
+ {
+ pv.param = childNode->getName();
+ int i = 0;
+ while ((value = childNode->getValue(i)) != NULL)
+ {
+ //printfd(__FILE__, "--> param=\'%s\' value=\'%s\'\n", childNode->getName(), value);
+ pv.value.push_back(value);
+ i++;
+ }
+ params->push_back(pv);
+ pv.value.clear();
+ childNode = childNode->getNextNode();
+ }
+
+/*for (unsigned i = 0; i < params->size(); i++)
+ {
+ printfd(__FILE__, "param \'%s\'\n", (*params)[i].param.c_str());
+ for (unsigned j = 0; j < (*params)[i].value.size(); j++)
+ {
+ printfd(__FILE__, "value \'%s\'\n", (*params)[i].value[j].c_str());
+ }
+ }*/
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+string SETTINGS::GetStrError() const
+{
+return strError;
+}
+//-----------------------------------------------------------------------------
+void SETTINGS::ErrorCallback(void * data, const char * buf)
+{
+ printfd(__FILE__, buf);
+ SETTINGS * settings = static_cast<SETTINGS *>(data);
+ settings->logger(buf);
+}
+//-----------------------------------------------------------------------------
+int SETTINGS::ReadSettings()
+{
+const char * requiredOptions[] = {
+ "ModulesPath",
+ "Modules",
+ "StoreModule",
+ "Rules",
+ "LogFile",
+ "DetailStatWritePeriod",
+ "DayFee",
+ "DayResetTraff",
+ "SpreadFee",
+ "FreeMbAllowInet",
+ "DayFeeIsLastDay",
+ "WriteFreeMbTraffCost",
+ NULL
+ };
+int storeModulesCount = 0;
+modulesSettings.clear();
+
+DOTCONFDocument conf(DOTCONFDocument::CASEINSENSITIVE);
+conf.setErrorCallback(SETTINGS::ErrorCallback, this);
+conf.setRequiredOptionNames(requiredOptions);
+string confFile = confDir + "/stargazer.conf";
+
+//printfd(__FILE__, "Conffile: %s\n", confFile.c_str());
+
+if(conf.setContent(confFile.c_str()) != 0)
+ {
+ strError = "Cannot read file " + confFile;
+ return -1;
+ }
+
+const DOTCONFDocumentNode * node = conf.getFirstNode();
+
+while (node)
+ {
+ if (strcasecmp(node->getName(), "ScriptDir") == 0)
+ {
+ scriptDir = node->getValue(0);
+ //printfd(__FILE__, "LogFile: %s\n", logFile.c_str());
+ }
+
+ if (strcasecmp(node->getName(), "LogFile") == 0)
+ {
+ logFile = node->getValue(0);
+ //printfd(__FILE__, "LogFile: %s\n", logFile.c_str());
+ }
+
+ if (strcasecmp(node->getName(), "PIDFile") == 0)
+ {
+ pidFile = node->getValue(0);
+ //printfd(__FILE__, "PIDFile: %s\n", pidFile.c_str());
+ }
+
+ if (strcasecmp(node->getName(), "ModulesPath") == 0)
+ {
+ modulesPath = node->getValue(0);
+ //printfd(__FILE__, "ModulesPath: %s\n", logFile.c_str());
+ }
+
+ if (strcasecmp(node->getName(), "Rules") == 0)
+ {
+ rules = node->getValue(0);
+ //printfd(__FILE__, "Rules: %s\n", rules.c_str());
+ }
+
+ if (strcasecmp(node->getName(), "DetailStatWritePeriod") == 0)
+ {
+ if (ParseDetailStatWritePeriod(node->getValue(0)) != 0)
+ {
+ strError = "Incorrect DetailStatWritePeriod value: \'" + string(node->getValue(0)) + "\'";
+ return -1;
+ }
+ //printfd(__FILE__, "DetailStatWritePeriod: %d\n", detailStatWritePeriod);
+ }
+
+ if (strcasecmp(node->getName(), "StatWritePeriod") == 0)
+ {
+ if (ParseIntInRange(node->getValue(0), 1, 1440, &statWritePeriod) != 0)
+ {
+ strError = "Incorrect StatWritePeriod value: \'" + string(node->getValue(0)) + "\'";
+ return -1;
+ }
+ //printfd(__FILE__, "StatWritePeriod: %d\n", statWritePeriod);
+ }
+
+ if (strcasecmp(node->getName(), "ExecMsgKey") == 0)
+ {
+ if (ParseInt(node->getValue(0), &stgExecMsgKey) != 0)
+ {
+ strError = "Incorrect ExecMsgKey value: \'" + string(node->getValue(0)) + "\'";
+ return -1;
+ }
+ }
+
+ if (strcasecmp(node->getName(), "ExecutersNum") == 0)
+ {
+ if (ParseIntInRange(node->getValue(0), 1, 1024, &executersNum) != 0)
+ {
+ strError = "Incorrect ExecutersNum value: \'" + string(node->getValue(0)) + "\'";
+ return -1;
+ }
+ //printfd(__FILE__, "DayResetTraff: %d\n", dayResetTraff);
+ }
+
+ /*if (strcasecmp(node->getName(), "ExecutersWaitTimeout") == 0)
+ {
+ if (ParseIntInRange(node->getValue(0), 1, 600, &executersWaitTimeout) != 0)
+ {
+ strError = "Incorrect ExecutersWaitTimeout value: \'" + string(node->getValue(0)) + "\'";
+ return -1;
+ }
+ //printfd(__FILE__, "DayResetTraff: %d\n", dayResetTraff);
+ }*/
+
+ if (strcasecmp(node->getName(), "DayFee") == 0)
+ {
+ if (ParseIntInRange(node->getValue(0), 0, 31, &dayFee) != 0)
+ {
+ strError = "Incorrect DayFee value: \'" + string(node->getValue(0)) + "\'";
+ return -1;
+ }
+ //printfd(__FILE__, "DayFee: %d\n", dayFee);
+ }
+
+ if (strcasecmp(node->getName(), "FullFee") == 0)
+ {
+ if (ParseYesNo(node->getValue(0), &fullFee) != 0)
+ {
+ strError = "Incorrect FullFee value: \'" + string(node->getValue(0)) + "\'";
+ return -1;
+ }
+ //printfd(__FILE__, "DayFee: %d\n", dayFee);
+ }
+
+ if (strcasecmp(node->getName(), "DayResetTraff") == 0)
+ {
+ if (ParseIntInRange(node->getValue(0), 0, 31, &dayResetTraff) != 0)
+ {
+ strError = "Incorrect DayResetTraff value: \'" + string(node->getValue(0)) + "\'";
+ return -1;
+ }
+ //printfd(__FILE__, "DayResetTraff: %d\n", dayResetTraff);
+ }
+
+ if (strcasecmp(node->getName(), "SpreadFee") == 0)
+ {
+ if (ParseYesNo(node->getValue(0), &spreadFee) != 0)
+ {
+ strError = "Incorrect SpreadFee value: \'" + string(node->getValue(0)) + "\'";
+ return -1;
+ }
+ //printfd(__FILE__, "SpreadFee: %d\n", spreadFee);
+ }
+
+ if (strcasecmp(node->getName(), "FreeMbAllowInet") == 0)
+ {
+ if (ParseYesNo(node->getValue(0), &freeMbAllowInet) != 0)
+ {
+ strError = "Incorrect FreeMbAllowInet value: \'" + string(node->getValue(0)) + "\'";
+ return -1;
+ }
+ //printfd(__FILE__, "FreeMbAllowInet: %d\n", freeMbAllowInet);
+ }
+
+ if (strcasecmp(node->getName(), "DayFeeIsLastDay") == 0)
+ {
+ if (ParseYesNo(node->getValue(0), &dayFeeIsLastDay) != 0)
+ {
+ strError = "Incorrect DayFeeIsLastDay value: \'" + string(node->getValue(0)) + "\'";
+ return -1;
+ }
+ //printfd(__FILE__, "DayFeeIsLastDay: %d\n", dayFeeIsLastDay);
+ }
+
+ if (strcasecmp(node->getName(), "WriteFreeMbTraffCost") == 0)
+ {
+ if (ParseYesNo(node->getValue(0), &writeFreeMbTraffCost) != 0)
+ {
+ strError = "Incorrect WriteFreeMbTraffCost value: \'" + string(node->getValue(0)) + "\'";
+ return -1;
+ }
+ //printfd(__FILE__, "WriteFreeMbTraffCost: %d\n", writeFreeMbTraffCost);
+ }
+
+ if (strcasecmp(node->getName(), "ShowFeeInCash") == 0)
+ {
+ if (ParseYesNo(node->getValue(0), &showFeeInCash) != 0)
+ {
+ strError = "Incorrect ShowFeeInCash value: \'" + string(node->getValue(0)) + "\'";
+ return -1;
+ }
+ //printfd(__FILE__, "ShowFeeInCash: %d\n", showFeeInCash);
+ }
+
+ if (strcasecmp(node->getName(), "MonitorDir") == 0)
+ {
+ monitorDir = node->getValue(0);
+ struct stat stat;
+ monitoring = false;
+
+ if (!lstat(monitorDir.c_str(), &stat) && S_ISDIR(stat.st_mode))
+ {
+ monitoring = true;
+ }
+ }
+
+ if (strcasecmp(node->getName(), "DirNames") == 0)
+ {
+ // íÙ ×ÎÕÔÒÉ ÓÅËÃÉÉ DirNames
+ const DOTCONFDocumentNode * child = node->getChildNode();
+ if (child)
+ {
+ const DOTCONFDocumentNode * dirNameNode;
+ for (int i = 0; i < DIR_NUM; i++)
+ {
+ char strDirName[12];
+ sprintf(strDirName, "DirName%d", i);
+ dirNameNode = conf.findNode(strDirName, node);
+ if (dirNameNode && dirNameNode->getValue(0))
+ {
+ dirName[i] = dirNameNode->getValue(0);
+ //printfd(__FILE__, "dirName[%d]: %s\n", i, dirName[i].c_str());
+ }
+ }
+ }
+ }
+
+ if (strcasecmp(node->getName(), "StoreModule") == 0)
+ {
+ // íÙ ×ÎÕÔÒÉ ÓÅËÃÉÉ StoreModule
+ //printfd(__FILE__, "StoreModule\n");
+
+ if (node->getValue(1))
+ {
+ // StoreModule ÄÏÌÖÅÎ ÉÍÅÔØ 1 ÁÔÒÉÂÕÔ
+ strError = "Unexpected \'" + string(node->getValue(1)) + "\'.";
+ return -1;
+ }
+
+ if (storeModulesCount)
+ {
+ // äÏÌÖÅÎ ÂÙÔØ ÔÏÌØËÏ ÏÄÉÎ ÍÏÄÕÌØ StoreModule!
+ strError = "Should be only one StoreModule.";
+ return -1;
+ }
+ storeModulesCount++;
+
+ //storeModuleSettings.clear(); //TODO To make constructor
+ //printfd(__FILE__, "StoreModule %s\n", node->getValue());
+ storeModuleSettings.moduleName = node->getValue(0);
+ ParseModuleSettings(node, &storeModuleSettings.moduleParams);
+ }
+
+ // þÉÔÁÅÍ ÎÁÓÔÒÏÊËÉ ×ÓÅÈ ÏÓÔÁ×ÛÉÈÓÑ ÍÏÄÕÌÅÊ.
+ if (strcasecmp(node->getName(), "Modules") == 0)
+ {
+ // íÙ ×ÎÕÔÒÉ ÓÅËÃÉÉ Modules
+ if (node->getValue(0))
+ {
+ // Modules ÎÅ ÄÏÌÖÅÎ ÉÍÅÔØ ÁÔÒÉÂÕÏ×
+ strError = "Unexpected \'" + string(node->getValue(0)) + "\'.";
+ return -1;
+ }
+ const DOTCONFDocumentNode * child = node->getChildNode();
+ while (child)
+ {
+ // íÙ ×ÎÕÔÒÉ ÓÅËÃÉÉ
+ //printfd(__FILE__, "Module \'%s\'\n", child->getValue(0));
+ if (strcasecmp(child->getName(), "Module") != 0)
+ {
+ child = child->getNextNode();
+ continue;
+ }
+ MODULE_SETTINGS modSettings;
+ modSettings.moduleParams.clear();
+ modSettings.moduleName = child->getValue();
+
+ ParseModuleSettings(child, &modSettings.moduleParams);
+
+ modulesSettings.push_back(modSettings);
+
+ child = child->getNextNode();
+ }
+ }
+
+ node = node->getNextNode();
+ }
+
+//sort(modulesSettings.begin(), modulesSettings.end());
+//modulesSettings.erase(unique(modulesSettings.begin(), modulesSettings.end()), modulesSettings.end());
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int SETTINGS::ParseDetailStatWritePeriod(const string & detailStatPeriodStr)
+{
+if (detailStatPeriodStr == "1")
+ {
+ detailStatWritePeriod = dsPeriod_1;
+ return 0;
+ }
+else if (detailStatPeriodStr == "1/2")
+ {
+ detailStatWritePeriod = dsPeriod_1_2;
+ return 0;
+ }
+else if (detailStatPeriodStr == "1/4")
+ {
+ detailStatWritePeriod = dsPeriod_1_4;
+ return 0;
+ }
+else if (detailStatPeriodStr == "1/6")
+ {
+ detailStatWritePeriod = dsPeriod_1_6;
+ return 0;
+ }
+
+return -1;
+}
+//-----------------------------------------------------------------------------
+int SETTINGS::Reload ()
+{
+return ReadSettings();
+}
+//-----------------------------------------------------------------------------
+const MODULE_SETTINGS & SETTINGS::GetStoreModuleSettings() const
+{
+return storeModuleSettings;
+}
+//-----------------------------------------------------------------------------
+const vector<MODULE_SETTINGS> & SETTINGS::GetModulesSettings() const
+{
+return modulesSettings;
+}
+//-----------------------------------------------------------------------------
+/*int SETTINGS::GetExecutersWaitTimeout() const
+{
+return executersWaitTimeout;
+}*/
+//-----------------------------------------------------------------------------
--- /dev/null
+ /*
+ $Revision: 1.27 $
+ $Date: 2010/08/19 13:42:30 $
+ $Author: faust $
+ */
+
+/*
+ * 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>
+ */
+
+ /*
+ $Revision: 1.27 $
+ $Date: 2010/08/19 13:42:30 $
+ */
+
+
+#ifndef settingsh_h
+#define settingsh_h 1
+
+#include <sys/types.h>
+#include <vector>
+#include <dotconfpp.h>
+
+#include "common.h"
+#include "base_settings.h"
+#include "stg_logger.h"
+
+using namespace std;
+
+//-----------------------------------------------------------------------------
+enum DETAIL_STAT_PERIOD
+{
+dsPeriod_1,
+dsPeriod_1_2,
+dsPeriod_1_4,
+dsPeriod_1_6,
+};
+//-----------------------------------------------------------------------------
+class SETTINGS
+{
+public:
+ SETTINGS();
+ SETTINGS(const std::string &);
+ SETTINGS(const SETTINGS &);
+ virtual ~SETTINGS();
+ int Reload();
+ int ReadSettings();
+
+ string GetStrError() const;
+
+ int GetExecMsgKey() const { return stgExecMsgKey; };
+ int GetExecutersNum() const { return executersNum; };
+ //int GetExecutersWaitTimeout() const;
+ const string & GetDirName(int num) const { return dirName[num]; };
+ const string & GetConfDir() const { return confDir; };
+ const string & GetScriptDir() const { return scriptDir; };
+ const string & GetRulesFileName() const { return rules; };
+ const string & GetLogFileName() const { return logFile; };
+ const string & GetPIDFileName() const { return pidFile; };
+ int GetDetailStatWritePeriod() const
+ { return detailStatWritePeriod; };
+ int GetStatWritePeriod() const { return statWritePeriod * 60; };
+ int GetDayFee() const { return dayFee; };
+ bool GetFullFee() const { return fullFee; };
+ int GetDayResetTraff() const { return dayResetTraff; };
+ bool GetSpreadFee() const { return spreadFee; };
+ bool GetFreeMbAllowInet() const { return freeMbAllowInet; };
+ bool GetDayFeeIsLastDay() const { return dayFeeIsLastDay; };
+ bool GetWriteFreeMbTraffCost() const
+ { return writeFreeMbTraffCost; };
+ bool GetShowFeeInCash() const { return showFeeInCash; };
+ const string & GetMonitorDir() const { return monitorDir; };
+ bool GetMonitoring() const { return monitoring; };
+
+ const string & GetModulesPath() const { return modulesPath; };
+ const MODULE_SETTINGS & GetStoreModuleSettings() const;
+ const vector<MODULE_SETTINGS> & GetModulesSettings() const;
+
+private:
+
+ int ParseInt(const string & value, int * val);
+ int ParseIntInRange(const string & value, int min, int max, int * val);
+ int ParseYesNo(const string & value, bool * val);
+ int ParseDetailStatWritePeriod(const string & detailStatPeriodStr);
+
+ int ParseModuleSettings(const DOTCONFDocumentNode * dirNameNode, vector<PARAM_VALUE> * params);
+
+ static void ErrorCallback(void * data, const char * buf);
+
+ string strError;
+ //////////settings
+ string modulesPath;
+ string dirName[DIR_NUM];
+ string confDir;
+ string scriptDir;
+ string rules;
+ string logFile;
+ string pidFile;
+ string monitorDir;
+ bool monitoring;
+ int detailStatWritePeriod;
+ int statWritePeriod;
+ int stgExecMsgKey;
+ int executersNum;
+ //int executersWaitTimeout;
+ bool fullFee;
+ int dayFee; // ÄÅÎØ ÓÎÑÔÉÑ ÁÂÏÎÐÌÁÔÙ
+ int dayResetTraff; // îÁÞÁÌÏ ÕÞÅÔÎÏÇÏ ÐÅÒÉÏÄÁ: ÄÅÎØ ÏÂÎÕÌÅÎÉÑ ÔÒÁÆÉËÁ É ÓÍÅÎÙ ÔÁÒÉÆÁ
+ bool spreadFee;
+ bool freeMbAllowInet;
+ bool dayFeeIsLastDay; // áð ÓÎÉÍÁÅÔÓÑ × ËÏÎÃÅ ÍÅÓÑÃÁ (true) ÉÌÉ × ÎÁÞÁÌÅ (false)
+ bool writeFreeMbTraffCost; // ðÉÓÁÔØ × ÄÅÔÁÌØÎÕÀ ÓÔÁÔÉÓÔÉËÕ ÓÔÏÉÍÏÓÔØ ÔÒÁÆÉËÁ, ÅÓÌÉ ÅÝÅ ÅÓÔØ ÐÒÅÄÏÐÌÁÞÅÎÎÙÊ ÔÒÁÆÉË
+ bool showFeeInCash; // ðÏËÁÚÙ×ÁÔØ ÐÏÌØÚÏ×ÁÔÅÌÀ áð ÎÅ ÓÞÅÔÕ É ÐÏÚ×ÏÌÑÔØ ÅÅ ÉÓÐÏÌØÚÏ×ÁÔØ
+
+ vector<MODULE_SETTINGS> modulesSettings;
+ MODULE_SETTINGS storeModuleSettings;
+
+ STG_LOGGER & logger;
+};
+//-----------------------------------------------------------------------------
+#endif
+
--- /dev/null
+<!DOCTYPE Project SYSTEM "http://www.slickedit.com/dtd/vse/10.0/vpj.dtd">
+<Project
+ Version="10.0"
+ VendorName="SlickEdit"
+ WorkingDir="."
+ VCSProject="CVS:">
+ <Config
+ Name="Debug"
+ Type="gnuc"
+ DebugCallbackName="gdb"
+ OutputFile="%bdstargazer">
+ <Menu>
+ <Target
+ Name="Compile"
+ MenuCaption="&Compile"
+ OutputExts="*.o"
+ Dialog="_gnuc_options_form Compile"
+ RunFromDir="%rw"
+ CaptureOutputWith="ProcessBuffer"
+ SaveOption="SaveCurrent"
+ Deletable="0">
+ <Exec CmdLine='g++ -c %xup -DLINUX -g -o "%bd%n%oe" %i "%f"'/>
+ </Target>
+ <Target
+ Name="Link"
+ MenuCaption="&Link"
+ ShowOnMenu="Never"
+ Dialog="_gnuc_options_form Link"
+ RunFromDir="%rw"
+ CaptureOutputWith="ProcessBuffer"
+ SaveOption="SaveCurrent"
+ Deletable="0">
+ <Exec CmdLine='g++ %xup -g -o "%o" %f %libs'/>
+ </Target>
+ <Target
+ Name="Build"
+ MenuCaption="&Build"
+ RunFromDir="%rw"
+ CaptureOutputWith="ProcessBuffer"
+ SaveOption="SaveWorkspaceFiles"
+ Deletable="0">
+ <Exec CmdLine="make OS=linux"/>
+ </Target>
+ <Target
+ Name="Rebuild"
+ MenuCaption="&Rebuild"
+ RunFromDir="%rw"
+ CaptureOutputWith="ProcessBuffer"
+ Deletable="0">
+ <Exec/>
+ </Target>
+ <Target
+ Name="Debug"
+ MenuCaption="&Debug"
+ Dialog="_gnuc_options_form Run/Debug"
+ RunFromDir="%rw"
+ BuildFirst="1"
+ CaptureOutputWith="ProcessBuffer"
+ Deletable="0">
+ <Exec CmdLine='vsdebugio -prog "%o"'/>
+ </Target>
+ <Target
+ Name="Execute"
+ MenuCaption="E&xecute"
+ Dialog="_gnuc_options_form Run/Debug"
+ RunFromDir="%rw"
+ BuildFirst="1"
+ CaptureOutputWith="ProcessBuffer"
+ SaveOption="SaveWorkspaceFiles"
+ Deletable="0">
+ <Exec CmdLine='"%o"'/>
+ </Target>
+ <Target
+ Name="dash"
+ MenuCaption="-"
+ RunFromDir="%rw">
+ <Exec/>
+ </Target>
+ <Target
+ Name="GNU C Options"
+ MenuCaption="GNU C &Options..."
+ ShowOnMenu="HideIfNoCmdLine"
+ Deletable="0">
+ <Exec
+ CmdLine="gnucoptions"
+ Type="Slick-C"/>
+ </Target>
+ </Menu>
+ <Includes>
+ <Include Dir="../../include/"/>
+ </Includes>
+ </Config>
+ <Config
+ Name="Release"
+ Type="gnuc"
+ DebugCallbackName="gdb"
+ OutputFile="%bdstargazer">
+ <Menu>
+ <Target
+ Name="Compile"
+ MenuCaption="&Compile"
+ OutputExts="*.o"
+ Dialog="_gnuc_options_form Compile"
+ RunFromDir="%rw"
+ CaptureOutputWith="ProcessBuffer"
+ SaveOption="SaveCurrent"
+ Deletable="0">
+ <Exec CmdLine='g++ -c %xup -DLINUX -o "%bd%n%oe" %i "%f"'/>
+ </Target>
+ <Target
+ Name="Link"
+ MenuCaption="&Link"
+ ShowOnMenu="Never"
+ Dialog="_gnuc_options_form Link"
+ RunFromDir="%rw"
+ CaptureOutputWith="ProcessBuffer"
+ SaveOption="SaveCurrent"
+ Deletable="0">
+ <Exec CmdLine='g++ %xup -o "%o" %f %libs'/>
+ </Target>
+ <Target
+ Name="Build"
+ MenuCaption="&Build"
+ RunFromDir="%rw"
+ CaptureOutputWith="ProcessBuffer"
+ SaveOption="SaveWorkspaceFiles"
+ Deletable="0">
+ <Exec CmdLine="make OS=linux"/>
+ </Target>
+ <Target
+ Name="Rebuild"
+ MenuCaption="&Rebuild"
+ RunFromDir="%rw"
+ CaptureOutputWith="ProcessBuffer"
+ Deletable="0">
+ <Exec/>
+ </Target>
+ <Target
+ Name="Debug"
+ MenuCaption="&Debug"
+ Dialog="_gnuc_options_form Run/Debug"
+ RunFromDir="%rw"
+ BuildFirst="1"
+ CaptureOutputWith="ProcessBuffer"
+ Deletable="0">
+ <Exec CmdLine='vsdebugio -prog "%o"'/>
+ </Target>
+ <Target
+ Name="Execute"
+ MenuCaption="E&xecute"
+ Dialog="_gnuc_options_form Run/Debug"
+ RunFromDir="%rw"
+ BuildFirst="1"
+ CaptureOutputWith="ProcessBuffer"
+ SaveOption="SaveWorkspaceFiles"
+ Deletable="0">
+ <Exec CmdLine='"%o"'/>
+ </Target>
+ <Target
+ Name="dash"
+ MenuCaption="-"
+ RunFromDir="%rw">
+ <Exec/>
+ </Target>
+ <Target
+ Name="GNU C Options"
+ MenuCaption="GNU C &Options..."
+ ShowOnMenu="HideIfNoCmdLine"
+ Deletable="0">
+ <Exec
+ CmdLine="gnucoptions"
+ Type="Slick-C"/>
+ </Target>
+ </Menu>
+ <Includes>
+ <Include Dir="../../include/"/>
+ </Includes>
+ </Config>
+ <Files>
+ <Folder
+ Name="Source Files"
+ Filters="*.c;*.cc;*.cpp;*.cp;*.cxx;*.prg;*.pas;*.dpr;*.asm;*.s;*.bas;*.java;*.sc;*.e;*.cob;*.html;*.rc;*.tcl;*.py;*.pl">
+ <Folder
+ Name="Plugin Sources"
+ Filters="">
+ <Folder
+ Name="auth"
+ Filters="">
+ <F N="plugins/authorization/inetaccess/antiflood.cpp"/>
+ <F N="plugins/authorization/ao/ao.cpp"/>
+ <F N="plugins/authorization/inetaccess/inetaccess.cpp"/>
+ <F N="plugins/authorization/stress/stress.cpp"/>
+ </Folder>
+ <Folder
+ Name="store"
+ Filters="">
+ <F N="plugins/store/files/file_store.cpp"/>
+ <F N="plugins/store/firebird/firebird_store.cpp"/>
+ <F N="plugins/store/firebird/firebird_store_admins.cpp"/>
+ <F N="plugins/store/firebird/firebird_store_corporations.cpp"/>
+ <F N="plugins/store/firebird/firebird_store_messages.cpp"/>
+ <F N="plugins/store/firebird/firebird_store_services.cpp"/>
+ <F N="plugins/store/firebird/firebird_store_tariffs.cpp"/>
+ <F N="plugins/store/firebird/firebird_store_users.cpp"/>
+ <F N="plugins/store/firebird/firebird_store_utils.cpp"/>
+ </Folder>
+ <Folder
+ Name="other"
+ Filters="">
+ <F N="plugins/other/ping/ping.cpp"/>
+ </Folder>
+ <Folder
+ Name="configuration"
+ Filters="">
+ <F N="plugins/configuration/sgconfig/configproto.cpp"/>
+ <F N="plugins/configuration/sgconfig/net_configurator.cpp"/>
+ <F N="plugins/configuration/sgconfig/parser_admin.cpp"/>
+ <F N="plugins/configuration/sgconfig/parser_tariff.cpp"/>
+ <F N="plugins/configuration/sgconfig/rsconf.cpp"/>
+ <F N="plugins/configuration/sgconfig/stgconfig.cpp"/>
+ <F N="plugins/configuration/sgconfig/parser.cpp"/>
+ </Folder>
+ <Folder
+ Name="capture"
+ Filters="">
+ <Folder
+ Name="debug_cap"
+ Filters="">
+ <F N="plugins/capture/cap_debug/debug_cap.cpp"/>
+ </Folder>
+ <Folder
+ Name="ipq_cap"
+ Filters="">
+ <F N="plugins/capture/ipq_linux/ipq_cap.cpp"/>
+ <F N="plugins/capture/ipq_linux/libipq.c"/>
+ </Folder>
+ <Folder
+ Name="divert_cap"
+ Filters="">
+ <F N="plugins/capture/divert_freebsd/divert_cap.cpp"/>
+ <F N="plugins/capture/divert_freebsd/divert_cap.h"/>
+ </Folder>
+ <F N="plugins/capture/ether_freebsd/ether_cap.cpp"/>
+ </Folder>
+ </Folder>
+ <F N="admin.cpp"/>
+ <F N="admins.cpp"/>
+ <F N="curr_ip.cpp"/>
+ <F N="main.cpp"/>
+ <F N="plugin_runner.cpp"/>
+ <F N="script_executer.cpp"/>
+ <F N="settings.cpp"/>
+ <F N="../../stglibs/stg_logger.lib/stg_logger.cpp"/>
+ <F N="stg_timer.cpp"/>
+ <F N="tariff.cpp"/>
+ <F N="tariffs.cpp"/>
+ <F N="traffcounter.cpp"/>
+ <F N="user.cpp"/>
+ <F N="user_property.cpp"/>
+ <F N="users.cpp"/>
+ </Folder>
+ <Folder
+ Name="Header Files"
+ Filters="*.h;*.hh;*.hpp;*.hxx;*.inc;*.sh;*.cpy;*.if">
+ <Folder
+ Name="Plugin Headers"
+ Filters="">
+ <F N="plugins/authorization/ao/ao.h"/>
+ <F N="plugins/configuration/sgconfig/configproto.h"/>
+ <F N="plugins/capture/cap_debug/debug_cap.h"/>
+ <F N="plugins/capture/ether_freebsd/ether_cap.h"/>
+ <F N="plugins/store/files/file_store.h"/>
+ <F N="plugins/authorization/inetaccess/inetaccess.h"/>
+ <F N="plugins/other/ping/ping.h"/>
+ <F N="plugins/authorization/inetaccess/recivecl.h"/>
+ <F N="plugins/configuration/sgconfig/parser.h"/>
+ <F N="plugins/authorization/inetaccess/packet.h"/>
+ </Folder>
+ <F N="admin.h"/>
+ <F N="../../include/admin_conf.h"/>
+ <F N="admins.h"/>
+ <F N="../../include/notifer.h"/>
+ <F N="../../stglibs/pinger.lib/pinger.h"/>
+ <F N="plugin_runner.h"/>
+ <F N="../../include/resetable.h"/>
+ <F N="script_executer.h"/>
+ <F N="settings.h"/>
+ <F N="../../include/stg_common.h"/>
+ <F N="../../include/stg_comp_stat.h"/>
+ <F N="../../include/stg_const.h"/>
+ <F N="stg_timer.h"/>
+ <F N="tariff.h"/>
+ <F N="../../include/tariff_conf.h"/>
+ <F N="tariffs.h"/>
+ <F N="traffcounter.h"/>
+ <F N="user.h"/>
+ <F N="../../include/user_conf.h"/>
+ <F N="../../include/user_ips.h"/>
+ <F N="user_property.h"/>
+ <F N="../../include/user_stat.h"/>
+ <F N="../../include/user_traff.h"/>
+ <F N="users.h"/>
+ </Folder>
+ <Folder
+ Name="Resource Files"
+ Filters="*.ico;*.cur;*.dlg"/>
+ <Folder
+ Name="Bitmaps"
+ Filters="*.bmp;*.xpm;*.xbm"/>
+ <Folder
+ Name="Other Files"
+ Filters="">
+ <F N="build"/>
+ <F
+ N="Makefile"
+ Type="Makefile"/>
+ </Folder>
+ </Files>
+</Project>
--- /dev/null
+<!DOCTYPE Workspace SYSTEM "http://www.slickedit.com/dtd/vse/10.0/vpw.dtd">
+<Workspace Version="10.0" VendorName="SlickEdit">
+ <Projects>
+ <Project File="../../stglibs/srvconf.lib/servconf.vpj" />
+ <Project File="stargazer.vpj" />
+ </Projects>
+</Workspace>
--- /dev/null
+[Global]
+CurrentProject=stargazer.vpj
+[ProjectDates]
+../../stglibs/srvconf.lib/servconf.vpj=20080818103030000
+stargazer.vpj=20080818104412000
+[ActiveConfig]
+stargazer.vpj=,Debug
+../../stglibs/srvconf.lib/servconf.vpj=,Debug
+[TreeExpansion]
+stargazer.vpj 1 1 1 0 0 1
+[State]
+SCREEN: 1680 1050 0 0 1680 980 0 0 N 0 0 0 0 1353 829
+CWD: plugins/configuration/sgconfig/
+BUFFER: BN="plugins/configuration/sgconfig/parser.cpp"
+BI: MA=1 74 1 TABS=1 5 WWS=1 IWT=0 ST=0 IN=2 BW=0 US=32000 RO=0 SE=1 SN=0 BIN=0 MN=C HM=0 MF=616 TL=0 MLL=0 ASE=0 LNL=6 LCF=0 CAPS=0 E=0 ESBU2=-1
+VIEW: LN=.0 CL=1 LE=0 CX=0 CY=0 WI=5 BI=32 HT=0 HN=0 HF=0 HC=4
+WINDOW: 200 200 913 559 0 0 M WF=0 WT=2 "misc-nil,14,0,1"
+BUFFER: BN="plugins/configuration/sgconfig/parser.cpp"
+VIEW: LN=.8617 CL=34 LE=0 CX=33 CY=19 WI=157 BI=32 HT=0 HN=0 HF=0 HC=4
+FILEHIST: 9
+tariff.h
+../../stglibs/stg_logger.lib/stg_logger.h
+../../stglibs/stg_logger.lib/stg_logger.cpp
+tariff.cpp
+traffcounter.cpp
+../../include/user_conf.h
+../../../../tmp/OLYMP.CPP
+../../../../tmp/olymp.cpp
+plugins/configuration/sgconfig/parser.cpp
+DEBUG: 0 0 0 0 3 0
+printf
+strcpy
+std::*
+[TreeExpansion2]
++ ../../stglibs/srvconf.lib/servconf.vpj
+- stargazer.vpj
+ - Source Files
+ - Plugin Sources
+ - auth
+ + store
+ + other
+ + configuration
+ + capture
+ + debug_cap
+ + ipq_cap
+ + divert_cap
+ - Header Files
+ + Plugin Headers
+ + Resource Files
+ + Bitmaps
+ + Other Files
+scroll:23
--- /dev/null
+#!/bin/bash
+
+LD_LIBRARY_PATH=../../lib ./stargazer /etc/stargazer
+#./stargazer /etc/stargazer.a
+
+if [ $? == 0 ]
+then
+ echo "Start successfull"
+else
+ echo "Start failed"
+fi
+
+#./stargazer /etc/stargazer
\ No newline at end of file
--- /dev/null
+#include <unistd.h>
+#include <pthread.h>
+
+#include <cstring>
+
+#include "common.h"
+
+static int nonstop;
+static pthread_t thrStgTimer;
+static bool isTimerRunning = false;
+volatile time_t stgTime;
+
+const int TIME_SPEED = 1;
+/*
+ 1 - 1x speed
+ 2 - 2x speed
+ 5 - 5x speed
+ 10 - 10x speed
+ */
+
+const int START_TIME = 0;
+/*
+ 0 - as is
+ 1 - start before new day (3 min before) 29.11.2005 23:57:00
+ 2 - start before new month (3 min before) 30.11.2005 23:57:00
+ */
+
+//-----------------------------------------------------------------------------
+void * StgTimer(void *)
+{
+#ifdef STG_TIMER_DEBUG
+struct tm lt;
+memset(<, 0, sizeof(lt));
+
+lt.tm_year = 2007 - 1900; // 2005
+lt.tm_mon = 10 - 1; // Nov
+lt.tm_hour = 23; // 23 h
+lt.tm_min = 57; // 50 min
+lt.tm_sec = 0; // 00 sec
+
+switch (START_TIME)
+ {
+ case 0:
+ stgTime = time(NULL);
+ break;
+
+ case 1:
+ lt.tm_mday = 29;
+ stgTime = mktime(<);
+ break;
+
+ case 2:
+ lt.tm_mday = 30;
+ stgTime = mktime(<);
+ break;
+ }
+#endif
+
+nonstop = 1;
+isTimerRunning = true;
+while (nonstop)
+ {
+ #ifdef STG_TIMER_DEBUG
+ usleep(1000000 / TIME_SPEED);
+ stgTime++;
+ #else
+ stgTime = time(NULL);
+ usleep(500000);
+ #endif
+ }
+isTimerRunning = false;
+
+return NULL;
+}
+//-----------------------------------------------------------------------------
+int RunStgTimer()
+{
+static int a = 0;
+isTimerRunning = false;
+
+if (a == 0)
+ if (pthread_create(&thrStgTimer, NULL, StgTimer, NULL))
+ {
+ isTimerRunning = false;
+ return -1;
+ }
+
+a = 1;
+return 0;
+}
+//-----------------------------------------------------------------------------
+void StopStgTimer()
+{
+nonstop = 0;
+pthread_join(thrStgTimer, NULL); // Cleanup thread resources
+printfd(__FILE__, "STG_TIMER stopped\n");
+}
+//-----------------------------------------------------------------------------
+bool IsStgTimerRunning()
+{
+return isTimerRunning;
+}
+//-----------------------------------------------------------------------------
+int stgUsleep(unsigned long t)
+{
+#ifdef STG_TIMER_DEBUG
+return usleep(t / TIME_SPEED);
+#else
+return usleep(t);
+#endif
+}
+//-----------------------------------------------------------------------------
+void WaitTimer()
+{
+ for (int i = 0; i < 5 && !isTimerRunning; i++)
+ stgUsleep(200000);
+}
+//-----------------------------------------------------------------------------
+
+
--- /dev/null
+ /*
+ $Revision: 1.9 $
+ $Date: 2010/11/03 10:37:52 $
+ $Author: faust $
+ */
+
+#ifndef STG_TIMER_H
+#define STG_TIMER_H
+
+#include <ctime>
+
+extern volatile const time_t stgTime;
+int RunStgTimer();
+void StopStgTimer();
+void WaitTimer();
+bool IsStgTimerRunning();
+int stgUsleep(unsigned long t);
+
+#endif //STG_TIMER_H
+
+
--- /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>
+ */
+
+/*
+ $Revision: 1.6 $
+ $Date: 2010/03/04 12:24:19 $
+ $Author: faust $
+ */
+
+/*
+ * An implementation of RAII store plugin loader
+ */
+
+#include <dlfcn.h>
+
+#include "store_loader.h"
+#include "common.h"
+
+STORE_LOADER::STORE_LOADER(const SETTINGS & settings)
+ : isLoaded(false),
+ handle(NULL),
+ plugin(NULL),
+ errorStr(),
+ storeSettings(settings.GetStoreModuleSettings()),
+ pluginFileName(settings.GetModulesPath() + "/mod_" + storeSettings.moduleName + ".so")
+{
+}
+
+STORE_LOADER::~STORE_LOADER()
+{
+Unload();
+}
+
+bool STORE_LOADER::Load()
+{
+printfd(__FILE__, "STORE_LOADER::Load()\n");
+if (isLoaded)
+ {
+ return false;
+ }
+
+if (pluginFileName.empty())
+ {
+ errorStr = "Empty store plugin filename";
+ printfd(__FILE__, "STORE_LOADER::Load - %s\n", errorStr.c_str());
+ return true;
+ }
+
+handle = dlopen(pluginFileName.c_str(), RTLD_NOW);
+
+if (!handle)
+ {
+ errorStr = "Error loading plugin '"
+ + pluginFileName + "': '" + dlerror() + "'";
+ printfd(__FILE__, "STORE_LOADER::Load - %s\n", errorStr.c_str());
+ return true;
+ }
+
+isLoaded = true;
+
+BASE_STORE * (*GetStore)();
+GetStore = (BASE_STORE * (*)())dlsym(handle, "GetStore");
+if (!GetStore)
+ {
+ errorStr = "GetStore not found.";
+ printfd(__FILE__, "STORE_LOADER::Load - %s\n", errorStr.c_str());
+ return true;
+ }
+
+plugin = GetStore();
+
+if (!plugin)
+ {
+ errorStr = "NULL store plugin";
+ printfd(__FILE__, "STORE_LOADER::Load - %s\n");
+ return true;
+ }
+
+plugin->SetSettings(storeSettings);
+if (plugin->ParseSettings())
+ {
+ errorStr = plugin->GetStrError();
+ printfd(__FILE__, "Failed to parse settings. Plugin reports: '%s'\n", errorStr.c_str());
+ return true;
+ }
+
+return false;
+}
+
+bool STORE_LOADER::Unload()
+{
+printfd(__FILE__, "STORE_LOADER::Unload()\n");
+if (!isLoaded)
+ {
+ return false;
+ }
+
+if (dlclose(handle))
+ {
+ errorStr = "Failed to unload plugin: '";
+ errorStr += dlerror();
+ errorStr += "'";
+ printfd(__FILE__, "STORE_LOADER::Unload - %s\n", errorStr.c_str());
+ return true;
+ }
+
+isLoaded = false;
+
+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 : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+/*
+ $Revision: 1.3 $
+ $Date: 2010/03/04 12:24:19 $
+ $Author: faust $
+ */
+
+/*
+ * Header file for RAII store plugin loader
+ */
+
+#ifndef __STORE_LOADER_H__
+#define __STORE_LOADER_H__
+
+#include <string>
+
+#include "base_store.h"
+#include "base_settings.h"
+#include "settings.h"
+#include "noncopyable.h"
+
+class STORE_LOADER : private NONCOPYABLE
+{
+public:
+ STORE_LOADER(const SETTINGS & settings);
+ ~STORE_LOADER();
+
+ bool Load();
+ bool Unload();
+
+ BASE_STORE * GetStore() { return plugin; };
+
+ const std::string & GetStrError() const { return errorStr; };
+private:
+ bool isLoaded;
+ void * handle;
+ BASE_STORE * plugin;
+ std::string errorStr;
+ MODULE_SETTINGS storeSettings;
+ std::string pluginFileName;
+};
+
+#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
+ */
+
+/*
+ * Date: 07.11.2007
+ */
+
+/*
+ * Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+/*
+ $Revision: 1.11 $
+ $Date: 2010/10/07 16:57:21 $
+ $Author: faust $
+ */
+
+#include <ctime>
+#include <algorithm> // std::max
+
+#include "tariff.h"
+#include "stg_timer.h"
+
+//-----------------------------------------------------------------------------
+TARIFF & TARIFF::operator=(const TARIFF_DATA & td)
+{
+tariffData = td;
+return *this;
+}
+//-----------------------------------------------------------------------------
+TARIFF & TARIFF::operator=(const TARIFF & t)
+{
+tariffData = t.tariffData;
+return *this;
+}
+//-----------------------------------------------------------------------------
+double TARIFF::GetPriceWithTraffType(uint64_t up,
+ uint64_t down,
+ int dir,
+ time_t t) const
+{
+return GetPriceWithoutFreeMb(dir, GetTraffByType(up, down) / (1024 * 1024), t);
+}
+//-----------------------------------------------------------------------------
+int64_t TARIFF::GetTraffByType(uint64_t up, uint64_t down) const
+{
+switch (tariffData.tariffConf.traffType)
+ {
+ case TRAFF_UP:
+ return up;
+
+ case TRAFF_DOWN:
+ return down;
+
+ case TRAFF_MAX:
+ return std::max(up, down);
+
+ default: //TRAFF_UP_DOWN:
+ return up + down;
+ }
+}
+//-----------------------------------------------------------------------------
+int TARIFF::GetThreshold(int dir) const
+{
+ return tariffData.dirPrice[dir].threshold;
+}
+//-----------------------------------------------------------------------------
+void TARIFF::PrintTariff() const
+{
+//printfd(__FILE__, "Traiff name: %s\n", tariffConf.name.c_str());
+//printfd(__FILE__, "Price: %8.3f %8.3f \n", dirPrice[0].GetPrice(0, 0), dirPrice[0].GetPrice(1, 0));
+//printfd(__FILE__, "Price: %8.3f %8.3f Thr:%d\n", dirPrice[1].GetPrice(0), dirPrice[1].GetPrice(1), dirPrice[1].GetThreshold());
+//printfd(__FILE__, "Price: %8.3f %8.3f Thr:%d\n", dirPrice[2].GetPrice(0), dirPrice[2].GetPrice(1), dirPrice[2].GetThreshold());
+//printfd(__FILE__, "Price: %8.3f %8.3f Thr:%d\n", dirPrice[3].GetPrice(0), dirPrice[3].GetPrice(1), dirPrice[3].GetThreshold());
+//printfd(__FILE__, "Free: %8.3f\n", tariffConf.free);
+}
+//-----------------------------------------------------------------------------
+void TARIFF::GetDirPrice(int dir, DIRPRICE_DATA * dd) const
+{
+*dd = tariffData.dirPrice[dir];
+}
+//-----------------------------------------------------------------------------
+void TARIFF::GetTariffData(TARIFF_DATA * td) const
+{
+*td = tariffData;
+}
+//-----------------------------------------------------------------------------
+int TARIFF::Interval(int dir, time_t t) const
+{
+// Start of the day (and end of the night) in sec from 00:00:00
+int s1 = tariffData.dirPrice[dir].hDay * 3600 +
+ tariffData.dirPrice[dir].mDay * 60;
+// Start of the night (and end of the day) in sec from 00:00:00
+int s2 = tariffData.dirPrice[dir].hNight * 3600 +
+ tariffData.dirPrice[dir].mNight * 60;
+
+struct tm * lt;
+
+lt = localtime(&t);
+
+// Position of time t in sec from 00:00:00
+// Ignoring seconds due to minute precision
+int lts = lt->tm_hour * 3600 + lt->tm_min * 60;
+
+if (s1 < s2)
+ {
+ // Normal situation (00:00:00 is a night)
+ if (lts > s1 && lts < s2)
+ return TARIFF_DAY;
+ else
+ return TARIFF_NIGHT;
+ }
+else
+ {
+ // Not so common but possible situation (00:00:00 is a day)
+ if (lts < s1 && lts > s2)
+ return TARIFF_NIGHT;
+ else
+ return TARIFF_DAY;
+ }
+}
+//-----------------------------------------------------------------------------
+double TARIFF::GetPriceWithoutFreeMb(int dir, int mb, time_t t) const
+{
+int interval = Interval(dir, t);
+
+/*
+ * 0011 - NB
+ * *01* - NA
+ * 0**1 - DB
+ * **** - DA
+ */
+
+bool nd = tariffData.dirPrice[dir].noDiscount;
+bool sp = tariffData.dirPrice[dir].singlePrice;
+bool th = (interval == TARIFF_NIGHT);
+bool tr = (mb > tariffData.dirPrice[dir].threshold);
+
+if (!nd && !sp && th && tr)
+ return tariffData.dirPrice[dir].priceNightB;
+else if (!nd && tr)
+ return tariffData.dirPrice[dir].priceDayB;
+else if (!sp && th)
+ return tariffData.dirPrice[dir].priceNightA;
+else
+ return tariffData.dirPrice[dir].priceDayA;
+
+/*if (tariffData.dirPrice[dir].noDiscount && tariffData.dirPrice[dir].singlePrice)
+ {
+ return tariffData.dirPrice[dir].priceDayA;
+ }
+else
+ {
+ if (tariffData.dirPrice[dir].noDiscount)
+ {
+ // Without threshold
+ if (interval == TARIFF_DAY)
+ return tariffData.dirPrice[dir].priceDayA;
+ else
+ return tariffData.dirPrice[dir].priceNightA;
+ }
+
+ if (tariffData.dirPrice[dir].singlePrice)
+ {
+ // Without day/night
+ if (mb < tariffData.dirPrice[dir].threshold)
+ return tariffData.dirPrice[dir].priceDayA;
+ else
+ return tariffData.dirPrice[dir].priceDayB;
+ }
+
+ if (mb < tariffData.dirPrice[dir].threshold)
+ {
+ if (interval == TARIFF_DAY)
+ return tariffData.dirPrice[dir].priceDayA;
+ else
+ return tariffData.dirPrice[dir].priceNightA;
+ }
+ else
+ {
+ if (interval == TARIFF_DAY)
+ return tariffData.dirPrice[dir].priceDayB;
+ else
+ return tariffData.dirPrice[dir].priceNightB;
+ }
+ }*/
+}
+//-----------------------------------------------------------------------------
--- /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: 07.11.2007
+ */
+
+/*
+ * Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+/*
+ $Revision: 1.9 $
+ $Date: 2010/10/07 17:53:39 $
+ $Author: faust $
+ */
+
+#ifndef TARIFF_H
+#define TARIFF_H
+
+#include <string>
+#include <list>
+
+#include "os_int.h"
+#include "tariff_conf.h"
+
+#define TARIFF_DAY 0
+#define TARIFF_NIGHT 1
+
+class TARIFF
+{
+public:
+ TARIFF()
+ : tariffData()
+ {};
+ TARIFF(const std::string & name)
+ : tariffData(name)
+ {};
+ TARIFF(const TARIFF_DATA & td)
+ : tariffData(td)
+ {};
+ TARIFF(const TARIFF & t)
+ : tariffData(t.tariffData)
+ {};
+ ~TARIFF() {};
+
+ double GetPriceWithTraffType(uint64_t up,
+ uint64_t down,
+ int dir,
+ time_t t) const;
+ double GetFreeMb() const { return tariffData.tariffConf.free; };
+ void GetDirPrice(int dir, DIRPRICE_DATA * dd) const;
+ double GetPassiveCost() const { return tariffData.tariffConf.passiveCost; };
+ double GetFee() const { return tariffData.tariffConf.fee; };
+ double GetFree() const { return tariffData.tariffConf.free; };
+
+ void PrintTariff() const;
+
+ const std::string & GetName() const { return tariffData.tariffConf.name; };
+ void SetName(const std::string & name) { tariffData.tariffConf.name = name; };
+
+ int GetTraffType() const { return tariffData.tariffConf.traffType; };
+ int64_t GetTraffByType(uint64_t up, uint64_t down) const;
+ int GetThreshold(int dir) const;
+ void GetTariffData(TARIFF_DATA * td) const;
+
+ TARIFF & operator=(const TARIFF_DATA & td);
+ TARIFF & operator=(const TARIFF & t);
+ bool operator==(const TARIFF & rhs) const { return GetName() == rhs.GetName(); };
+ bool operator!=(const TARIFF & rhs) const { return GetName() != rhs.GetName(); };
+
+private:
+ TARIFF_DATA tariffData;
+
+ double GetPriceWithoutFreeMb(int dir, int mb, time_t t) const;
+ int Interval(int dir, time_t t) const;
+};
+//-----------------------------------------------------------------------------
+
+#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
+ */
+
+/*
+ * Date: 07.11.2007
+ */
+
+/*
+ * Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+/*
+ $Revision: 1.9 $
+ $Date: 2010/10/07 18:43:21 $
+ $Author: faust $
+ */
+
+#include <cassert>
+#include <algorithm>
+#include <vector>
+
+#include "tariffs.h"
+#include "stg_locker.h"
+#include "stg_logger.h"
+#include "base_store.h"
+#include "admin.h"
+
+using namespace std;
+
+//-----------------------------------------------------------------------------
+TARIFFS::TARIFFS(BASE_STORE * st)
+ : tariffs(),
+ store(st),
+ WriteServLog(GetStgLogger()),
+ strError(),
+ noTariff(NO_TARIFF_NAME)
+{
+pthread_mutex_init(&mutex, NULL);
+ReadTariffs();
+}
+//-----------------------------------------------------------------------------
+TARIFFS::~TARIFFS()
+{
+pthread_mutex_destroy(&mutex);
+}
+//-----------------------------------------------------------------------------
+int TARIFFS::ReadTariffs()
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+vector<string> tariffsList;
+if (store->GetTariffsList(&tariffsList))
+ {
+ WriteServLog("Cannot get tariffs list.");
+ WriteServLog("%s", store->GetStrError().c_str());
+ }
+
+int tariffsNum = tariffsList.size();
+
+for (int i = 0; i < tariffsNum; i++)
+ {
+ TARIFF_DATA td;
+ if (store->RestoreTariff(&td, tariffsList[i]))
+ {
+ WriteServLog("Cannot read tariff %s.", tariffsList[i].c_str());
+ WriteServLog("%s", store->GetStrError().c_str());
+ return -1;
+ }
+ tariffs.push_back(TARIFF(td));
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int TARIFFS::GetTariffsNum() const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+return tariffs.size();
+}
+//-----------------------------------------------------------------------------
+const TARIFF * TARIFFS::FindByName(const string & name) const
+{
+if (name == NO_TARIFF_NAME)
+ return &noTariff;
+
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+list<TARIFF>::const_iterator ti;
+ti = find(tariffs.begin(), tariffs.end(), TARIFF(name));
+
+if (ti != tariffs.end())
+ return &(*ti);
+
+return NULL;
+}
+//-----------------------------------------------------------------------------
+int TARIFFS::Chg(const TARIFF_DATA & td, const ADMIN & admin)
+{
+const PRIV * priv = admin.GetPriv();
+
+if (!priv->tariffChg)
+ {
+ string s = admin.GetLogStr() + " Change tariff \'"
+ + td.tariffConf.name + "\'. Access denied.";
+ strError = "Access denied.";
+ WriteServLog(s.c_str());
+ return -1;
+ }
+
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+list<TARIFF>::iterator ti;
+ti = find(tariffs.begin(), tariffs.end(), TARIFF(td.tariffConf.name));
+
+if (ti == tariffs.end())
+ {
+ strError = "Tariff \'" + td.tariffConf.name + "\' cannot be changed. Tariff does not exist.";
+ WriteServLog("%s %s", admin.GetLogStr().c_str(), strError.c_str());
+ return -1;
+ }
+
+*ti = td;
+
+if (store->SaveTariff(td, td.tariffConf.name))
+ {
+ string error = "Tariff " + td.tariffConf.name + " writing error. " + store->GetStrError();
+ WriteServLog(error.c_str());
+ return -1;
+ }
+
+WriteServLog("%s Tariff \'%s\' changed.",
+ admin.GetLogStr().c_str(), td.tariffConf.name.c_str());
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int TARIFFS::Del(const string & name, const ADMIN & admin)
+{
+const PRIV * priv = admin.GetPriv();
+
+if (!priv->tariffChg)
+ {
+ string s = admin.GetLogStr() + " Delete tariff \'"
+ + name + "\'. Access denied.";
+ strError = "Access denied.";
+ WriteServLog(s.c_str());
+ return -1;
+ }
+
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+list<TARIFF>::iterator ti;
+ti = find(tariffs.begin(), tariffs.end(), TARIFF(name));
+
+if (ti == tariffs.end())
+ {
+ strError = "Tariff \'" + name + "\' cannot be deleted. Tariff does not exist.";
+ WriteServLog("%s %s", admin.GetLogStr().c_str(), strError.c_str());
+ return -1;
+ }
+
+if (store->DelTariff(name))
+ {
+ WriteServLog("Cannot delete tariff %s.", name.c_str());
+ WriteServLog("%s", store->GetStrError().c_str());
+ return -1;
+ }
+
+tariffs.erase(ti);
+
+WriteServLog("%s Tariff \'%s\' deleted.",
+ admin.GetLogStr().c_str(),
+ name.c_str());
+return 0;
+}
+//-----------------------------------------------------------------------------
+int TARIFFS::Add(const string & name, const ADMIN & admin)
+{
+const PRIV * priv = admin.GetPriv();
+
+if (!priv->tariffChg)
+ {
+ string s = admin.GetLogStr() + " Add tariff \'"
+ + name + "\'. Access denied.";
+ strError = "Access denied.";
+ WriteServLog(s.c_str());
+ return -1;
+ }
+
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+list<TARIFF>::iterator ti;
+ti = find(tariffs.begin(), tariffs.end(), TARIFF(name));
+
+if (ti != tariffs.end())
+ {
+ strError = "Tariff \'" + name + "\' cannot be added. Tariff alredy exist.";
+ WriteServLog("%s %s", admin.GetLogStr().c_str(), strError.c_str());
+ return -1;
+ }
+
+tariffs.push_back(TARIFF(name));
+
+if (store->AddTariff(name) < 0)
+ {
+ strError = "Tariff " + name + " adding error. " + store->GetStrError();
+ WriteServLog(strError.c_str());
+ return -1;
+ }
+
+WriteServLog("%s Tariff \'%s\' added.",
+ admin.GetLogStr().c_str(), name.c_str());
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+void TARIFFS::GetTariffsData(std::list<TARIFF_DATA> * tdl)
+{
+assert(tdl != NULL && "Tariffs data list is not null");
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+std::list<TARIFF>::const_iterator it = tariffs.begin();
+TARIFF_DATA td;
+for (; it != tariffs.end(); ++it)
+ {
+ it->GetTariffData(&td);
+ tdl->push_back(td);
+ }
+}
+//-----------------------------------------------------------------------------
--- /dev/null
+ /*
+ $Revision: 1.7 $
+ $Date: 2010/10/07 18:43:21 $
+ */
+
+/*
+ * 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: 07.11.2007
+ */
+
+/*
+ * Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+/*
+ $Revision: 1.7 $
+ $Date: 2010/10/07 18:43:21 $
+ $Author: faust $
+ */
+
+#ifndef TARIFFS_H
+#define TARIFFS_H
+
+#include <string>
+#include <list>
+
+#include "tariff.h"
+#include "tariff_conf.h"
+
+#define TARIFF_DAY 0
+#define TARIFF_NIGHT 1
+
+class BASE_STORE;
+class STG_LOGGER;
+class ADMIN;
+
+//-----------------------------------------------------------------------------
+class TARIFFS
+{
+public:
+ TARIFFS(BASE_STORE * store);
+ ~TARIFFS();
+ int ReadTariffs ();
+ const TARIFF * FindByName(const std::string & name) const;
+ const TARIFF * GetNoTariff() const { return &noTariff; };
+ int GetTariffsNum() const;
+ int Del(const std::string & name, const ADMIN & admin);
+ int Add(const std::string & name, const ADMIN & admin);
+ int Chg(const TARIFF_DATA & td, const ADMIN & admin);
+
+ void GetTariffsData(std::list<TARIFF_DATA> * tdl);
+
+ const std::string & GetStrError() const { return strError; };
+private:
+ std::list<TARIFF> tariffs;
+ BASE_STORE * store;
+ STG_LOGGER & WriteServLog;
+ mutable pthread_mutex_t mutex;
+ std::string strError;
+ TARIFF noTariff;
+};
+//-----------------------------------------------------------------------------
+
+#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
+ */
+
+/*
+ * Date: 27.10.2002
+ */
+
+/*
+ * Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+/*
+ $Revision: 1.58 $
+ $Date: 2010/11/03 11:28:07 $
+ $Author: faust $
+ */
+
+#include <csignal>
+#include <cassert>
+
+#include "traffcounter.h"
+#include "common.h"
+#include "stg_locker.h"
+
+#define FLUSH_TIME (10)
+#define REMOVE_TIME (31)
+
+const char protoName[PROTOMAX][8] =
+{"TCP", "UDP", "ICMP", "TCP_UDP", "ALL"};
+
+enum protoNum
+ {
+ tcp = 0, udp, icmp, tcp_udp, all
+ };
+
+//-----------------------------------------------------------------------------
+TRAFFCOUNTER::TRAFFCOUNTER(USERS * u, const TARIFFS *, const string & fn)
+ : WriteServLog(GetStgLogger()),
+ rulesFileName(fn),
+ monitoring(false),
+ users(u),
+ running(false),
+ stopped(true),
+ addUserNotifier(*this),
+ delUserNotifier(*this)
+{
+for (int i = 0; i < DIR_NUM; i++)
+ strprintf(&dirName[i], "DIR%d", i);
+
+dirName[DIR_NUM] = "NULL";
+
+users->AddNotifierUserAdd(&addUserNotifier);
+users->AddNotifierUserDel(&delUserNotifier);
+
+pthread_mutex_init(&mutex, NULL);
+}
+//-----------------------------------------------------------------------------
+TRAFFCOUNTER::~TRAFFCOUNTER()
+{
+pthread_mutex_destroy(&mutex);
+}
+//-----------------------------------------------------------------------------
+int TRAFFCOUNTER::Start()
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (!stopped)
+ return 0;
+
+if (ReadRules())
+ {
+ WriteServLog("TRAFFCOUNTER: Cannot read rules.");
+ return -1;
+ }
+
+printfd(__FILE__, "TRAFFCOUNTER::Start()\n");
+int h = users->OpenSearch();
+user_iter u;
+if (!h)
+ {
+ WriteServLog("TRAFFCOUNTER: Cannot get users.");
+ return -1;
+ }
+
+while (users->SearchNext(h, &u) == 0)
+ {
+ SetUserNotifiers(u);
+ }
+users->CloseSearch(h);
+
+running = true;
+if (pthread_create(&thread, NULL, Run, this))
+ {
+ WriteServLog("TRAFFCOUNTER: Error: Cannot start thread!");
+ return -1;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int TRAFFCOUNTER::Stop()
+{
+if (stopped)
+ return 0;
+
+running = false;
+
+int h = users->OpenSearch();
+if (!h)
+ {
+ WriteServLog("TRAFFCOUNTER: Fatal error: Cannot get users.");
+ return -1;
+ }
+
+user_iter u;
+while (users->SearchNext(h, &u) == 0)
+ {
+ UnSetUserNotifiers(u);
+ }
+users->CloseSearch(h);
+
+//5 seconds to thread stops itself
+for (int i = 0; i < 25 && !stopped; i++)
+ {
+ usleep(200000);
+ }
+
+//after 5 seconds waiting thread still running. now kill it
+if (!stopped)
+ {
+ printfd(__FILE__, "kill TRAFFCOUNTER thread.\n");
+ if (pthread_kill(thread, SIGINT))
+ {
+ return -1;
+ }
+ printfd(__FILE__, "TRAFFCOUNTER killed\n");
+ }
+printfd(__FILE__, "TRAFFCOUNTER::Stop()\n");
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+void * TRAFFCOUNTER::Run(void * data)
+{
+TRAFFCOUNTER * tc = static_cast<TRAFFCOUNTER *>(data);
+tc->stopped = false;
+int c = 0;
+
+time_t touchTime = stgTime - MONITOR_TIME_DELAY_SEC;
+
+while (tc->running)
+ {
+ usleep(500000);
+ if (!tc->running)
+ {
+ tc->FlushAndRemove();
+ break;
+ }
+
+ if (tc->monitoring && (touchTime + MONITOR_TIME_DELAY_SEC <= stgTime))
+ {
+ string monFile(tc->monitorDir + "/traffcounter_r");
+ printfd(__FILE__, "Monitor=%d file TRAFFCOUNTER %s\n", tc->monitoring, monFile.c_str());
+ touchTime = stgTime;
+ TouchFile(monFile.c_str());
+ }
+
+ if (++c % FLUSH_TIME == 0)
+ tc->FlushAndRemove();
+ }
+
+tc->stopped = true;
+return NULL;
+}
+//-----------------------------------------------------------------------------
+void TRAFFCOUNTER::Process(const RAW_PACKET & rawPacket)
+{
+if (!running)
+ return;
+
+static time_t touchTime = stgTime - MONITOR_TIME_DELAY_SEC;
+
+if (monitoring && (touchTime + MONITOR_TIME_DELAY_SEC <= stgTime))
+ {
+ static string monFile = monitorDir + "/traffcounter_p";
+ printfd(__FILE__, "Monitor=%d file TRAFFCOUNTER %s\n", monitoring, monFile.c_str());
+ touchTime = stgTime;
+ TouchFile(monFile.c_str());
+ }
+
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+//printfd(__FILE__, "TRAFFCOUNTER::Process()\n");
+//TODO replace find with lower_bound.
+
+// Searching a new packet in a tree.
+pp_iter pi = packets.find(rawPacket);
+
+// Packet found - update length and time
+if (pi != packets.end())
+ {
+ pi->second.lenU += rawPacket.GetLen();
+ pi->second.lenD += rawPacket.GetLen();
+ pi->second.updateTime = stgTime;
+ /*printfd(__FILE__, "=============================\n");
+ printfd(__FILE__, "Packet found!\n");
+ printfd(__FILE__, "Version=%d\n", rawPacket.GetIPVersion());
+ printfd(__FILE__, "HeaderLen=%d\n", rawPacket.GetHeaderLen());
+ printfd(__FILE__, "PacketLen=%d\n", rawPacket.GetLen());
+ printfd(__FILE__, "SIP=%s\n", inet_ntostring(rawPacket.GetSrcIP()).c_str());
+ printfd(__FILE__, "DIP=%s\n", inet_ntostring(rawPacket.GetDstIP()).c_str());
+ printfd(__FILE__, "src port=%d\n", rawPacket.GetSrcPort());
+ printfd(__FILE__, "pst port=%d\n", rawPacket.GetDstPort());
+ printfd(__FILE__, "len=%d\n", rawPacket.GetLen());
+ printfd(__FILE__, "proto=%d\n", rawPacket.GetProto());
+ printfd(__FILE__, "PacketDirU=%d\n", pi->second.dirU);
+ printfd(__FILE__, "PacketDirD=%d\n", pi->second.dirD);
+ printfd(__FILE__, "=============================\n");*/
+ return;
+ }
+
+PACKET_EXTRA_DATA ed;
+
+// Packet not found - add new packet
+
+ed.updateTime = stgTime;
+ed.flushTime = stgTime;
+
+/*
+ userU is that whose user_ip == packet_ip_src
+ userD is that whose user_ip == packet_ip_dst
+ */
+
+uint32_t ipU = rawPacket.GetSrcIP();
+uint32_t ipD = rawPacket.GetDstIP();
+
+// Searching users with such IP
+if (users->FindByIPIdx(ipU, &ed.userU) == 0)
+ {
+ ed.userUPresent = true;
+ }
+
+if (users->FindByIPIdx(ipD, &ed.userD) == 0)
+ {
+ ed.userDPresent = true;
+ }
+
+if (ed.userUPresent ||
+ ed.userDPresent)
+ {
+ DeterminateDir(rawPacket, &ed.dirU, &ed.dirD);
+
+ ed.lenD = ed.lenU = rawPacket.GetLen();
+
+ //TODO use result of lower_bound to inserting new record
+
+ // Adding packet to a tree.
+ pair<pp_iter, bool> insertResult = packets.insert(pair<RAW_PACKET,
+ PACKET_EXTRA_DATA>(rawPacket, ed));
+ pp_iter newPacket = insertResult.first;
+
+ // Adding packet reference to an IP index.
+ ip2packets.insert(pair<uint32_t, pp_iter>(ipU, newPacket));
+ ip2packets.insert(pair<uint32_t, pp_iter>(ipD, newPacket));
+ }
+}
+//-----------------------------------------------------------------------------
+void TRAFFCOUNTER::FlushAndRemove()
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+int oldPacketsSize = packets.size();
+int oldIp2packetsSize = ip2packets.size();
+
+pp_iter pi;
+pi = packets.begin();
+std::map<RAW_PACKET, PACKET_EXTRA_DATA> newPackets;
+std::multimap<uint32_t, pp_iter> newIP2Packets;
+while (pi != packets.end())
+ {
+ //Flushing
+ if (stgTime - pi->second.flushTime > FLUSH_TIME)
+ {
+ if (pi->second.userUPresent)
+ {
+ //printfd(__FILE__, "+++ Flushing U user %s (%s:%d) of length %d\n", pi->second.userU->GetLogin().c_str(), inet_ntostring(pi->first.GetSrcIP()).c_str(), pi->first.GetSrcPort(), pi->second.lenU);
+
+ // Add stat
+ if (pi->second.dirU < DIR_NUM)
+ {
+ #ifdef TRAFF_STAT_WITH_PORTS
+ pi->second.userU->AddTraffStatU(pi->second.dirU,
+ pi->first.GetDstIP(),
+ pi->first.GetDstPort(),
+ pi->second.lenU);
+ #else
+ pi->second.userU->AddTraffStatU(pi->second.dirU,
+ pi->first.GetDstIP(),
+ pi->second.lenU);
+ #endif
+ }
+
+ pi->second.lenU = 0;
+ pi->second.flushTime = stgTime;
+ }
+
+ if (pi->second.userDPresent)
+ {
+ //printfd(__FILE__, "+++ Flushing D user %s (%s:%d) of length %d\n", pi->second.userD->GetLogin().c_str(), inet_ntostring(pi->first.GetDstIP()).c_str(), pi->first.GetDstPort(), pi->second.lenD);
+
+ // Add stat
+ if (pi->second.dirD < DIR_NUM)
+ {
+ #ifdef TRAFF_STAT_WITH_PORTS
+ pi->second.userD->AddTraffStatD(pi->second.dirD,
+ pi->first.GetSrcIP(),
+ pi->first.GetSrcPort(),
+ pi->second.lenD);
+ #else
+ pi->second.userD->AddTraffStatD(pi->second.dirD,
+ pi->first.GetSrcIP(),
+ pi->second.lenD);
+ #endif
+ }
+
+ pi->second.lenD = 0;
+ pi->second.flushTime = stgTime;
+ }
+ }
+
+ /*//Removing
+ if (stgTime - pi->second.updateTime > REMOVE_TIME)
+ {
+ // Remove packet and references from ip2packets index
+ //printfd(__FILE__, "+++ Removing +++\n");
+ pair<ip2p_iter, ip2p_iter> be(
+ ip2packets.equal_range(pi->first.GetSrcIP()));
+ while (be.first != be.second)
+ {
+ // Have a reference to a packet?
+ if (be.first->second == pi)
+ {
+ ip2packets.erase(be.first++);
+ //printfd(__FILE__, "Remove U from ip2packets %s\n", inet_ntostring(pi->first.GetSrcIP()).c_str());
+ }
+ else
+ {
+ ++be.first;
+ }
+ }
+
+ //printfd(__FILE__, "-------------------\n");
+ be = ip2packets.equal_range(pi->first.GetDstIP());
+ while (be.first != be.second)
+ {
+ // Have a reference to a packet?
+ if (be.first->second == pi)
+ {
+ ip2packets.erase(be.first++);
+ //printfd(__FILE__, "Remove D from ip2packets %s\n", inet_ntostring(pi->first.GetDstIP()).c_str());
+ }
+ else
+ {
+ ++be.first;
+ }
+ }
+ //printfd(__FILE__, "Remove packet\n");
+ packets.erase(pi++);
+ }
+ else
+ {
+ ++pi;
+ }*/
+ if (stgTime - pi->second.updateTime < REMOVE_TIME)
+ {
+ pair<pp_iter, bool> res = newPackets.insert(*pi);
+ if (res.second)
+ {
+ newIP2Packets.insert(make_pair(pi->first.GetSrcIP(), res.first));
+ newIP2Packets.insert(make_pair(pi->first.GetDstIP(), res.first));
+ }
+ }
+ ++pi;
+ }
+swap(packets, newPackets);
+swap(ip2packets, newIP2Packets);
+printfd(__FILE__, "FlushAndRemove() packets: %d(rem %d) ip2packets: %d(rem %d)\n",
+ packets.size(),
+ oldPacketsSize - packets.size(),
+ ip2packets.size(),
+ oldIp2packetsSize - ip2packets.size());
+
+}
+//-----------------------------------------------------------------------------
+void TRAFFCOUNTER::AddUser(user_iter user)
+{
+printfd(__FILE__, "AddUser: %s\n", user->GetLogin().c_str());
+uint32_t uip = user->GetCurrIP();
+pair<ip2p_iter, ip2p_iter> pi;
+
+STG_LOCKER(&mutex, __FILE__, __LINE__);
+// Find all packets with IP belongs to this user
+pi = ip2packets.equal_range(uip);
+
+while (pi.first != pi.second)
+ {
+ if (pi.first->second->first.GetSrcIP() == uip)
+ {
+ assert((!pi.first->second->second.userUPresent ||
+ pi.first->second->second.userU == user) &&
+ "U user present but it's not current user");
+
+ pi.first->second->second.lenU = 0;
+ pi.first->second->second.userU = user;
+ pi.first->second->second.userUPresent = true;
+ }
+
+ if (pi.first->second->first.GetDstIP() == uip)
+ {
+ assert((!pi.first->second->second.userDPresent ||
+ pi.first->second->second.userD == user) &&
+ "D user present but it's not current user");
+
+ pi.first->second->second.lenD = 0;
+ pi.first->second->second.userD = user;
+ pi.first->second->second.userDPresent = true;
+ }
+
+ ++pi.first;
+ }
+}
+//-----------------------------------------------------------------------------
+void TRAFFCOUNTER::DelUser(uint32_t uip)
+{
+printfd(__FILE__, "DelUser: %s \n", inet_ntostring(uip).c_str());
+pair<ip2p_iter, ip2p_iter> pi;
+
+STG_LOCKER(&mutex, __FILE__, __LINE__);
+pi = ip2packets.equal_range(uip);
+
+while (pi.first != pi.second)
+ {
+ if (pi.first->second->first.GetSrcIP() == uip)
+ {
+ if (pi.first->second->second.dirU < DIR_NUM && pi.first->second->second.userUPresent)
+ {
+ #ifdef TRAFF_STAT_WITH_PORTS
+ pi.first->second->second.userU->AddTraffStatU(pi.first->second->second.dirU,
+ pi.first->second->first.GetDstIP(),
+ pi.first->second->first.GetDstPort(),
+ pi.first->second->second.lenU);
+ #else
+ pi.first->second->second.userU->AddTraffStatU(pi.first->second->second.dirU,
+ pi.first->second->first.GetDstIP(),
+ pi.first->second->second.lenU);
+ #endif
+ }
+ pi.first->second->second.userUPresent = false;
+ }
+
+ if (pi.first->second->first.GetDstIP() == uip)
+ {
+ if (pi.first->second->second.dirD < DIR_NUM && pi.first->second->second.userDPresent)
+ {
+ #ifdef TRAFF_STAT_WITH_PORTS
+ pi.first->second->second.userD->AddTraffStatD(pi.first->second->second.dirD,
+ pi.first->second->first.GetSrcIP(),
+ pi.first->second->first.GetSrcPort(),
+ pi.first->second->second.lenD);
+ #else
+ pi.first->second->second.userD->AddTraffStatD(pi.first->second->second.dirD,
+ pi.first->second->first.GetSrcIP(),
+ pi.first->second->second.lenD);
+ #endif
+ }
+
+ pi.first->second->second.userDPresent = false;
+ }
+
+ ++pi.first;
+ }
+
+ip2packets.erase(pi.first, pi.second);
+}
+//-----------------------------------------------------------------------------
+void TRAFFCOUNTER::SetUserNotifiers(user_iter user)
+{
+// Adding user. Adding notifiers to user.
+TRF_IP_BEFORE ipBNotifier(*this, user);
+ipBeforeNotifiers.push_front(ipBNotifier);
+user->AddCurrIPBeforeNotifier(&(*ipBeforeNotifiers.begin()));
+
+TRF_IP_AFTER ipANotifier(*this, user);
+ipAfterNotifiers.push_front(ipANotifier);
+user->AddCurrIPAfterNotifier(&(*ipAfterNotifiers.begin()));
+}
+//-----------------------------------------------------------------------------
+void TRAFFCOUNTER::UnSetUserNotifiers(user_iter user)
+{
+// Removing user. Removing notifiers from user.
+list<TRF_IP_BEFORE>::iterator bi;
+list<TRF_IP_AFTER>::iterator ai;
+
+bi = ipBeforeNotifiers.begin();
+while (bi != ipBeforeNotifiers.end())
+ {
+ if (user->GetLogin() == bi->GetUser()->GetLogin())
+ {
+ user->DelCurrIPBeforeNotifier(&(*bi));
+ ipBeforeNotifiers.erase(bi);
+ break;
+ }
+ ++bi;
+ }
+
+ai = ipAfterNotifiers.begin();
+while (ai != ipAfterNotifiers.end())
+ {
+ if (user->GetLogin() == ai->GetUser()->GetLogin())
+ {
+ user->DelCurrIPAfterNotifier(&(*ai));
+ ipAfterNotifiers.erase(ai);
+ break;
+ }
+ ++ai;
+ }
+}
+//-----------------------------------------------------------------------------
+void TRAFFCOUNTER::DeterminateDir(const RAW_PACKET & packet,
+ int * dirU, // Direction for incoming packet
+ int * dirD) const // Direction for outgoing packet
+{
+bool addrMatchU;
+bool portMatchU;
+bool addrMatchD;
+bool portMatchD;
+bool foundU = false; // Was rule for U found ?
+bool foundD = false; // Was rule for D found ?
+//printfd(__FILE__, "foundU=%d, foundD=%d\n", foundU, foundD);
+
+enum { ICMP_RPOTO = 1, TCP_PROTO = 6, UDP_PROTO = 17 };
+
+list<RULE>::const_iterator ln;
+ln = rules.begin();
+
+while (ln != rules.end())
+ {
+ if (!foundU)
+ {
+ addrMatchU = false;
+ portMatchU = false;
+
+ switch (ln->proto)
+ {
+ case all:
+ portMatchU = true;
+ break;
+
+ case icmp:
+ portMatchU = (packet.GetProto() == ICMP_RPOTO);
+ break;
+
+ case tcp_udp:
+ if (packet.GetProto() == TCP_PROTO || packet.GetProto() == UDP_PROTO)
+ portMatchU = (packet.GetDstPort() >= ln->port1) && (packet.GetDstPort() <= ln->port2);
+ break;
+
+ case tcp:
+ if (packet.GetProto() == TCP_PROTO)
+ portMatchU = (packet.GetDstPort() >= ln->port1) && (packet.GetDstPort() <= ln->port2);
+ break;
+
+ case udp:
+ if (packet.GetProto() == UDP_PROTO)
+ portMatchU = (packet.GetDstPort() >= ln->port1) && (packet.GetDstPort() <= ln->port2);
+ break;
+
+ default:
+ printfd(__FILE__, "Error! Incorrect rule!\n");
+ break;
+ }
+
+ addrMatchU = (packet.GetDstIP() & ln->mask) == ln->ip;
+
+ if (!foundU && addrMatchU && portMatchU)
+ {
+ foundU = true;
+ *dirU = ln->dir;
+ //printfd(__FILE__, "Up rule ok! %d\n", ln->dir);
+ //PrintRule(ln->rule);
+ }
+
+ } //if (!foundU)
+
+ if (!foundD)
+ {
+ addrMatchD = false;
+ portMatchD = false;
+
+ switch (ln->proto)
+ {
+ case all:
+ portMatchD = true;
+ break;
+
+ case icmp:
+ portMatchD = (packet.GetProto() == ICMP_RPOTO);
+ break;
+
+ case tcp_udp:
+ if (packet.GetProto() == TCP_PROTO || packet.GetProto() == UDP_PROTO)
+ portMatchD = (packet.GetSrcPort() >= ln->port1) && (packet.GetSrcPort() <= ln->port2);
+ break;
+
+ case tcp:
+ if (packet.GetProto() == TCP_PROTO)
+ portMatchD = (packet.GetSrcPort() >= ln->port1) && (packet.GetSrcPort() <= ln->port2);
+ break;
+
+ case udp:
+ if (packet.GetProto() == UDP_PROTO)
+ portMatchD = (packet.GetSrcPort() >= ln->port1) && (packet.GetSrcPort() <= ln->port2);
+ break;
+
+ default:
+ printfd(__FILE__, "Error! Incorrect rule!\n");
+ break;
+ }
+
+ addrMatchD = (packet.GetSrcIP() & ln->mask) == ln->ip;
+
+ if (!foundD && addrMatchD && portMatchD)
+ {
+ foundD = true;
+ *dirD = ln->dir;
+ //printfd(__FILE__, "Down rule ok! %d\n", ln->dir);
+ //PrintRule(ln->rule);
+ }
+ } //if (!foundD)
+
+ ++ln;
+ } //while (ln != rules.end())
+
+if (!foundU)
+ *dirU = DIR_NUM;
+
+if (!foundD)
+ *dirD = DIR_NUM;
+
+return;
+};
+//-----------------------------------------------------------------------------
+void TRAFFCOUNTER::SetRulesFile(const string & fn)
+{
+rulesFileName = fn;
+}
+//-----------------------------------------------------------------------------
+bool TRAFFCOUNTER::ReadRules(bool test)
+{
+//printfd(__FILE__, "TRAFFCOUNTER::ReadRules()\n");
+
+RULE rul;
+FILE * f;
+char str[1024];
+char tp[100]; // protocol
+char ta[100]; // address
+char td[100]; // target direction
+int r;
+int lineNumber = 0;
+f = fopen(rulesFileName.c_str(), "rt");
+
+if (!f)
+ {
+ WriteServLog("File %s cannot be oppened.", rulesFileName.c_str());
+ return true;
+ }
+
+while (fgets(str, 1023, f))
+ {
+ lineNumber++;
+ if (str[strspn(str," \t")] == '#' || str[strspn(str," \t")] == '\n')
+ {
+ continue;
+ }
+
+ r = sscanf(str,"%s %s %s", tp, ta, td);
+ if (r != 3)
+ {
+ WriteServLog("Error in file %s. There must be 3 parameters. Line %d.", rulesFileName.c_str(), lineNumber);
+ return true;
+ }
+
+ rul.proto = 0xff;
+ rul.dir = 0xff;
+
+ for (int i = 0; i < PROTOMAX; i++)
+ {
+ if (strcasecmp(tp, protoName[i]) == 0)
+ rul.proto = i;
+ }
+
+ for (int i = 0; i < DIR_NUM + 1; i++)
+ {
+ if (td == dirName[i])
+ rul.dir = i;
+ }
+
+ if (rul.dir == 0xff || rul.proto == 0xff)
+ {
+ WriteServLog("Error in file %s. Line %d.",
+ rulesFileName.c_str(), lineNumber);
+ return true;
+ }
+
+ if (ParseAddress(ta, &rul) != 0)
+ {
+ WriteServLog("Error in file %s. Error in adress. Line %d.",
+ rulesFileName.c_str(), lineNumber);
+ return true;
+ }
+ if (!test)
+ rules.push_back(rul);
+ //PrintRule(rul);
+ }
+
+fclose(f);
+
+// Adding lastest rule: ALL 0.0.0.0/0 NULL
+rul.dir = DIR_NUM; //NULL
+rul.ip = 0; //0.0.0.0
+rul.mask = 0;
+rul.port1 = 0;
+rul.port2 = 65535;
+rul.proto = all;
+
+if (!test)
+ rules.push_back(rul);
+
+//PrintRule(rul);
+
+return false;
+}
+//-----------------------------------------------------------------------------
+int TRAFFCOUNTER::Reload()
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (ReadRules(true))
+ {
+ WriteServLog("TRAFFCOUNTER: Cannot reload rules. Errors found.");
+ return -1;
+ }
+
+FreeRules();
+ReadRules();
+WriteServLog("TRAFFCOUNTER: Reload rules successfull.");
+return 0;
+}
+//-----------------------------------------------------------------------------
+bool TRAFFCOUNTER::ParseAddress(const char * ta, RULE * rule) const
+{
+char addr[50], mask[20], port1[20], port2[20], ports[40];
+
+int len = strlen(ta);
+char n = 0;
+int i, p;
+memset(addr, 0, sizeof(addr));
+for (i = 0; i < len; i++)
+ {
+ if (ta[i] == '/' || ta[i] == ':')
+ {
+ addr[i] = 0;
+ n = ta[i];
+ break;
+ }
+ addr[i] = ta[i];
+ n = 0;
+ }
+addr[i + 1] = 0;
+p = i + 1;
+
+if (n == '/')
+ {
+ // mask
+ for (; i < len; i++)
+ {
+ if (ta[i] == ':')
+ {
+ mask[i - p] = 0;
+ n = ':';
+ break;
+ }
+ mask[i - p] = ta[i];
+ }
+ mask[i - p] = 0;
+ }
+else
+ {
+ strcpy(mask, "32");
+ }
+
+p = i + 1;
+i++;
+
+if (n == ':')
+ {
+ // port
+ if (!(rule->proto == tcp || rule->proto == udp || rule->proto == tcp_udp))
+ {
+ WriteServLog("No ports specified for this protocol.");
+ return true;
+ }
+
+ for (; i < len; i++)
+ ports[i - p] = ta[i];
+
+ ports[i - p] = 0;
+ }
+else
+ {
+ strcpy(ports, "0-65535");
+ }
+
+char *sss;
+char pts[100];
+strcpy(pts, ports);
+
+if ((sss = strchr(ports, '-')) != NULL)
+ {
+ strncpy(port1, ports, int(sss-ports));
+ port1[int(sss - ports)] = 0;
+ strcpy(port2, sss + 1);
+ }
+else
+ {
+ strcpy(port1, ports);
+ strcpy(port2, ports);
+ }
+
+// Convert strings to mask, ports and IP
+int prt1, prt2, msk;
+unsigned ip;
+char *res;
+
+msk = strtol(mask, &res, 10);
+if (*res != 0)
+ return true;
+
+prt1 = strtol(port1, &res, 10);
+if (*res != 0)
+ return true;
+
+prt2 = strtol(port2, &res, 10);
+if (*res != 0)
+ return true;
+
+int r = inet_aton(addr, (struct in_addr*)&ip);
+if (r == 0)
+ return true;
+
+rule->ip = ip;
+rule->mask = CalcMask(msk);
+//msk = 1;
+//printfd(__FILE__, "msk=%d mask=%08X mask=%08X\n", msk, rule->mask, (0xFFffFFff << (32 - msk)));
+
+if ((ip & rule->mask) != ip)
+ {
+ WriteServLog("Address does'n match mask.");
+ return true;
+ }
+
+rule->port1 = prt1;
+rule->port2 = prt2;
+
+return false;
+}
+//-----------------------------------------------------------------------------
+uint32_t TRAFFCOUNTER::CalcMask(uint32_t msk) const
+{
+if (msk >= 32) return 0xFFffFFff;
+if (msk == 0) return 0;
+return htonl(0xFFffFFff << (32 - msk));
+}
+//---------------------------------------------------------------------------
+void TRAFFCOUNTER::FreeRules()
+{
+rules.clear();
+}
+//-----------------------------------------------------------------------------
+void TRAFFCOUNTER::PrintRule(RULE rule) const
+{
+printf("%15s ", inet_ntostring(rule.ip).c_str());
+printf("mask=%08X ", rule.mask);
+printf("port1=%5d ", rule.port1);
+printf("port2=%5d ", rule.port2);
+switch (rule.proto)
+ {
+ case 0:
+ printf("TCP ");
+ break;
+ case 1:
+ printf("UDP ");
+ break;
+ case 2:
+ printf("ICMP ");
+ break;
+ case 3:
+ printf("TCP_UDP ");
+ break;
+ case 4:
+ printf("ALL ");
+ break;
+ }
+printf("dir=%d \n", rule.dir);
+return;
+}
+//-----------------------------------------------------------------------------
+void TRAFFCOUNTER::SetMonitorDir(const string & monitorDir)
+{
+TRAFFCOUNTER::monitorDir = monitorDir;
+monitoring = (monitorDir != "");
+}
+//-----------------------------------------------------------------------------
--- /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>
+ */
+
+ /*
+ $Revision: 1.23 $
+ $Date: 2010/04/22 12:57:46 $
+ $Author: faust $
+ */
+
+
+#ifndef TRAFFCOUNTER_H
+#define TRAFFCOUNTER_H
+
+#include <pthread.h>
+#include <ctime>
+#include <list>
+#include <map>
+#include <string>
+
+#include "os_int.h"
+#include "stg_logger.h"
+#include "raw_ip_packet.h"
+#include "users.h"
+#include "actions.h"
+#include "noncopyable.h"
+#include "eventloop.h"
+
+#define PROTOMAX (5)
+
+//-----------------------------------------------------------------------------
+struct RULE
+{
+uint32_t ip; // IP
+uint32_t mask; // Network mask
+uint16_t port1; // Min port
+uint16_t port2; // Max port
+uint8_t proto; // Protocol
+uint32_t dir; // Direction
+};
+//-----------------------------------------------------------------------------
+struct PACKET_EXTRA_DATA
+{
+PACKET_EXTRA_DATA()
+ : flushTime(0),
+ updateTime(0),
+ userU(),
+ userUPresent(false),
+ userD(),
+ userDPresent(false),
+ dirU(DIR_NUM),
+ dirD(DIR_NUM),
+ lenU(0),
+ lenD(0)
+{};
+
+PACKET_EXTRA_DATA(const PACKET_EXTRA_DATA & pp)
+ : flushTime(pp.flushTime),
+ updateTime(pp.updateTime),
+ userU(pp.userU),
+ userUPresent(pp.userUPresent),
+ userD(pp.userD),
+ userDPresent(pp.userDPresent),
+ dirU(pp.dirU),
+ dirD(pp.dirD),
+ lenU(pp.lenU),
+ lenD(pp.lenD)
+{};
+
+time_t flushTime; // Last flush time
+time_t updateTime; // Last update time
+user_iter userU; // Uploader
+bool userUPresent; // Uploader is registered user
+user_iter userD; // Downloader
+bool userDPresent; // Downloader is registered user
+int dirU; // Upload direction
+int dirD; // Download direction
+uint32_t lenU; // Upload length
+uint32_t lenD; // Download length
+};
+//-----------------------------------------------------------------------------
+class TRAFFCOUNTER;
+//-----------------------------------------------------------------------------
+class TRF_IP_BEFORE: public PROPERTY_NOTIFIER_BASE<uint32_t>
+{
+public:
+ TRF_IP_BEFORE(TRAFFCOUNTER & t, user_iter u)
+ : PROPERTY_NOTIFIER_BASE<uint32_t>(),
+ traffCnt(t),
+ user(u)
+ {};
+ void Notify(const uint32_t & oldValue, const uint32_t & newValue);
+ void SetUser(user_iter u) { user = u; }
+ user_iter GetUser() { return user; }
+
+private:
+ TRAFFCOUNTER & traffCnt;
+ user_iter user;
+};
+//-----------------------------------------------------------------------------
+class TRF_IP_AFTER: public PROPERTY_NOTIFIER_BASE<uint32_t>
+{
+public:
+ TRF_IP_AFTER(TRAFFCOUNTER & t, user_iter u)
+ : PROPERTY_NOTIFIER_BASE<uint32_t>(),
+ traffCnt(t),
+ user(u)
+ {};
+ void Notify(const uint32_t & oldValue, const uint32_t & newValue);
+ void SetUser(user_iter u) { user = u; }
+ user_iter GetUser() { return user; }
+private:
+ TRAFFCOUNTER & traffCnt;
+ user_iter user;
+};
+//-----------------------------------------------------------------------------
+class ADD_USER_NONIFIER: public NOTIFIER_BASE<user_iter>
+{
+public:
+ ADD_USER_NONIFIER(TRAFFCOUNTER & t) :
+ NOTIFIER_BASE<user_iter>(),
+ traffCnt(t) {};
+ virtual ~ADD_USER_NONIFIER(){};
+ void Notify(const user_iter & user);
+private:
+ TRAFFCOUNTER & traffCnt;
+};
+//-----------------------------------------------------------------------------
+class DEL_USER_NONIFIER: public NOTIFIER_BASE<user_iter>
+{
+public:
+ DEL_USER_NONIFIER(TRAFFCOUNTER & t) :
+ NOTIFIER_BASE<user_iter>(),
+ traffCnt(t) {};
+ virtual ~DEL_USER_NONIFIER(){};
+ void Notify(const user_iter & user);
+private:
+ TRAFFCOUNTER & traffCnt;
+};
+//-----------------------------------------------------------------------------
+class TRAFFCOUNTER : private NONCOPYABLE
+{
+friend class ADD_USER_NONIFIER;
+friend class DEL_USER_NONIFIER;
+friend class TRF_IP_BEFORE;
+friend class TRF_IP_AFTER;
+public:
+ TRAFFCOUNTER(USERS * users, const TARIFFS * tariffs, const std::string & rulesFileName);
+ ~TRAFFCOUNTER();
+
+ void SetRulesFile(const std::string & rulesFileName);
+
+ int Reload();
+ int Start();
+ int Stop();
+
+ void Process(const RAW_PACKET & rawPacket);
+ void SetMonitorDir(const std::string & monitorDir);
+
+private:
+ bool ParseAddress(const char * ta, RULE * rule) const;
+ uint32_t CalcMask(uint32_t msk) const;
+ void FreeRules();
+ void PrintRule(RULE rule) const;
+ bool ReadRules(bool test = false);
+
+ static void * Run(void * data);
+
+ void DeterminateDir(const RAW_PACKET & packet,
+ int * dirU, // Direction for upload
+ int * dirD) const; // Direction for download
+
+ void FlushAndRemove();
+
+ void AddUser(user_iter user);
+ void DelUser(uint32_t uip);
+ void SetUserNotifiers(user_iter user);
+ void UnSetUserNotifiers(user_iter user);
+
+ std::list<RULE> rules;
+ typedef std::list<RULE>::iterator rule_iter;
+
+ std::map<RAW_PACKET, PACKET_EXTRA_DATA> packets; // Packets tree
+ typedef std::map<RAW_PACKET, PACKET_EXTRA_DATA>::iterator pp_iter;
+
+ std::multimap<uint32_t, pp_iter> ip2packets; // IP-to-Packet index
+
+ typedef std::multimap<uint32_t, pp_iter>::iterator ip2p_iter;
+ typedef std::multimap<uint32_t, pp_iter>::const_iterator ip2p_citer;
+
+ std::string dirName[DIR_NUM + 1];
+
+ STG_LOGGER & WriteServLog;
+ std::string rulesFileName;
+
+ std::string monitorDir;
+ bool monitoring;
+
+ USERS * users;
+
+ bool running;
+ bool stopped;
+ pthread_mutex_t mutex;
+ pthread_t thread;
+
+ std::list<TRF_IP_BEFORE> ipBeforeNotifiers;
+ std::list<TRF_IP_AFTER> ipAfterNotifiers;
+
+ ADD_USER_NONIFIER addUserNotifier;
+ DEL_USER_NONIFIER delUserNotifier;
+};
+//-----------------------------------------------------------------------------
+inline
+void TRF_IP_BEFORE::Notify(const uint32_t & oldValue, const uint32_t &)
+{
+// User changes his address. Remove old IP
+if (!oldValue)
+ return;
+
+EVENT_LOOP_SINGLETON::GetInstance().Enqueue(traffCnt, &TRAFFCOUNTER::DelUser, oldValue);
+}
+//-----------------------------------------------------------------------------
+inline
+void TRF_IP_AFTER::Notify(const uint32_t &, const uint32_t & newValue)
+{
+// User changes his address. Add new IP
+if (!newValue)
+ return;
+
+EVENT_LOOP_SINGLETON::GetInstance().Enqueue(traffCnt, &TRAFFCOUNTER::AddUser, user);
+}
+//-----------------------------------------------------------------------------
+inline
+void ADD_USER_NONIFIER::Notify(const user_iter & user)
+{
+EVENT_LOOP_SINGLETON::GetInstance().Enqueue(traffCnt, &TRAFFCOUNTER::SetUserNotifiers, user);
+}
+//-----------------------------------------------------------------------------
+inline
+void DEL_USER_NONIFIER::Notify(const user_iter & user)
+{
+EVENT_LOOP_SINGLETON::GetInstance().Enqueue(traffCnt, &TRAFFCOUNTER::UnSetUserNotifiers, user);
+EVENT_LOOP_SINGLETON::GetInstance().Enqueue(traffCnt, &TRAFFCOUNTER::DelUser, user->GetCurrIP());
+}
+//-----------------------------------------------------------------------------
+#endif //TRAFFCOUNTER_H
--- /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>
+ */
+
+/*
+ $Revision: 1.101 $
+ $Date: 2010/11/03 10:50:03 $
+ $Author: faust $
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <pthread.h>
+#include <unistd.h> // access
+
+#include <cassert>
+
+#include "user.h"
+#include "common.h"
+#include "settings.h"
+#include "script_executer.h"
+#include "tariff.h"
+#include "tariffs.h"
+#include "admin.h"
+
+USER::USER(const SETTINGS * s,
+ const BASE_STORE * st,
+ const TARIFFS * t,
+ const ADMIN & a,
+ const map<uint32_t, user_iter> * ipIdx)
+ : property(s),
+ WriteServLog(GetStgLogger()),
+ login(),
+ id(0),
+ __connected(0),
+ connected(__connected),
+ userIDGenerator(),
+ __currIP(0),
+ currIP(__currIP),
+ lastIPForDisconnect(0),
+ pingTime(0),
+ sysAdmin(a),
+ store(st),
+ tariffs(t),
+ tariff(tariffs->GetNoTariff()),
+ cash(property.cash),
+ up(property.up),
+ down(property.down),
+ lastCashAdd(property.lastCashAdd),
+ passiveTime(property.passiveTime),
+ lastCashAddTime(property.lastCashAddTime),
+ freeMb(property.freeMb),
+ lastActivityTime(property.lastActivityTime),
+ password(property.password),
+ passive(property.passive),
+ disabled(property.disabled),
+ disabledDetailStat(property.disabledDetailStat),
+ alwaysOnline(property.alwaysOnline),
+ tariffName(property.tariffName),
+ nextTariff(property.nextTariff),
+ address(property.address),
+ note(property.note),
+ group(property.group),
+ email(property.email),
+ phone(property.phone),
+ realName(property.realName),
+ credit(property.credit),
+ creditExpire(property.creditExpire),
+ ips(property.ips),
+ userdata0(property.userdata0),
+ userdata1(property.userdata1),
+ userdata2(property.userdata2),
+ userdata3(property.userdata3),
+ userdata4(property.userdata4),
+ userdata5(property.userdata5),
+ userdata6(property.userdata6),
+ userdata7(property.userdata7),
+ userdata8(property.userdata8),
+ userdata9(property.userdata9),
+ passiveNotifier(this),
+ tariffNotifier(this),
+ cashNotifier(this),
+ ipNotifier(this)
+{
+settings = s;
+ipIndex = ipIdx;
+
+password = "*_EMPTY_PASSWORD_*";
+tariffName = NO_TARIFF_NAME;
+connected = 0;
+traffStatInUse = 0;
+traffStat = &traffStatInternal[0];
+tariff = tariffs->GetNoTariff();
+ips = StrToIPS("*");
+deleted = false;
+lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
+lastWriteDeatiledStat = stgTime;
+lastSwapDeatiledStat = stgTime;
+
+property.tariffName.AddBeforeNotifier(&tariffNotifier);
+property.passive.AddBeforeNotifier(&passiveNotifier);
+property.cash.AddBeforeNotifier(&cashNotifier);
+currIP.AddAfterNotifier(&ipNotifier);
+
+lastScanMessages = 0;
+
+writeFreeMbTraffCost = settings->GetWriteFreeMbTraffCost();
+
+pthread_mutexattr_t attr;
+pthread_mutexattr_init(&attr);
+pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+pthread_mutex_init(&mutex, &attr);
+}
+//-----------------------------------------------------------------------------
+USER::USER(const USER & u)
+ : property(u.settings),
+ WriteServLog(GetStgLogger()),
+ login(u.login),
+ id(u.id),
+ __connected(u.__connected),
+ connected(__connected),
+ __currIP(u.__currIP),
+ currIP(__currIP),
+ lastIPForDisconnect(0),
+ pingTime(u.pingTime),
+ sysAdmin(u.sysAdmin),
+ store(u.store),
+ tariffs(u.tariffs),
+ tariff(u.tariff),
+ cash(property.cash),
+ up(property.up),
+ down(property.down),
+ lastCashAdd(property.lastCashAdd),
+ passiveTime(property.passiveTime),
+ lastCashAddTime(property.lastCashAddTime),
+ freeMb(property.freeMb),
+ lastActivityTime(property.lastActivityTime),
+ password(property.password),
+ passive(property.passive),
+ disabled(property.disabled),
+ disabledDetailStat(property.disabledDetailStat),
+ alwaysOnline(property.alwaysOnline),
+ tariffName(property.tariffName),
+ nextTariff(property.nextTariff),
+ address(property.address),
+ note(property.note),
+ group(property.group),
+ email(property.email),
+ phone(property.phone),
+ realName(property.realName),
+ credit(property.credit),
+ creditExpire(property.creditExpire),
+ ips(property.ips),
+ userdata0(property.userdata0),
+ userdata1(property.userdata1),
+ userdata2(property.userdata2),
+ userdata3(property.userdata3),
+ userdata4(property.userdata4),
+ userdata5(property.userdata5),
+ userdata6(property.userdata6),
+ userdata7(property.userdata7),
+ userdata8(property.userdata8),
+ userdata9(property.userdata9),
+ passiveNotifier(this),
+ tariffNotifier(this),
+ cashNotifier(this),
+ ipNotifier(this)
+{
+if (&u == this)
+ return;
+
+connected = 0;
+traffStatInUse = 0;
+
+ipIndex = u.ipIndex;
+
+deleted = u.deleted;
+traffStat = &traffStatInternal[traffStatInUse % 2];
+traffStatToWrite = &traffStatInternal[(traffStatInUse +1) % 2];
+
+lastWriteStat = u.lastWriteStat;
+lastWriteDeatiledStat = u.lastWriteDeatiledStat;
+lastSwapDeatiledStat = u.lastSwapDeatiledStat;
+
+settings = u.settings;
+
+property.tariffName.AddBeforeNotifier(&tariffNotifier);
+property.passive.AddBeforeNotifier(&passiveNotifier);
+property.cash.AddBeforeNotifier(&cashNotifier);
+currIP.AddAfterNotifier(&ipNotifier);
+
+lastScanMessages = 0;
+
+writeFreeMbTraffCost = settings->GetWriteFreeMbTraffCost();
+
+pthread_mutexattr_t attr;
+pthread_mutexattr_init(&attr);
+pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+pthread_mutex_init(&mutex, &attr);
+}
+//-----------------------------------------------------------------------------
+USER::~USER()
+{
+property.passive.DelBeforeNotifier(&passiveNotifier);
+property.tariffName.DelBeforeNotifier(&tariffNotifier);
+pthread_mutex_destroy(&mutex);
+}
+//-----------------------------------------------------------------------------
+void USER::SetLogin(string const & l)
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+assert(login.empty() && "Login is already set");
+login = l;
+id = userIDGenerator.GetNextID();
+}
+//-----------------------------------------------------------------------------
+int USER::ReadConf()
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+USER_CONF uc;
+
+if (store->RestoreUserConf(&uc, login))
+ {
+ WriteServLog("Cannot read conf for user %s.", login.c_str());
+ WriteServLog("%s", store->GetStrError().c_str());
+ printfd(__FILE__, "Cannot read conf for user %s.\n", login.c_str());
+ printfd(__FILE__, "%s\n", store->GetStrError().c_str());
+ return -1;
+ }
+
+password = uc.password;
+passive = uc.passive;
+disabled = uc.disabled;
+disabledDetailStat = uc.disabledDetailStat;
+alwaysOnline = uc.alwaysOnline;
+tariffName = uc.tariffName;
+address = uc.address;
+phone = uc.phone;
+email = uc.email;
+note = uc.note;
+realName = uc.realName;
+group = uc.group;
+credit = uc.credit;
+nextTariff = uc.nextTariff;
+userdata0 = uc.userdata[0];
+userdata1 = uc.userdata[1];
+userdata2 = uc.userdata[2];
+userdata3 = uc.userdata[3];
+userdata4 = uc.userdata[4];
+userdata5 = uc.userdata[5];
+userdata6 = uc.userdata[6];
+userdata7 = uc.userdata[7];
+userdata8 = uc.userdata[8];
+userdata9 = uc.userdata[9];
+
+creditExpire = uc.creditExpire;
+ips = uc.ips;
+
+tariff = tariffs->FindByName(tariffName);
+if (tariff == NULL)
+ {
+ WriteServLog("Cannot read user %s. Tariff %s not exist.",
+ login.c_str(), property.tariffName.Get().c_str());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int USER::ReadStat()
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+USER_STAT us;
+
+if (store->RestoreUserStat(&us, login))
+ {
+ WriteServLog("Cannot read stat for user %s.", login.c_str());
+ WriteServLog("%s", store->GetStrError().c_str());
+ printfd(__FILE__, "Cannot read stat for user %s.\n", login.c_str());
+ printfd(__FILE__, "%s\n", store->GetStrError().c_str());
+ return -1;
+ }
+
+up = us.up;
+down = us.down;
+cash = us.cash;
+freeMb = us.freeMb;
+lastCashAdd = us.lastCashAdd;
+lastCashAddTime = us.lastCashAddTime;
+passiveTime = us.passiveTime;
+lastActivityTime = us.lastActivityTime;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int USER::WriteConf()
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+USER_CONF uc;
+
+uc.password = password;
+uc.passive = passive;
+uc.disabled = disabled;
+uc.disabledDetailStat = disabledDetailStat;
+uc.alwaysOnline = alwaysOnline;
+uc.tariffName = tariffName;
+uc.address = address;
+uc.phone = phone;
+uc.email = email;
+uc.note = note;
+uc.realName = realName;
+uc.group = group;
+uc.credit = credit;
+uc.nextTariff = nextTariff;
+uc.userdata[0] = userdata0;
+uc.userdata[1] = userdata1;
+uc.userdata[2] = userdata2;
+uc.userdata[3] = userdata3;
+uc.userdata[4] = userdata4;
+uc.userdata[5] = userdata5;
+uc.userdata[6] = userdata6;
+uc.userdata[7] = userdata7;
+uc.userdata[8] = userdata8;
+uc.userdata[9] = userdata9;
+
+uc.creditExpire = creditExpire;
+uc.ips = ips;
+
+printfd(__FILE__, "USER::WriteConf()\n");
+
+if (store->SaveUserConf(uc, login))
+ {
+ WriteServLog("Cannot write conf for user %s.", login.c_str());
+ WriteServLog("%s", store->GetStrError().c_str());
+ printfd(__FILE__, "Cannot write conf for user %s.\n", login.c_str());
+ printfd(__FILE__, "%s\n", store->GetStrError().c_str());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int USER::WriteStat()
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+USER_STAT us;
+
+us.up = up;
+us.down = down;
+us.cash = cash;
+us.freeMb = freeMb;
+us.lastCashAdd = lastCashAdd;
+us.lastCashAddTime = lastCashAddTime;
+us.passiveTime = passiveTime;
+us.lastActivityTime = lastActivityTime;
+
+printfd(__FILE__, "USER::WriteStat()\n");
+
+if (store->SaveUserStat(us, login))
+ {
+ WriteServLog("Cannot write stat for user %s.", login.c_str());
+ WriteServLog("%s", store->GetStrError().c_str());
+ printfd(__FILE__, "Cannot write stat for user %s.\n", login.c_str());
+ printfd(__FILE__, "%s\n", store->GetStrError().c_str());
+ return -1;
+ }
+
+lastWriteStat = stgTime;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int USER::WriteMonthStat()
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+USER_STAT us;
+struct tm * t1;
+time_t tt = stgTime - 3600;
+t1 = localtime(&tt);
+
+us.up = up;
+us.down = down;
+us.cash = cash;
+us.freeMb = freeMb;
+us.lastCashAdd = lastCashAdd;
+us.lastCashAddTime = lastCashAddTime;
+us.passiveTime = passiveTime;
+us.lastActivityTime = lastActivityTime;
+
+if (store->SaveMonthStat(us, t1->tm_mon, t1->tm_year, login))
+ {
+ WriteServLog("Cannot write month stat for user %s.", login.c_str());
+ WriteServLog("%s", store->GetStrError().c_str());
+ printfd(__FILE__, "Cannot write month stat for user %s.\n", login.c_str());
+ printfd(__FILE__, "%s\n", store->GetStrError().c_str());
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int USER::Authorize(uint32_t ip, const string &, uint32_t dirs, const BASE_AUTH * auth)
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+/*
+ * Authorize user. It only means that user will be authorized. Nothing more.
+ * User can be connected or disconnected while authorized.
+ * Example: user is authorized but disconnected due to 0 money or blocking
+ */
+
+/*
+ * Prevent double authorization by identical authorizers
+ */
+if (authorizedBy.find(auth) != authorizedBy.end())
+ return 0;
+
+if (!ip)
+ return -1;
+
+for (int i = 0; i < DIR_NUM; i++)
+ {
+ enabledDirs[i] = dirs & (1 << i);
+ }
+
+if (authorizedBy.size())
+ {
+ if (currIP != ip)
+ {
+ // We are already authorized, but with different IP address
+ errorStr = "User " + login + " alredy authorized with IP address " + inet_ntostring(ip);
+ return -1;
+ }
+
+ map<uint32_t, user_iter>::const_iterator ci = ipIndex->find(ip);
+ if (ci != ipIndex->end())
+ {
+ // Address is already present in IP-index
+ // If it's not our IP - throw an error
+ if (&(*ci->second) != this)
+ {
+ errorStr = "IP address " + inet_ntostring(ip) + " alredy in use";
+ return -1;
+ }
+ }
+ }
+else
+ {
+ if (ipIndex->find(ip) != ipIndex->end())
+ {
+ // Address is already present in IP-index
+ errorStr = "IP address " + inet_ntostring(ip) + " alredy in use";
+ return -1;
+ }
+
+ if (ips.ConstData().IsIPInIPS(ip))
+ {
+ currIP = ip;
+ lastIPForDisconnect = currIP;
+ }
+ else
+ {
+ printfd(__FILE__, " user %s: ips = %s\n", login.c_str(), ips.ConstData().GetIpStr().c_str());
+ errorStr = "IP address " + inet_ntostring(ip) + " not belong user " + login;
+ return -1;
+ }
+ }
+
+authorizedBy.insert(auth);
+
+ScanMessage();
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+void USER::Unauthorize(const BASE_AUTH * auth)
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+/*
+ * Authorizer tries to unauthorize user, that was not authorized by it
+ */
+if (!authorizedBy.erase(auth))
+ return;
+
+if (authorizedBy.empty())
+ {
+ lastIPForDisconnect = currIP;
+ currIP = 0; // DelUser in traffcounter
+ return;
+ }
+}
+//-----------------------------------------------------------------------------
+bool USER::IsAuthorizedBy(const BASE_AUTH * auth) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+// Is this user authorized by specified authorizer?
+return authorizedBy.find(auth) != authorizedBy.end();
+}
+//-----------------------------------------------------------------------------
+void USER::Connect(bool fakeConnect)
+{
+/*
+ * Connect user to Internet. This function is differ from Authorize() !!!
+ */
+
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (!fakeConnect)
+ {
+ string scriptOnConnect = settings->GetScriptDir() + "/OnConnect";
+
+ if (access(scriptOnConnect.c_str(), X_OK) == 0)
+ {
+ char dirsStr[DIR_NUM + 1];
+ dirsStr[DIR_NUM] = 0;
+ for (int i = 0; i < DIR_NUM; i++)
+ {
+ dirsStr[i] = enabledDirs[i] ? '1' : '0';
+ }
+
+ string scriptOnConnectParams;
+ strprintf(&scriptOnConnectParams,
+ "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
+ scriptOnConnect.c_str(),
+ login.c_str(),
+ inet_ntostring(currIP).c_str(),
+ (double)cash,
+ id,
+ dirsStr);
+
+ ScriptExec(scriptOnConnectParams);
+ }
+ else
+ {
+ WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
+ }
+
+ connected = true;
+ }
+
+if (store->WriteUserConnect(login, currIP))
+ {
+ WriteServLog("Cannot write connect for user %s.", login.c_str());
+ WriteServLog("%s", store->GetStrError().c_str());
+ }
+
+if (!fakeConnect)
+ lastIPForDisconnect = currIP;
+
+//printfd(__FILE__, "Connect. user name \'%s\' ip=%s\n", login.c_str(), inet_ntostring(currIP).c_str());
+/*if (settings->GetLogUserConnectDisconnect())
+ WriteServLog("User \'%s\', %s: Connect.", login.c_str(), inet_ntostring(currIP).c_str());*/
+}
+//-----------------------------------------------------------------------------
+void USER::Disconnect(bool fakeDisconnect, const std::string & reason)
+{
+/*
+ * Disconnect user from Internet. This function is differ from UnAuthorize() !!!
+ */
+
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (!lastIPForDisconnect)
+ {
+ printfd(__FILE__, "lastIPForDisconnect\n");
+ return;
+ }
+
+if (!fakeDisconnect)
+ {
+ string scriptOnDisonnect = settings->GetScriptDir() + "/OnDisconnect";
+
+ if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
+ {
+ char dirsStr[DIR_NUM + 1];
+ dirsStr[DIR_NUM] = 0;
+ for (int i = 0; i < DIR_NUM; i++)
+ {
+ dirsStr[i] = enabledDirs[i] ? '1' : '0';
+ }
+
+ string scriptOnDisonnectParams;
+ strprintf(&scriptOnDisonnectParams,
+ "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
+ scriptOnDisonnect.c_str(),
+ login.c_str(),
+ inet_ntostring(lastIPForDisconnect).c_str(),
+ (double)cash,
+ id,
+ dirsStr);
+
+ ScriptExec(scriptOnDisonnectParams);
+ }
+ else
+ {
+ WriteServLog("Script OnDisconnect cannot be executed. File not found.");
+ }
+
+ connected = false;
+ }
+
+if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload, cash, freeMb, reason))
+ {
+ WriteServLog("Cannot write disconnect for user %s.", login.c_str());
+ WriteServLog("%s", store->GetStrError().c_str());
+ }
+
+//printfd(__FILE__, "Disconnect. User name \'%s\' ip=%s reason: '%s'\n", login.c_str(), inet_ntostring(lastIPForDisconnect).c_str(), reason.c_str());
+/*if (settings->GetLogUserConnectDisconnect())
+ WriteServLog("User \'%s\', %s: Disconnect.", login.c_str(), inet_ntostring(lastIPForDisconnect).c_str());*/
+
+if (!fakeDisconnect)
+ lastIPForDisconnect = 0;
+
+DIR_TRAFF zeroSesssion;
+
+sessionUpload = zeroSesssion;
+sessionDownload = zeroSesssion;
+}
+//-----------------------------------------------------------------------------
+void USER::PrintUser() const
+{
+//return;
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+cout << "============================================================" << endl;
+cout << "id=" << id << endl;
+cout << "login=" << login << endl;
+cout << "password=" << password << endl;
+cout << "passive=" << passive << endl;
+cout << "disabled=" << disabled << endl;
+cout << "disabledDetailStat=" << disabledDetailStat << endl;
+cout << "alwaysOnline=" << alwaysOnline << endl;
+cout << "tariffName=" << tariffName << endl;
+cout << "address=" << address << endl;
+cout << "phone=" << phone << endl;
+cout << "email=" << email << endl;
+cout << "note=" << note << endl;
+cout << "realName=" <<realName << endl;
+cout << "group=" << group << endl;
+cout << "credit=" << credit << endl;
+cout << "nextTariff=" << nextTariff << endl;
+cout << "userdata0" << userdata0 << endl;
+cout << "userdata1" << userdata1 << endl;
+cout << "creditExpire=" << creditExpire << endl;
+cout << "ips=" << ips << endl;
+cout << "------------------------" << endl;
+cout << "up=" << up << endl;
+cout << "down=" << down << endl;
+cout << "cash=" << cash << endl;
+cout << "freeMb=" << freeMb << endl;
+cout << "lastCashAdd=" << lastCashAdd << endl;
+cout << "lastCashAddTime=" << lastCashAddTime << endl;
+cout << "passiveTime=" << passiveTime << endl;
+cout << "lastActivityTime=" << lastActivityTime << endl;
+cout << "============================================================" << endl;
+}
+//-----------------------------------------------------------------------------
+void USER::Run()
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (stgTime - lastWriteStat > settings->GetStatWritePeriod())
+ {
+ printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
+ WriteStat();
+ }
+if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
+ {
+ WriteServLog("User: %s. Credit expired.", login.c_str());
+ credit = 0;
+ creditExpire = 0;
+ WriteConf();
+ }
+
+if (passive.ConstData()
+ && (stgTime % 30 == 0)
+ && (passiveTime.ModificationTime() != stgTime))
+ {
+ passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
+ printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
+ }
+
+if (!authorizedBy.empty())
+ {
+ if (connected)
+ {
+ lastActivityTime = *const_cast<time_t *>(&stgTime);
+ }
+ if (!connected && IsInetable())
+ {
+ Connect();
+ }
+ if (connected && !IsInetable())
+ {
+ if (disabled)
+ Disconnect(false, "disabled");
+ else if (passive)
+ Disconnect(false, "passive");
+ else
+ Disconnect(false, "no cash");
+ }
+
+ if (stgTime - lastScanMessages > 10)
+ {
+ ScanMessage();
+ lastScanMessages = stgTime;
+ }
+ }
+else
+ {
+ if (connected)
+ {
+ Disconnect(false, "not authorized");
+ }
+ }
+
+}
+//-----------------------------------------------------------------------------
+void USER::UpdatePingTime(time_t t)
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+//printfd(__FILE__, "UpdatePingTime(%d) %s\n", t, login.c_str());
+if (t)
+ pingTime = t;
+else
+ pingTime = stgTime;
+}
+//-----------------------------------------------------------------------------
+bool USER::IsInetable()
+{
+//STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (disabled || passive)
+ return false;
+
+if (settings->GetFreeMbAllowInet())
+ {
+ if (freeMb >= 0)
+ return true;
+ }
+
+if (settings->GetShowFeeInCash())
+ {
+ return (cash >= -credit);
+ }
+
+return (cash - tariff->GetFee() >= -credit);
+}
+//-----------------------------------------------------------------------------
+string USER::GetEnabledDirs()
+{
+//STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+string dirs = "";
+for(int i = 0; i < DIR_NUM; i++)
+ dirs += enabledDirs[i] ? "1" : "0";
+return dirs;
+}
+//-----------------------------------------------------------------------------
+#ifdef TRAFF_STAT_WITH_PORTS
+void USER::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
+#else
+void USER::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
+#endif
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (!connected)
+ return;
+
+double cost = 0;
+DIR_TRAFF dt(up);
+
+int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
+int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
+
+dt[dir] += len;
+
+int tt = tariff->GetTraffType();
+if (tt == TRAFF_UP ||
+ tt == TRAFF_UP_DOWN ||
+ // Check NEW traff data
+ (tt == TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
+ {
+ double dc = 0;
+ if (traff < threshold &&
+ traff + len >= threshold)
+ {
+ // cash = partBeforeThreshold * priceBeforeThreshold +
+ // partAfterThreshold * priceAfterThreshold
+ int64_t before = threshold - traff; // Chunk part before threshold
+ int64_t after = len - before; // Chunk part after threshold
+ dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
+ down.ConstData()[dir],
+ dir,
+ stgTime) * before +
+ tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
+ down.ConstData()[dir],
+ dir,
+ stgTime) * after;
+ }
+ else
+ {
+ dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
+ down.ConstData()[dir],
+ dir,
+ stgTime) * len;
+ }
+
+ if (freeMb.ConstData() <= 0) // FreeMb is exhausted
+ cost = dc;
+ else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
+ cost = dc - freeMb.ConstData();
+
+ // Direct access to internal data structures via friend-specifier
+ property.stat.freeMb -= dc;
+ property.stat.cash -= cost;
+ cash.ModifyTime();
+ freeMb.ModifyTime();
+ }
+
+up = dt;
+sessionUpload[dir] += len;
+
+//Add detailed stat
+
+if (!writeFreeMbTraffCost && freeMb.ConstData() >= 0)
+ cost = 0;
+
+#ifdef TRAFF_STAT_WITH_PORTS
+IP_DIR_PAIR idp(ip, dir, port);
+#else
+IP_DIR_PAIR idp(ip, dir);
+#endif
+
+map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
+lb = traffStat->lower_bound(idp);
+if (lb == traffStat->end())
+ {
+ traffStat->insert(lb,
+ pair<IP_DIR_PAIR, STAT_NODE>(idp,
+ STAT_NODE(len, 0, cost)));
+ }
+else
+ if (lb->first.dir == dir && lb->first.ip == ip)
+ {
+ lb->second.cash += cost;
+ lb->second.up += len;
+ }
+ else
+ {
+ traffStat->insert(lb,
+ pair<IP_DIR_PAIR, STAT_NODE>(idp,
+ STAT_NODE(len, 0, cost)));
+ }
+}
+//-----------------------------------------------------------------------------
+#ifdef TRAFF_STAT_WITH_PORTS
+void USER::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
+#else
+void USER::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
+#endif
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (!connected)
+ return;
+
+double cost = 0;
+DIR_TRAFF dt(down);
+
+int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
+int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
+
+dt[dir] += len;
+
+int tt = tariff->GetTraffType();
+if (tt == TRAFF_DOWN ||
+ tt == TRAFF_UP_DOWN ||
+ // Check NEW traff data
+ (tt == TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
+ {
+ double dc = 0;
+ if (traff < threshold &&
+ traff + len >= threshold)
+ {
+ // cash = partBeforeThreshold * priceBeforeThreshold +
+ // partAfterThreshold * priceAfterThreshold
+ int64_t before = threshold - traff; // Chunk part before threshold
+ int64_t after = len - before; // Chunk part after threshold
+ dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
+ down.ConstData()[dir], // Traff before chunk
+ dir,
+ stgTime) * before +
+ tariff->GetPriceWithTraffType(up.ConstData()[dir],
+ dt[dir], // Traff after chunk
+ dir,
+ stgTime) * after;
+ }
+ else
+ {
+ dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
+ down.ConstData()[dir],
+ dir,
+ stgTime) * len;
+ }
+
+ if (freeMb.ConstData() <= 0) // FreeMb is exhausted
+ cost = dc;
+ else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
+ cost = dc - freeMb.ConstData();
+
+ property.stat.freeMb -= dc;
+ property.stat.cash -= cost;
+ cash.ModifyTime();
+ freeMb.ModifyTime();
+ }
+
+down = dt;
+sessionDownload[dir] += len;
+
+//Add detailed stat
+
+if (!writeFreeMbTraffCost && freeMb.ConstData() >= 0)
+ cost = 0;
+
+#ifdef TRAFF_STAT_WITH_PORTS
+IP_DIR_PAIR idp(ip, dir, port);
+#else
+IP_DIR_PAIR idp(ip, dir);
+#endif
+
+map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
+lb = traffStat->lower_bound(idp);
+if (lb == traffStat->end())
+ {
+ traffStat->insert(lb,
+ pair<IP_DIR_PAIR, STAT_NODE>(idp,
+ STAT_NODE(0, len, cost)));
+ }
+else
+ if (lb->first.dir == dir && lb->first.ip == ip)
+ {
+ lb->second.cash += cost;
+ lb->second.down += len;
+ }
+ else
+ {
+ traffStat->insert(lb,
+ pair<IP_DIR_PAIR, STAT_NODE>(idp,
+ STAT_NODE(0, len, cost)));
+ }
+}
+//-----------------------------------------------------------------------------
+void USER::AddCurrIPBeforeNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+currIP.AddBeforeNotifier(n);
+}
+//-----------------------------------------------------------------------------
+void USER::DelCurrIPBeforeNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+currIP.DelBeforeNotifier(n);
+}
+//-----------------------------------------------------------------------------
+void USER::AddCurrIPAfterNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+currIP.AddAfterNotifier(n);
+}
+//-----------------------------------------------------------------------------
+void USER::DelCurrIPAfterNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * n)
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+currIP.DelAfterNotifier(n);
+}
+//-----------------------------------------------------------------------------
+void USER::OnAdd()
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+string scriptOnAdd = settings->GetScriptDir() + "/OnUserAdd";
+
+if (access(scriptOnAdd.c_str(), X_OK) == 0)
+ {
+ string scriptOnAddParams;
+ strprintf(&scriptOnAddParams,
+ "%s \"%s\"",
+ scriptOnAdd.c_str(),
+ login.c_str());
+
+ ScriptExec(scriptOnAddParams);
+ }
+else
+ {
+ WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
+ }
+}
+//-----------------------------------------------------------------------------
+void USER::OnDelete()
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+string scriptOnDel = settings->GetScriptDir() + "/OnUserDel";
+
+if (access(scriptOnDel.c_str(), X_OK) == 0)
+ {
+ string scriptOnDelParams;
+ strprintf(&scriptOnDelParams,
+ "%s \"%s\"",
+ scriptOnDel.c_str(),
+ login.c_str());
+
+ ScriptExec(scriptOnDelParams);
+ }
+else
+ {
+ WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
+ }
+
+Run();
+}
+//-----------------------------------------------------------------------------
+void USER::ResetDetailStat()
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+traffStatToWrite->erase(traffStatToWrite->begin(), traffStatToWrite->end());
+}
+//-----------------------------------------------------------------------------
+int USER::WriteDetailStat()
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+printfd(__FILE__, "USER::WriteDetailedStat(): size = %d\n", traffStatToWrite->size());
+
+if (traffStatToWrite->size() && !disabledDetailStat)
+ {
+ if (store->WriteDetailedStat(traffStatToWrite, lastWriteDeatiledStat, login))
+ {
+ WriteServLog("Cannot write detail stat for user %s.", login.c_str());
+ WriteServLog("%s", store->GetStrError().c_str());
+ }
+ }
+lastWriteDeatiledStat = lastSwapDeatiledStat;
+return 0;
+}
+//-----------------------------------------------------------------------------
+int USER::SwapDetailStat()
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+lastSwapDeatiledStat = stgTime;
+traffStatToWrite = &traffStatInternal[traffStatInUse % 2];
+traffStat = &traffStatInternal[++traffStatInUse % 2];
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+double USER::GetPassiveTimePart() const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+static int daysInMonth[12] =
+{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+struct tm * tms;
+time_t t = stgTime;
+tms = localtime(&t);
+
+time_t secMonth = daysInMonth[(tms->tm_mon + 11) % 12] * 24 * 3600; // Previous month
+
+if (tms->tm_year % 4 == 0 && tms->tm_mon == 1)
+ {
+ // Leap year
+ secMonth += 24 * 3600;
+ }
+
+int dt = secMonth - passiveTime;
+
+if (dt < 0)
+ dt = 0;
+
+return double(dt) / (secMonth);
+}
+//-----------------------------------------------------------------------------
+void USER::SetPassiveTimeAsNewUser()
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+time_t t;
+struct tm * tm;
+t = stgTime;
+tm = localtime(&t);
+int daysCurrMon = DaysInCurrentMonth();
+double pt = (tm->tm_mday - 1) / (double)daysCurrMon;
+
+passiveTime = (time_t)(pt * 24 * 3600 * daysCurrMon);
+}
+//-----------------------------------------------------------------------------
+void USER::MidnightResetSessionStat()
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (connected)
+ {
+ Disconnect(true, "fake");
+ Connect(true);
+ }
+}
+//-----------------------------------------------------------------------------
+void USER::ProcessNewMonth()
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+// Reset traff
+if (connected)
+ {
+ Disconnect(true, "fake");
+ }
+DIR_TRAFF zeroTarff;
+
+WriteMonthStat();
+
+up = zeroTarff;
+down = zeroTarff;
+
+if (connected)
+ {
+ Connect(true);
+ }
+
+// Set new tariff
+if (nextTariff.ConstData() != "")
+ {
+ const TARIFF * nt;
+ nt = tariffs->FindByName(nextTariff);
+ if (nt == NULL)
+ {
+ WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
+ login.c_str(), property.tariffName.Get().c_str());
+ }
+ else
+ {
+ property.tariffName.Set(nextTariff, sysAdmin, login, store);
+ tariff = nt;
+ }
+ ResetNextTariff();
+ WriteConf();
+ }
+}
+//-----------------------------------------------------------------------------
+void USER::ProcessDayFeeSpread()
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (passive.ConstData())
+ return;
+
+double f = tariff->GetFee() / DaysInCurrentMonth();
+
+if (f == 0.0)
+ return;
+
+double c = cash;
+property.cash.Set(c - f, sysAdmin, login, store, "Subscriber fee charge");
+ResetPassiveTime();
+}
+//-----------------------------------------------------------------------------
+void USER::ProcessDayFee()
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+double passiveTimePart = 1.0;
+if (!settings->GetFullFee())
+ {
+ passiveTimePart = GetPassiveTimePart();
+ }
+else
+ {
+ if (passive.ConstData())
+ {
+ printfd(__FILE__, "Don't charge fee `cause we are passive\n");
+ return;
+ }
+ }
+double f = tariff->GetFee() * passiveTimePart;
+
+ResetPassiveTime();
+
+if (f == 0.0)
+ return;
+
+double c = cash;
+printfd(__FILE__, "login: %8s Fee=%f PassiveTimePart=%f fee=%f\n",
+ login.c_str(),
+ tariff->GetFee(),
+ passiveTimePart,
+ f);
+property.cash.Set(c - f, sysAdmin, login, store, "Subscriber fee charge");
+}
+//-----------------------------------------------------------------------------
+void USER::SetPrepaidTraff()
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
+}
+//-----------------------------------------------------------------------------
+int USER::AddMessage(STG_MSG * msg)
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (SendMessage(*msg) == 0)
+ {
+ if (msg->header.repeat > 0)
+ {
+ msg->header.repeat--;
+ #ifndef DEBUG
+ //TODO: gcc v. 4.x generate ICE on x86_64
+ msg->header.lastSendTime = time(NULL);
+ #else
+ msg->header.lastSendTime = stgTime;
+ #endif
+ if (store->AddMessage(msg, login))
+ {
+ errorStr = store->GetStrError();
+ STG_LOGGER & WriteServLog = GetStgLogger();
+ WriteServLog("Error adding message %s", errorStr.c_str());
+ WriteServLog("%s", store->GetStrError().c_str());
+ return -1;
+ }
+ }
+ }
+else
+ {
+ if (store->AddMessage(msg, login))
+ {
+ errorStr = store->GetStrError();
+ STG_LOGGER & WriteServLog = GetStgLogger();
+ WriteServLog("Error adding message %s", errorStr.c_str());
+ WriteServLog("%s", store->GetStrError().c_str());
+ return -1;
+ }
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int USER::SendMessage(const STG_MSG & msg)
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (authorizedBy.empty())
+ {
+ return -1;
+ }
+
+int ret = -1;
+set<const BASE_AUTH*>::iterator it;
+
+it = authorizedBy.begin();
+while (it != authorizedBy.end())
+ {
+ if ((*it)->SendMessage(msg, currIP) == 0)
+ ret = 0;
+ ++it;
+ }
+return ret;
+}
+//-----------------------------------------------------------------------------
+int USER::ScanMessage()
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+vector<STG_MSG_HDR> hdrsList;
+
+if (store->GetMessageHdrs(&hdrsList, login))
+ {
+ printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str());
+ return -1;
+ }
+
+for (unsigned i = 0; i < hdrsList.size(); i++)
+ {
+
+ if (hdrsList[i].lastSendTime + hdrsList[i].repeatPeriod * 60 < (unsigned)stgTime)
+ {
+ STG_MSG msg;
+ if (store->GetMessage(hdrsList[i].id, &msg, login) == 0)
+ {
+ if (SendMessage(msg) == 0)
+ {
+ msg.header.repeat--;
+ if (msg.header.repeat < 0)
+ {
+ printfd(__FILE__, "DelMessage\n");
+ store->DelMessage(hdrsList[i].id, login);
+ }
+ else
+ {
+ #ifndef DEBUG
+ //TODO: gcc v. 4.x generate ICE on x86_64
+ msg.header.lastSendTime = time(NULL);
+ #else
+ msg.header.lastSendTime = stgTime;
+ #endif
+ if (store->EditMessage(msg, login))
+ {
+ printfd(__FILE__, "EditMessage Error %s\n", store->GetStrError().c_str());
+ }
+ }
+ }
+ }
+ else
+ {
+ WriteServLog("Cannot get message for user %s.", login.c_str());
+ WriteServLog("%s", store->GetStrError().c_str());
+ }
+ }
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
+{
+if (newPassive && !oldPassive)
+ user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
+ user->sysAdmin,
+ user->login,
+ user->store,
+ "Freeze");
+}
+//-----------------------------------------------------------------------------
+void CHG_TARIFF_NOTIFIER::Notify(const string &, const string & newTariff)
+{
+user->tariff = user->tariffs->FindByName(newTariff);
+}
+//-----------------------------------------------------------------------------
+void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
+{
+user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
+user->lastCashAdd = newCash - oldCash;
+}
+//-----------------------------------------------------------------------------
+void CHG_IP_NOTIFIER::Notify(const uint32_t & from, const uint32_t & to)
+{
+ printfd(__FILE__, "Change IP from %s to %s\n", inet_ntostring(from).c_str(), inet_ntostring(to).c_str());
+ if (from != 0)
+ user->Disconnect(false, "Change IP");
+ if (to != 0)
+ user->Connect(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>
+ */
+
+/*
+ $Revision: 1.48 $
+ $Date: 2010/11/03 10:50:03 $
+ $Author: faust $
+ */
+
+#ifndef USER_H
+#define USER_H
+
+#include <ctime>
+#include <list>
+#include <string>
+#include <map>
+#include <set>
+
+#include "os_int.h"
+#include "stg_const.h"
+#include "user_stat.h"
+#include "user_conf.h"
+#include "user_ips.h"
+#include "user_property.h"
+#include "base_auth.h"
+#include "stg_message.h"
+#include "noncopyable.h"
+
+using namespace std;
+
+//-----------------------------------------------------------------------------
+class USER;
+class TARIFF;
+class TARIFFS;
+class ADMIN;
+typedef list<USER>::iterator user_iter;
+typedef list<USER>::const_iterator const_user_iter;
+//-----------------------------------------------------------------------------
+class USER_ID_GENERATOR
+{
+friend class USER;
+private:
+ USER_ID_GENERATOR() {}
+ int GetNextID() { static int id = 0; return id++; }
+};
+//-----------------------------------------------------------------------------
+class CHG_PASSIVE_NOTIFIER : public PROPERTY_NOTIFIER_BASE<int>,
+ private NONCOPYABLE
+{
+public:
+ CHG_PASSIVE_NOTIFIER(USER * u) : user(u) {}
+ void Notify(const int & oldPassive, const int & newPassive);
+
+private:
+ USER * user;
+};
+//-----------------------------------------------------------------------------
+class CHG_TARIFF_NOTIFIER : public PROPERTY_NOTIFIER_BASE<string>,
+ private NONCOPYABLE
+{
+public:
+ CHG_TARIFF_NOTIFIER(USER * u) : user(u) {}
+ void Notify(const string & oldTariff, const string & newTariff);
+
+private:
+ USER * user;
+};
+//-----------------------------------------------------------------------------
+class CHG_CASH_NOTIFIER : public PROPERTY_NOTIFIER_BASE<double>,
+ private NONCOPYABLE
+{
+public:
+ CHG_CASH_NOTIFIER(USER * u) : user(u) {}
+ void Notify(const double & oldCash, const double & newCash);
+
+private:
+ USER * user;
+};
+//-----------------------------------------------------------------------------
+class CHG_IP_NOTIFIER : public PROPERTY_NOTIFIER_BASE<uint32_t>,
+ private NONCOPYABLE
+{
+public:
+ CHG_IP_NOTIFIER(USER * u) : user(u) {}
+ void Notify(const uint32_t & oldCash, const uint32_t & newCash);
+
+private:
+ USER * user;
+};
+//-----------------------------------------------------------------------------
+class USER
+{
+friend class CHG_PASSIVE_NOTIFIER;
+friend class CHG_TARIFF_NOTIFIER;
+friend class CHG_CASH_NOTIFIER;
+friend class CHG_IP_NOTIFIER;
+public:
+ USER(const SETTINGS * settings,
+ const BASE_STORE * store,
+ const TARIFFS * tariffs,
+ const ADMIN & sysAdmin,
+ const map<uint32_t, user_iter> * ipIndex);
+ USER(const USER & u);
+ ~USER();
+
+ int ReadConf();
+ int ReadStat();
+ int WriteConf();
+ int WriteStat();
+ int WriteMonthStat();
+
+ string const & GetLogin() const { return login; }
+ void SetLogin(string const & l);
+
+ uint32_t GetCurrIP() const { return currIP; }
+ time_t GetCurrIPModificationTime() const { return currIP.ModificationTime(); }
+
+ void AddCurrIPBeforeNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> *);
+ void DelCurrIPBeforeNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> *);
+
+ void AddCurrIPAfterNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> *);
+ void DelCurrIPAfterNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> *);
+
+ int GetID() const { return id; }
+
+ double GetPassiveTimePart() const;
+ void ResetPassiveTime() { passiveTime = 0; }
+ void SetPassiveTimeAsNewUser();
+
+ void ResetDetailStat();
+ int SwapDetailStat();
+ int WriteDetailStat();
+
+ const TARIFF * GetTariff() const { return tariff; }
+ void ResetNextTariff() { nextTariff = ""; }
+
+ #ifdef TRAFF_STAT_WITH_PORTS
+ void AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len);
+ void AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len);
+ #else
+ void AddTraffStatU(int dir, uint32_t ip, uint32_t len);
+ void AddTraffStatD(int dir, uint32_t ip, uint32_t len);
+ #endif
+
+ const DIR_TRAFF & GetSessionUpload() const { return sessionUpload; }
+ const DIR_TRAFF & GetSessionDownload() const { return sessionDownload; }
+
+ bool GetConnected() const { return connected; }
+ time_t GetConnectedModificationTime() const { return connected.ModificationTime(); }
+ int GetAuthorized() const { return authorizedBy.size(); }
+ int Authorize(uint32_t ip, const string & iface, uint32_t enabledDirs, const BASE_AUTH * auth);
+ void Unauthorize(const BASE_AUTH * auth);
+ bool IsAuthorizedBy(const BASE_AUTH * auth) const;
+ void OnAdd();
+ void OnDelete();
+
+ int AddMessage(STG_MSG * msg);
+
+ void UpdatePingTime(time_t t = 0);
+ time_t GetPingTime() const { return pingTime; }
+
+ void PrintUser() const;
+ void Run();
+
+ const string & GetStrError() const { return errorStr; }
+
+ USER_PROPERTIES property;
+
+ void SetDeleted() { deleted = true; }
+ bool GetDeleted() const { return deleted; }
+
+ time_t GetLastWriteStatTime() const { return lastWriteStat; }
+
+ void MidnightResetSessionStat();
+ void ProcessDayFee();
+ void SetPrepaidTraff();
+ void ProcessDayFeeSpread();
+ void ProcessNewMonth();
+
+ bool IsInetable();
+ string GetEnabledDirs();
+
+private:
+ STG_LOGGER & WriteServLog;
+
+ void Connect(bool fakeConnect = false);
+ void Disconnect(bool fakeDisconnect, const std::string & reason);
+ int SaveMonthStat(int month, int year);
+
+ int SendMessage(const STG_MSG & msg);
+ int RemoveMessage(uint64_t) { return 0; }
+ int ScanMessage();
+ time_t lastScanMessages;
+
+ string login;
+ int id;
+ bool __connected;
+ USER_PROPERTY<bool> connected;
+
+ bool enabledDirs[DIR_NUM];
+
+ USER_ID_GENERATOR userIDGenerator;
+
+ uint32_t __currIP; // ôÅËÕÝÉÊ ÁÄÒÅÓ ÐÏÌØÚÏ×ÁÔÅÌÑ
+ USER_PROPERTY<uint32_t> currIP;
+
+ /*
+ ë ÔÏÍÕ ÍÏÍÅÎÔÕ ËÁË ÍÙ ÕÖÅ ÎÅ Á×ÔÏÒÉÚÏ×ÁÎÉÙ, ÎÏ ÅÝÅ ÎÅ ×ÙÐÏÌÎÅÎ Disconnect,
+ currIP ÕÖÅ ÓÂÒÏÛÅÎ. ðÏÓÌÅÄÎÅÅ ÚÎÁÞÅÎÉÅ currIP ÓÏÈÒÁÎÑÅÍ × lastIPForDisconnect
+ */
+ uint32_t lastIPForDisconnect;
+
+ time_t pingTime;
+
+ const ADMIN sysAdmin;
+ const BASE_STORE * store;
+
+ const TARIFFS * tariffs;
+ const TARIFF * tariff;
+
+ map<IP_DIR_PAIR, STAT_NODE> traffStatInternal[2];
+ map<IP_DIR_PAIR, STAT_NODE> * traffStat;
+ map<IP_DIR_PAIR, STAT_NODE> * traffStatToWrite;
+ int traffStatInUse;
+
+ const SETTINGS * settings;
+
+ set<const BASE_AUTH *> authorizedBy;
+
+ const map<uint32_t, user_iter> * ipIndex;
+
+ bool deleted;
+
+ time_t lastWriteStat; // ÷ÒÅÍÑ ÐÏÓÌÅÄÎÅÊ ÚÁÐÉÓÉ ÓÔÁÔÉÓÔÉËÉ
+ time_t lastWriteDeatiledStat; // ÷ÒÅÍÑ ÐÏÓÌÅÄÎÅÊ ÚÁÐÉÓÉ ÄÅÔÁÌØÎÏÊ ÓÔÁÔÉÓÔÉËÉ
+ time_t lastSwapDeatiledStat; // ÷ÒÅÍÑ ÐÏÓÌÅÄÎÅÊ ÚÁÐÉÓÉ ÄÅÔÁÌØÎÏÊ ÓÔÁÔÉÓÔÉËÉ
+
+ bool writeFreeMbTraffCost;
+
+ // Properties
+ USER_PROPERTY<double> & cash;
+ USER_PROPERTY<DIR_TRAFF> & up;
+ USER_PROPERTY<DIR_TRAFF> & down;
+ USER_PROPERTY<double> & lastCashAdd;
+ USER_PROPERTY<time_t> & passiveTime;
+ USER_PROPERTY<time_t> & lastCashAddTime;
+ USER_PROPERTY<double> & freeMb;
+ USER_PROPERTY<time_t> & lastActivityTime;
+ USER_PROPERTY<string> & password;
+ USER_PROPERTY<int> & passive;
+ USER_PROPERTY<int> & disabled;
+ USER_PROPERTY<int> & disabledDetailStat;
+ USER_PROPERTY<int> & alwaysOnline;
+ USER_PROPERTY<string> & tariffName;
+ USER_PROPERTY<string> & nextTariff;
+ USER_PROPERTY<string> & address;
+ USER_PROPERTY<string> & note;
+ USER_PROPERTY<string> & group;
+ USER_PROPERTY<string> & email;
+ USER_PROPERTY<string> & phone;
+ USER_PROPERTY<string> & realName;
+ USER_PROPERTY<double> & credit;
+ USER_PROPERTY<time_t> & creditExpire;
+ USER_PROPERTY<USER_IPS> & ips;
+ USER_PROPERTY<string> & userdata0;
+ USER_PROPERTY<string> & userdata1;
+ USER_PROPERTY<string> & userdata2;
+ USER_PROPERTY<string> & userdata3;
+ USER_PROPERTY<string> & userdata4;
+ USER_PROPERTY<string> & userdata5;
+ USER_PROPERTY<string> & userdata6;
+ USER_PROPERTY<string> & userdata7;
+ USER_PROPERTY<string> & userdata8;
+ USER_PROPERTY<string> & userdata9;
+
+ // End properties
+
+ DIR_TRAFF sessionUpload;
+ DIR_TRAFF sessionDownload;
+
+ CHG_PASSIVE_NOTIFIER passiveNotifier;
+ CHG_TARIFF_NOTIFIER tariffNotifier;
+ CHG_CASH_NOTIFIER cashNotifier;
+ CHG_IP_NOTIFIER ipNotifier;
+
+ mutable pthread_mutex_t mutex;
+
+ string errorStr;
+};
+//-----------------------------------------------------------------------------
+
+#endif //USER_H
--- /dev/null
+#include "user_property.h"
+
+//-----------------------------------------------------------------------------
+USER_PROPERTIES::USER_PROPERTIES(const SETTINGS * s)
+:
+cash (stat.cash, "cash", false, true, GetStgLogger(), s),
+up (stat.up, "upload", false, true, GetStgLogger(), s),
+down (stat.down, "download", false, true, GetStgLogger(), s),
+lastCashAdd (stat.lastCashAdd, "lastCashAdd", false, true, GetStgLogger(), s),
+passiveTime (stat.passiveTime, "passiveTime", false, true, GetStgLogger(), s),
+lastCashAddTime (stat.lastCashAddTime, "lastCashAddTime", false, true, GetStgLogger(), s),
+freeMb (stat.freeMb, "freeMb", false, true, GetStgLogger(), s),
+lastActivityTime(stat.lastActivityTime, "lastActivityTime", false, true, GetStgLogger(), s),
+
+
+password (conf.password, "password", true, false, GetStgLogger(), s),
+passive (conf.passive, "passive", false, false, GetStgLogger(), s),
+disabled (conf.disabled, "disabled", false, false, GetStgLogger(), s),
+disabledDetailStat(conf.disabledDetailStat,"DisabledDetailStat",false,false,GetStgLogger(), s),
+alwaysOnline(conf.alwaysOnline, "alwaysOnline", false, false, GetStgLogger(), s),
+tariffName (conf.tariffName, "tariff", false, false, GetStgLogger(), s),
+nextTariff (conf.nextTariff, "new tariff", false, false, GetStgLogger(), s),
+address (conf.address, "address", false, false, GetStgLogger(), s),
+note (conf.note, "note", false, false, GetStgLogger(), s),
+group (conf.group, "group", false, false, GetStgLogger(), s),
+email (conf.email, "email", false, false, GetStgLogger(), s),
+phone (conf.phone, "phone", false, false, GetStgLogger(), s),
+realName (conf.realName, "realName", false, false, GetStgLogger(), s),
+credit (conf.credit, "credit", false, false, GetStgLogger(), s),
+creditExpire(conf.creditExpire, "creditExpire", false, false, GetStgLogger(), s),
+ips (conf.ips, "IP", false, false, GetStgLogger(), s),
+userdata0 (conf.userdata[0], "userdata0", false, false, GetStgLogger(), s),
+userdata1 (conf.userdata[1], "userdata1", false, false, GetStgLogger(), s),
+userdata2 (conf.userdata[2], "userdata2", false, false, GetStgLogger(), s),
+userdata3 (conf.userdata[3], "userdata3", false, false, GetStgLogger(), s),
+userdata4 (conf.userdata[4], "userdata4", false, false, GetStgLogger(), s),
+userdata5 (conf.userdata[5], "userdata5", false, false, GetStgLogger(), s),
+userdata6 (conf.userdata[6], "userdata6", false, false, GetStgLogger(), s),
+userdata7 (conf.userdata[7], "userdata7", false, false, GetStgLogger(), s),
+userdata8 (conf.userdata[8], "userdata8", false, false, GetStgLogger(), s),
+userdata9 (conf.userdata[9], "userdata9", false, false, GetStgLogger(), s)
+{
+
+}
+//-----------------------------------------------------------------------------
+
--- /dev/null
+/*
+$Revision: 1.44 $
+$Date: 2010/09/13 05:54:43 $
+$Author: faust $
+*/
+
+
+#ifndef USER_PROPERTY_H
+#define USER_PROPERTY_H
+
+#include <ctime>
+#include <string>
+#include <set>
+#include <sstream>
+#include <iostream>
+#include <algorithm>
+
+#include "base_store.h"
+#include "stg_logger.h"
+#include "admin.h"
+#include "settings.h"
+#include "notifer.h"
+#include "stg_logger.h"
+#include "stg_locker.h"
+#include "script_executer.h"
+
+using namespace std;
+
+extern const volatile time_t stgTime;
+
+//-----------------------------------------------------------------------------
+template<typename varT>
+class USER_PROPERTY
+ {
+public:
+ USER_PROPERTY(varT& val);
+ USER_PROPERTY<varT>& operator= (const varT&);
+ USER_PROPERTY<varT>& operator-= (const varT&);
+ virtual ~USER_PROPERTY();
+
+ const varT * operator&() const throw();
+ const varT& ConstData() const throw();
+
+ operator const varT&() const throw()
+ {
+ return value;
+ }
+
+ //bool IsEmpty() const throw();
+
+ void AddBeforeNotifier(PROPERTY_NOTIFIER_BASE<varT> * n);
+ void DelBeforeNotifier(PROPERTY_NOTIFIER_BASE<varT> * n);
+
+ void AddAfterNotifier(PROPERTY_NOTIFIER_BASE<varT> * n);
+ void DelAfterNotifier(PROPERTY_NOTIFIER_BASE<varT> * n);
+
+ time_t ModificationTime() const throw();
+ void ModifyTime() throw();
+
+protected:
+ varT & value;
+ time_t modificationTime;
+ //typedef set<PROPERTY_NOTIFIER_BASE<varT> *>::iterator notifier_iter_t;
+ mutable set<PROPERTY_NOTIFIER_BASE<varT> *> beforeNotifiers;
+ mutable set<PROPERTY_NOTIFIER_BASE<varT> *> afterNotifiers;
+ mutable pthread_mutex_t mutex;
+ };
+//-----------------------------------------------------------------------------
+template<typename varT>
+class USER_PROPERTY_LOGGED: public USER_PROPERTY<varT>
+ {
+public:
+ USER_PROPERTY_LOGGED(varT& val,
+ const string n,
+ bool isPassword,
+ bool isStat,
+ STG_LOGGER & logger,
+ const SETTINGS * s);
+ virtual ~USER_PROPERTY_LOGGED();
+
+ //operator const varT&() const throw();;
+ USER_PROPERTY_LOGGED<varT> * GetPointer() throw();
+ const varT & Get() const;
+ const string & GetName() const;
+ bool Set(const varT & val,
+ const ADMIN & admin,
+ const string & login,
+ const BASE_STORE * store,
+ const string & msg = "");
+protected:
+ void WriteAccessDenied(const string & login,
+ const ADMIN & admin,
+ const string & parameter);
+
+ void WriteSuccessChange(const string & login,
+ const ADMIN & admin,
+ const string & parameter,
+ const string & oldValue,
+ const string & newValue,
+ const string & msg,
+ const BASE_STORE * store);
+
+ void OnChange(const string & login,
+ const string & paramName,
+ const string & oldValue,
+ const string & newValue,
+ const ADMIN & admin);
+
+ string name; // parameter name. needed for logging
+ bool isPassword; // is parameter password. when true, it will be logged as *******
+ bool isStat; // is parameter a stat data or conf data?
+ mutable pthread_mutex_t mutex;
+ STG_LOGGER & stgLogger; // server's logger
+ const SETTINGS * settings;
+ };
+//-----------------------------------------------------------------------------
+class USER_PROPERTIES
+ {
+ friend class USER;
+/*
+ В этом месте важен порядок следования приватной и открытой частей.
+ Это связано с тем, что часть которая находится в публичной секции
+ по сути является завуалированной ссылкой на закрытую часть. Т.о. нам нужно
+ чтобы конструкторы из закрытой части вызвались раньше открытой. Поэтомому в
+ начале идет закрытая секция
+ * */
+
+private:
+ USER_STAT stat;
+ USER_CONF conf;
+
+public:
+ USER_PROPERTIES(const SETTINGS * settings);
+ USER_PROPERTY_LOGGED<double> cash;
+ USER_PROPERTY_LOGGED<DIR_TRAFF> up;
+ USER_PROPERTY_LOGGED<DIR_TRAFF> down;
+ USER_PROPERTY_LOGGED<double> lastCashAdd;
+ USER_PROPERTY_LOGGED<time_t> passiveTime;
+ USER_PROPERTY_LOGGED<time_t> lastCashAddTime;
+ USER_PROPERTY_LOGGED<double> freeMb;
+ USER_PROPERTY_LOGGED<time_t> lastActivityTime;
+
+ USER_PROPERTY_LOGGED<string> password;
+ USER_PROPERTY_LOGGED<int> passive;
+ USER_PROPERTY_LOGGED<int> disabled;
+ USER_PROPERTY_LOGGED<int> disabledDetailStat;
+ USER_PROPERTY_LOGGED<int> alwaysOnline;
+ USER_PROPERTY_LOGGED<string> tariffName;
+ USER_PROPERTY_LOGGED<string> nextTariff;
+ USER_PROPERTY_LOGGED<string> address;
+ USER_PROPERTY_LOGGED<string> note;
+ USER_PROPERTY_LOGGED<string> group;
+ USER_PROPERTY_LOGGED<string> email;
+ USER_PROPERTY_LOGGED<string> phone;
+ USER_PROPERTY_LOGGED<string> realName;
+ USER_PROPERTY_LOGGED<double> credit;
+ USER_PROPERTY_LOGGED<time_t> creditExpire;
+ USER_PROPERTY_LOGGED<USER_IPS> ips;
+ USER_PROPERTY_LOGGED<string> userdata0;
+ USER_PROPERTY_LOGGED<string> userdata1;
+ USER_PROPERTY_LOGGED<string> userdata2;
+ USER_PROPERTY_LOGGED<string> userdata3;
+ USER_PROPERTY_LOGGED<string> userdata4;
+ USER_PROPERTY_LOGGED<string> userdata5;
+ USER_PROPERTY_LOGGED<string> userdata6;
+ USER_PROPERTY_LOGGED<string> userdata7;
+ USER_PROPERTY_LOGGED<string> userdata8;
+ USER_PROPERTY_LOGGED<string> userdata9;
+ };
+
+//=============================================================================
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template <typename varT>
+USER_PROPERTY<varT>::USER_PROPERTY(varT& val)
+:
+value(val)
+{
+pthread_mutex_init(&mutex, NULL);
+modificationTime = stgTime;
+}
+//-----------------------------------------------------------------------------
+template <typename varT>
+USER_PROPERTY<varT>::~USER_PROPERTY()
+{
+}
+//-----------------------------------------------------------------------------
+template <typename varT>
+void USER_PROPERTY<varT>::ModifyTime() throw()
+{
+ modificationTime = stgTime;
+}
+//-----------------------------------------------------------------------------
+template <typename varT>
+USER_PROPERTY<varT>& USER_PROPERTY<varT>::operator= (const varT& newValue)
+{
+STG_LOCKER locker(&mutex, __FILE__, __LINE__);
+
+/*
+TODO
+if (value == newValue)
+ return *this;*/
+
+typename set<PROPERTY_NOTIFIER_BASE<varT> *>::iterator ni;
+
+//printf("USER_PROPERTY<varT>::operator= (const varT& rhs)\n");
+
+varT oldVal = value;
+
+ni = beforeNotifiers.begin();
+while (ni != beforeNotifiers.end())
+ (*ni++)->Notify(oldVal, newValue);
+
+value = newValue;
+modificationTime = stgTime;
+
+ni = afterNotifiers.begin();
+while (ni != afterNotifiers.end())
+ (*ni++)->Notify(oldVal, newValue);
+
+return *this;
+}
+//-----------------------------------------------------------------------------
+template <typename varT>
+USER_PROPERTY<varT>& USER_PROPERTY<varT>::operator-= (const varT& delta)
+{
+STG_LOCKER locker(&mutex, __FILE__, __LINE__);
+
+typename set<PROPERTY_NOTIFIER_BASE<varT> *>::iterator ni;
+
+varT oldVal = value;
+
+ni = beforeNotifiers.begin();
+while (ni != beforeNotifiers.end())
+ (*ni++)->Notify(oldVal, oldVal - delta);
+
+value -= delta;
+modificationTime = stgTime;
+
+ni = afterNotifiers.begin();
+while (ni != afterNotifiers.end())
+ (*ni++)->Notify(oldVal, value);
+
+return *this;
+}
+//-----------------------------------------------------------------------------
+template <typename varT>
+const varT * USER_PROPERTY<varT>::operator&() const throw()
+{
+STG_LOCKER locker(&mutex, __FILE__, __LINE__);
+return &value;
+}
+//-----------------------------------------------------------------------------
+template <typename varT>
+const varT& USER_PROPERTY<varT>::ConstData() const throw()
+{
+STG_LOCKER locker(&mutex, __FILE__, __LINE__);
+return value;
+}
+//-----------------------------------------------------------------------------
+/*template <typename varT>
+bool USER_PROPERTY<varT>::IsEmpty() const throw()
+{
+STG_LOCKER locker(&mutex, __FILE__, __LINE__);
+return !is_set;
+}*/
+//-----------------------------------------------------------------------------
+template <typename varT>
+void USER_PROPERTY<varT>::AddBeforeNotifier(PROPERTY_NOTIFIER_BASE<varT> * n)
+{
+STG_LOCKER locker(&mutex, __FILE__, __LINE__);
+beforeNotifiers.insert(n);
+}
+//-----------------------------------------------------------------------------
+template <typename varT>
+void USER_PROPERTY<varT>::DelBeforeNotifier(PROPERTY_NOTIFIER_BASE<varT> * n)
+{
+STG_LOCKER locker(&mutex, __FILE__, __LINE__);
+beforeNotifiers.erase(n);
+}
+//-----------------------------------------------------------------------------
+template <typename varT>
+void USER_PROPERTY<varT>::AddAfterNotifier(PROPERTY_NOTIFIER_BASE<varT> * n)
+{
+STG_LOCKER locker(&mutex, __FILE__, __LINE__);
+afterNotifiers.insert(n);
+}
+//-----------------------------------------------------------------------------
+template <typename varT>
+void USER_PROPERTY<varT>::DelAfterNotifier(PROPERTY_NOTIFIER_BASE<varT> * n)
+{
+STG_LOCKER locker(&mutex, __FILE__, __LINE__);
+afterNotifiers.erase(n);
+}
+//-----------------------------------------------------------------------------
+template <typename varT>
+time_t USER_PROPERTY<varT>::ModificationTime() const throw()
+{
+STG_LOCKER locker(&mutex, __FILE__, __LINE__);
+return modificationTime;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template <typename varT>
+USER_PROPERTY_LOGGED<varT>::USER_PROPERTY_LOGGED(
+ varT& val,
+ string n,
+ bool isPass,
+ bool isSt,
+ STG_LOGGER & logger,
+ const SETTINGS * s)
+
+:USER_PROPERTY<varT>(val),
+stgLogger(logger)
+{
+pthread_mutex_init(&mutex, NULL);
+STG_LOCKER locker(&mutex, __FILE__, __LINE__);
+USER_PROPERTY<varT>::value = val;
+isPassword = isPass;
+isStat = isSt;
+name = n;
+settings = s;
+}
+//-----------------------------------------------------------------------------
+template <typename varT>
+USER_PROPERTY_LOGGED<varT>::~USER_PROPERTY_LOGGED()
+{
+STG_LOCKER locker(&mutex, __FILE__, __LINE__);
+}
+//-----------------------------------------------------------------------------
+template <typename varT>
+USER_PROPERTY_LOGGED<varT> * USER_PROPERTY_LOGGED<varT>::GetPointer() throw()
+{
+STG_LOCKER locker(&mutex, __FILE__, __LINE__);
+return this;
+}
+//-----------------------------------------------------------------------------
+template <typename varT>
+const varT & USER_PROPERTY_LOGGED<varT>::Get() const
+{
+STG_LOCKER locker(&mutex, __FILE__, __LINE__);
+return USER_PROPERTY<varT>::value;
+};
+//-------------------------------------------------------------------------
+template <typename varT>
+const string & USER_PROPERTY_LOGGED<varT>::GetName() const
+{
+STG_LOCKER locker(&mutex, __FILE__, __LINE__);
+return name;
+};
+//-------------------------------------------------------------------------
+template <typename varT>
+bool USER_PROPERTY_LOGGED<varT>::Set(const varT & val,
+ const ADMIN & admin,
+ const string & login,
+ const BASE_STORE * store,
+ const string & msg)
+{
+STG_LOCKER locker(&mutex, __FILE__, __LINE__);
+
+//cout << "USER_PROPERTY_LOGGED " << val << endl;
+//value = val;
+//modificationTime = stgTime;
+
+const PRIV * priv = admin.GetPriv();
+string adm_login = admin.GetLogin();
+string adm_ip = admin.GetAdminIPStr();
+
+if ((priv->userConf && !isStat) || (priv->userStat && isStat) || (priv->userPasswd && isPassword) || (priv->userCash && name == "cash"))
+ {
+ stringstream oldVal;
+ stringstream newVal;
+
+ oldVal.flags(oldVal.flags() | ios::fixed);
+ newVal.flags(newVal.flags() | ios::fixed);
+
+ oldVal << USER_PROPERTY<varT>::value;
+ newVal << val;
+
+ OnChange(login, name, oldVal.str(), newVal.str(), admin);
+
+ if (isPassword)
+ {
+ WriteSuccessChange(login, admin, name, "******", "******", msg, store);
+ }
+ else
+ {
+ WriteSuccessChange(login, admin, name, oldVal.str(), newVal.str(), msg, store);
+ }
+ USER_PROPERTY<varT>::operator =(val);
+ return true;
+ }
+else
+ {
+ WriteAccessDenied(login, admin, name);
+ return false;
+ }
+return true;
+}
+//-------------------------------------------------------------------------
+template <typename varT>
+void USER_PROPERTY_LOGGED<varT>::WriteAccessDenied(const string & login,
+ const ADMIN & admin,
+ const string & parameter)
+{
+stgLogger("%s Change user \'%s.\' Parameter \'%s\'. Access denied.",
+ admin.GetLogStr().c_str(), login.c_str(), parameter.c_str());
+}
+//-------------------------------------------------------------------------
+template <typename varT>
+void USER_PROPERTY_LOGGED<varT>::WriteSuccessChange(const string & login,
+ const ADMIN & admin,
+ const string & parameter,
+ const string & oldValue,
+ const string & newValue,
+ const string & msg,
+ const BASE_STORE * store)
+{
+stgLogger("%s User \'%s\': \'%s\' parameter changed from \'%s\' to \'%s\'. %s",
+ admin.GetLogStr().c_str(),
+ login.c_str(),
+ parameter.c_str(),
+ oldValue.c_str(),
+ newValue.c_str(),
+ msg.c_str());
+
+
+/*char userLogMsg[2048];
+sprintf(userLogMsg, "\'%s\' parameter changed from \'%s\' to \'%s\'. %s",
+ parameter.c_str(), oldValue.c_str(),
+ newValue.c_str(), msg.c_str());*/
+store->WriteUserChgLog(login, admin.GetLogin(), admin.GetAdminIP(), parameter, oldValue, newValue, msg);
+//store->WriteLogString(userLogMsg, login);
+}
+//-------------------------------------------------------------------------
+template <typename varT>
+void USER_PROPERTY_LOGGED<varT>::OnChange(const string & login,
+ const string & paramName,
+ const string & oldValue,
+ const string & newValue,
+ const ADMIN &)
+{
+string str1;
+
+str1 = settings->GetConfDir() + "/OnChange";
+
+if (access(str1.c_str(), X_OK) == 0)
+ {
+ string str2("\"" + str1 + "\" \"" + login + "\" \"" + paramName + "\" \"" + oldValue + "\" \"" + newValue + "\"");
+ ScriptExec(str2);
+ }
+else
+ {
+ stgLogger("Script OnChange cannot be executed. File %s not found.", str1.c_str());
+ }
+}
+//-------------------------------------------------------------------------
+//-------------------------------------------------------------------------
+//-------------------------------------------------------------------------
+template<typename varT>
+stringstream & operator<< (stringstream & s, const USER_PROPERTY<varT> & v)
+{
+s << v.ConstData();
+return s;
+}
+//-----------------------------------------------------------------------------
+template<typename varT>
+ostream & operator<< (ostream & o, const USER_PROPERTY<varT> & v)
+{
+return o << v.ConstData();
+}
+//-----------------------------------------------------------------------------
+
+
+#endif // USER_PROPERTY_H
+
--- /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>
+ */
+
+/*
+ $Revision: 1.61 $
+ $Date: 2010/09/13 05:56:42 $
+ $Author: faust $
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <pthread.h>
+#include <csignal>
+#include <cassert>
+#include <algorithm>
+#include <utility>
+#include <string>
+#include <vector>
+
+#include "settings.h"
+#include "users.h"
+#include "user.h"
+#include "common.h"
+#include "stg_timer.h"
+
+using namespace std;
+
+extern const volatile time_t stgTime;
+
+//#define USERS_DEBUG 1
+
+//-----------------------------------------------------------------------------
+USERS::USERS(SETTINGS * s, BASE_STORE * st, TARIFFS * t, const ADMIN & sa)
+ : users(),
+ usersToDelete(),
+ userIPNotifiersBefore(),
+ userIPNotifiersAfter(),
+ ipIndex(),
+ loginIndex(),
+ settings(s),
+ tariffs(t),
+ store(st),
+ sysAdmin(sa),
+ WriteServLog(GetStgLogger()),
+ nonstop(false),
+ isRunning(false),
+ mutex(),
+ thread(),
+ handle(0),
+ searchDescriptors(),
+ onAddNotifiers(),
+ onDelNotifiers()
+{
+pthread_mutexattr_t attr;
+pthread_mutexattr_init(&attr);
+pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+pthread_mutex_init(&mutex, &attr);
+}
+//-----------------------------------------------------------------------------
+USERS::~USERS()
+{
+pthread_mutex_destroy(&mutex);
+}
+//-----------------------------------------------------------------------------
+int USERS::FindByNameNonLock(const string & login, user_iter * user) const
+{
+map<string, user_iter>::const_iterator iter;
+iter = loginIndex.find(login);
+if (iter != loginIndex.end())
+ {
+ if (user)
+ *user = iter->second;
+ return 0;
+ }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int USERS::FindByName(const string & login, user_iter * user) const
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+return FindByNameNonLock(login, user);
+}
+//-----------------------------------------------------------------------------
+bool USERS::TariffInUse(const string & tariffName)
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+list<USER>::iterator iter;
+iter = users.begin();
+while (iter != users.end())
+ {
+ if (iter->property.tariffName.Get() == tariffName)
+ return true;
+ ++iter;
+ }
+return false;
+}
+//-----------------------------------------------------------------------------
+int USERS::Add(const string & login, const ADMIN & admin)
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+const PRIV * priv = admin.GetPriv();
+
+if (!priv->userAddDel)
+ {
+ WriteServLog("%s tried to add user \'%s\'. Access denied.",
+ admin.GetLogStr().c_str(), login.c_str());
+ /*errorStr = "Admin \'" + admin.GetLogin() +
+ "\': tried to add user \'" + ud->login + "\'. Access denied.";*/
+ return -1;
+ }
+
+//////
+if (store->AddUser(login))
+ {
+ //TODO
+ //WriteServLog("Admin \'%s\': tried to add user \'%s\'. Access denied.",
+ // admin.GetLogin().c_str(), ud->login.c_str());
+ return -1;
+ }
+//////
+
+USER u(settings, store, tariffs, sysAdmin, &ipIndex);
+
+struct tm * tms;
+time_t t = stgTime;
+
+tms = localtime(&t);
+
+tms->tm_hour = 0;
+tms->tm_min = 0;
+tms->tm_sec = 0;
+
+if (settings->GetDayResetTraff() > tms->tm_mday)
+ tms->tm_mon -= 1;
+
+tms->tm_mday = settings->GetDayResetTraff();
+
+u.SetLogin(login);
+
+u.SetPassiveTimeAsNewUser();
+
+u.WriteConf();
+u.WriteStat();
+
+WriteServLog("%s User \'%s\' added.",
+ admin.GetLogStr().c_str(), login.c_str());
+
+u.OnAdd();
+
+users.push_front(u);
+
+AddUserIntoIndexes(users.begin());
+SetUserNotifiers(users.begin());
+
+// õ×ÅÄÏÍÌÑÅÍ ×ÓÅÈ ÖÅÌÁÀÝÉÈ, ÞÔÏ ÄÏÂÁ×ÌÅÎ ÎÏ×ÙÊ ÐÏÌØÚÏ×ÁÔÅÌØ
+set<NOTIFIER_BASE<user_iter> *>::iterator ni = onAddNotifiers.begin();
+while (ni != onAddNotifiers.end())
+ {
+ (*ni)->Notify(users.begin());
+ ++ni;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+void USERS::Del(const string & login, const ADMIN & admin)
+{
+const PRIV * priv = admin.GetPriv();
+user_iter u;
+
+if (!priv->userAddDel)
+ {
+ WriteServLog("%s tried to remove user \'%s\'. Access denied.",
+ admin.GetLogStr().c_str(), login.c_str());
+ return;
+ }
+
+
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+ if (FindByNameNonLock(login, &u))
+ {
+ WriteServLog("%s tried to delete user \'%s\': not found.",
+ admin.GetLogStr().c_str(),
+ login.c_str());
+ return;
+ }
+ }
+
+set<NOTIFIER_BASE<user_iter> *>::iterator ni = onDelNotifiers.begin();
+while (ni != onDelNotifiers.end())
+ {
+ (*ni)->Notify(u);
+ ++ni;
+ }
+
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+ u->OnDelete();
+ u->SetDeleted();
+
+ USER_TO_DEL utd;
+ utd.iter = u;
+ utd.delTime = stgTime;
+ usersToDelete.push_back(utd);
+
+ UnSetUserNotifiers(u);
+ DelUserFromIndexes(u);
+
+ WriteServLog("%s User \'%s\' deleted.",
+ admin.GetLogStr().c_str(), login.c_str());
+
+ }
+}
+//-----------------------------------------------------------------------------
+int USERS::ReadUsers()
+{
+vector<string> usersList;
+usersList.clear();
+if (store->GetUsersList(&usersList) < 0)
+ {
+ WriteServLog(store->GetStrError().c_str());
+ exit(1);
+ }
+
+user_iter ui;
+
+for (unsigned int i = 0; i < usersList.size(); i++)
+ {
+ USER u(settings, store, tariffs, sysAdmin, &ipIndex);
+
+ u.SetLogin(usersList[i]);
+ users.push_front(u);
+ ui = users.begin();
+
+ AddUserIntoIndexes(ui);
+ SetUserNotifiers(ui);
+
+ if (ui->ReadConf() < 0)
+ return -1;
+
+ if (ui->ReadStat() < 0)
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+void * USERS::Run(void * d)
+{
+printfd(__FILE__, "=====================| pid: %d |===================== \n", getpid());
+USERS * us = (USERS*) d;
+
+struct tm * t;
+time_t tt = stgTime;
+t = localtime(&tt);
+
+int min = t->tm_min;
+int day = t->tm_mday;
+
+printfd(__FILE__,"Day = %d Min = %d\n", day, min);
+
+time_t touchTime = stgTime - MONITOR_TIME_DELAY_SEC;
+string monFile = us->settings->GetMonitorDir() + "/users_r";
+printfd(__FILE__, "Monitor=%d file USERS %s\n", us->settings->GetMonitoring(), monFile.c_str());
+
+us->isRunning = true;
+while (us->nonstop)
+ {
+ //printfd(__FILE__,"New Minute. old = %02d current = %02d\n", min, t->tm_min);
+ //printfd(__FILE__,"New Day. old = %2d current = %2d\n", day, t->tm_mday);
+
+ for_each(us->users.begin(), us->users.end(), mem_fun_ref(&USER::Run));
+
+ tt = stgTime;
+ t = localtime(&tt);
+
+ if (min != t->tm_min)
+ {
+ printfd(__FILE__,"Sec = %d\n", stgTime);
+ printfd(__FILE__,"New Minute. old = %d current = %d\n", min, t->tm_min);
+ min = t->tm_min;
+
+ us->NewMinute(t);
+ }
+
+ t = localtime(&tt);
+ if (day != t->tm_mday)
+ {
+ printfd(__FILE__,"Sec = %d\n", stgTime);
+ printfd(__FILE__,"New Day. old = %d current = %d\n", day, t->tm_mday);
+ day = t->tm_mday;
+ us->NewDay(t);
+ }
+
+ if (us->settings->GetMonitoring() && (touchTime + MONITOR_TIME_DELAY_SEC <= stgTime))
+ {
+ //printfd(__FILE__, "Monitor=%d file TRAFFCOUNTER %s\n", tc->monitoring, monFile.c_str());
+ touchTime = stgTime;
+ TouchFile(monFile.c_str());
+ }
+
+ stgUsleep(100000);
+ } //while (us->nonstop)
+
+user_iter ui = us->users.begin();
+while (ui != us->users.end())
+ {
+ us->UnSetUserNotifiers(ui);
+ us->DelUserFromIndexes(ui);
+ ui++;
+ }
+
+list<USER_TO_DEL>::iterator iter;
+iter = us->usersToDelete.begin();
+while (iter != us->usersToDelete.end())
+ {
+ iter->delTime -= 2 * userDeleteDelayTime;
+ ++iter;
+ }
+us->RealDelUser();
+
+us->isRunning = false;
+
+return NULL;
+}
+//-----------------------------------------------------------------------------
+void USERS::NewMinute(const struct tm * t)
+{
+int usersCnt = 0;
+list<USER>::iterator usr;
+
+//Write traff, reset session traff. Fake disconnect-connect
+if (t->tm_hour == 23 && t->tm_min == 59)
+ {
+ printfd(__FILE__,"MidnightResetSessionStat\n");
+ for_each(users.begin(), users.end(), mem_fun_ref(&USER::MidnightResetSessionStat));
+ }
+
+if (TimeToWriteDetailStat(t))
+ {
+ //printfd(__FILE__, "USER::WriteInetStat\n");
+ for_each(users.begin(), users.end(), mem_fun_ref(&USER::SwapDetailStat));
+ usersCnt = 0;
+
+ // ðÉÛÅÍ ÀÚÅÒÏ× ÞÁÓÔÑÍÉ. ÷ ÐÅÒÅÒÙ×ÁÈ ×ÙÚÙ×ÁÅÍ USER::Run
+ usr = users.begin();
+ while (usr != users.end())
+ {
+ usersCnt++;
+ usr->WriteDetailStat();
+ usr++;
+ if (usersCnt % 10 == 0)
+ for_each(users.begin(), users.end(), mem_fun_ref(&USER::Run));
+ }
+
+ for_each(users.begin(), users.end(), mem_fun_ref(&USER::ResetDetailStat));
+ }
+
+RealDelUser();
+}
+//-----------------------------------------------------------------------------
+void USERS::NewDay(const struct tm * t)
+{
+struct tm * t1;
+time_t tt = stgTime;
+t1 = localtime(&tt);
+int dayFee = settings->GetDayFee();
+
+if (dayFee == 0)
+ dayFee = DaysInCurrentMonth();
+
+printfd(__FILE__, "DayFee = %d\n", dayFee);
+printfd(__FILE__, "Today = %d DayResetTraff = %d\n", t1->tm_mday, settings->GetDayResetTraff());
+printfd(__FILE__, "DayFeeIsLastDay = %d\n", settings->GetDayFeeIsLastDay());
+
+if (!settings->GetDayFeeIsLastDay())
+ {
+ printfd(__FILE__, "DayResetTraff - 1 -\n");
+ DayResetTraff(t1);
+ //printfd(__FILE__, "DayResetTraff - 1 - 1 -\n");
+ }
+
+if (settings->GetSpreadFee())
+ {
+ printfd(__FILE__, "Spread DayFee\n");
+ for_each(users.begin(), users.end(), mem_fun_ref(&USER::ProcessDayFeeSpread));
+ }
+else
+ {
+ if (t->tm_mday == dayFee)
+ {
+ printfd(__FILE__, "DayFee\n");
+ for_each(users.begin(), users.end(), mem_fun_ref(&USER::ProcessDayFee));
+ }
+ }
+
+if (settings->GetDayFeeIsLastDay())
+ {
+ printfd(__FILE__, "DayResetTraff - 2 -\n");
+ DayResetTraff(t1);
+ }
+}
+//-----------------------------------------------------------------------------
+void USERS::DayResetTraff(const struct tm * t1)
+{
+int dayResetTraff = settings->GetDayResetTraff();
+if (dayResetTraff == 0)
+ dayResetTraff = DaysInCurrentMonth();
+if (t1->tm_mday == dayResetTraff)
+ {
+ printfd(__FILE__, "ResetTraff\n");
+ for_each(users.begin(), users.end(), mem_fun_ref(&USER::ProcessNewMonth));
+ for_each(users.begin(), users.end(), mem_fun_ref(&USER::SetPrepaidTraff));
+ }
+}
+//-----------------------------------------------------------------------------
+int USERS::Start()
+{
+if (ReadUsers())
+ {
+ WriteServLog("USERS: Error: Cannot read users!");
+ return -1;
+ }
+
+nonstop = true;
+if (pthread_create(&thread, NULL, Run, this))
+ {
+ WriteServLog("USERS: Error: Cannot start thread!");
+ return -1;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int USERS::Stop()
+{
+printfd(__FILE__, "USERS::Stop()\n");
+
+if (!isRunning)
+ {
+ //printfd(__FILE__, "Alredy stopped\n");
+ return 0;
+ }
+
+nonstop = false;
+
+//5 seconds to thread stops itself
+unsigned i;
+for (i = 0; i < 25 * (users.size() / 50 + 1); i++)
+ {
+ if (!isRunning)
+ break;
+
+ usleep(200000);
+ }
+
+//after 5 seconds waiting thread still running. now kill it
+if (isRunning)
+ {
+ printfd(__FILE__, "kill USERS thread.\n");
+ //TODO pthread_cancel()
+ if (pthread_kill(thread, SIGINT))
+ {
+ //errorStr = "Cannot kill USERS thread.";
+ //printfd(__FILE__, "Cannot kill USERS thread.\n");
+ //return 0;
+ }
+ printfd(__FILE__, "USERS killed\n");
+ }
+
+printfd(__FILE__, "Before USERS::Run()\n");
+for_each(users.begin(), users.end(), mem_fun_ref(&USER::Run));
+for_each(users.begin(), users.end(), mem_fun_ref(&USER::SwapDetailStat));
+for_each(users.begin(), users.end(), mem_fun_ref(&USER::WriteDetailStat));
+for_each(users.begin(), users.end(), mem_fun_ref(&USER::WriteStat));
+for_each(users.begin(), users.end(), mem_fun_ref(&USER::WriteConf));
+
+printfd(__FILE__, "USERS::Stop()\n");
+return 0;
+}
+//-----------------------------------------------------------------------------
+void USERS::RealDelUser()
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+printfd(__FILE__, "RealDelUser() users to del: %d\n", usersToDelete.size());
+
+list<USER_TO_DEL>::iterator iter;
+iter = usersToDelete.begin();
+while (iter != usersToDelete.end())
+ {
+ printfd(__FILE__, "RealDelUser() user=%s\n", iter->iter->GetLogin().c_str());
+ if (iter->delTime + userDeleteDelayTime < stgTime)
+ {
+ printfd(__FILE__, "RealDelUser() user=%s removed from DB\n", iter->iter->GetLogin().c_str());
+ if (store->DelUser(iter->iter->GetLogin()))
+ {
+ WriteServLog("Error removing user \'%s\' from database.", iter->iter->GetLogin().c_str());
+ }
+ users.erase(iter->iter);
+ usersToDelete.erase(iter++);
+ }
+ else
+ {
+ ++iter;
+ }
+ }
+return;
+}
+//-----------------------------------------------------------------------------
+int USERS::GetUserNum()
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+return users.size();
+}
+//-----------------------------------------------------------------------------
+void USERS::AddToIPIdx(user_iter user)
+{
+printfd(__FILE__, "USERS: Add IP Idx\n");
+uint32_t ip = user->GetCurrIP();
+//assert(ip && "User has non-null ip");
+if (!ip)
+ return; // User has disconnected
+
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+const map<uint32_t, user_iter>::iterator it(
+ ipIndex.lower_bound(ip)
+);
+
+assert((it == ipIndex.end() || it->first != ip) && "User is not in index");
+
+ipIndex.insert(it, std::make_pair(ip, user));
+}
+//-----------------------------------------------------------------------------
+void USERS::DelFromIPIdx(uint32_t ip)
+{
+printfd(__FILE__, "USERS: Del IP Idx\n");
+assert(ip && "User has non-null ip");
+
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+const map<uint32_t, user_iter>::iterator it(
+ ipIndex.find(ip)
+);
+
+//assert(it != ipIndex.end() && "User is in index");
+if (it == ipIndex.end())
+ return; // User has not been added
+
+ipIndex.erase(it);
+}
+//-----------------------------------------------------------------------------
+int USERS::FindByIPIdx(uint32_t ip, user_iter * usr)
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+map<uint32_t, user_iter>::iterator it;
+it = ipIndex.find(ip);
+
+if (it == ipIndex.end())
+ {
+ //printfd(__FILE__, "User NOT found in IP_Index!!!\n");
+ return -1;
+ }
+*usr = it->second;
+//printfd(__FILE__, "User found in IP_Index\n");
+return 0;
+}
+//-----------------------------------------------------------------------------
+void USERS::AddNotifierUserAdd(NOTIFIER_BASE<user_iter> * n)
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+onAddNotifiers.insert(n);
+}
+//-----------------------------------------------------------------------------
+void USERS::DelNotifierUserAdd(NOTIFIER_BASE<user_iter> * n)
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+//printfd(__FILE__, "DelNotifierUserAdd\n");
+onAddNotifiers.erase(n);
+}
+//-----------------------------------------------------------------------------
+void USERS::AddNotifierUserDel(NOTIFIER_BASE<user_iter> * n)
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+onDelNotifiers.insert(n);
+}
+//-----------------------------------------------------------------------------
+void USERS::DelNotifierUserDel(NOTIFIER_BASE<user_iter> * n)
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+onDelNotifiers.erase(n);
+}
+//-----------------------------------------------------------------------------
+int USERS::OpenSearch()
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+handle++;
+searchDescriptors[handle] = users.begin();
+return handle;
+}
+//-----------------------------------------------------------------------------
+int USERS::SearchNext(int h, user_iter * u)
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+if (searchDescriptors.find(h) == searchDescriptors.end())
+ {
+ WriteServLog("USERS. Incorrect search handle.");
+ return -1;
+ }
+
+if (searchDescriptors[h] == users.end())
+ return -1;
+
+while (searchDescriptors[h]->GetDeleted())
+ {
+ ++searchDescriptors[h];
+ if (searchDescriptors[h] == users.end())
+ {
+ return -1;
+ }
+ }
+
+*u = searchDescriptors[h];
+
+++searchDescriptors[h];
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int USERS::CloseSearch(int h)
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+if (searchDescriptors.find(h) != searchDescriptors.end())
+ {
+ searchDescriptors.erase(searchDescriptors.find(h));
+ return 0;
+ }
+
+WriteServLog("USERS. Incorrect search handle.");
+return -1;
+}
+//-----------------------------------------------------------------------------
+void USERS::SetUserNotifiers(user_iter user)
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+PROPERTY_NOTIFER_IP_BEFORE nb(*this, user);
+PROPERTY_NOTIFER_IP_AFTER na(*this, user);
+
+userIPNotifiersBefore.push_front(nb);
+userIPNotifiersAfter.push_front(na);
+
+user->AddCurrIPBeforeNotifier(&(*userIPNotifiersBefore.begin()));
+user->AddCurrIPAfterNotifier(&(*userIPNotifiersAfter.begin()));
+}
+//-----------------------------------------------------------------------------
+void USERS::UnSetUserNotifiers(user_iter user)
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+list<PROPERTY_NOTIFER_IP_BEFORE>::iterator bi;
+list<PROPERTY_NOTIFER_IP_AFTER>::iterator ai;
+
+bi = userIPNotifiersBefore.begin();
+while (bi != userIPNotifiersBefore.end())
+ {
+ if (bi->GetUser() == user)
+ {
+ bi->GetUser()->DelCurrIPBeforeNotifier(&(*bi));
+ userIPNotifiersBefore.erase(bi);
+ //printfd(__FILE__, "Notifier Before removed. User %s\n", bi->GetUser()->GetLogin().c_str());
+ break;
+ }
+ bi++;
+ }
+
+ai = userIPNotifiersAfter.begin();
+while (ai != userIPNotifiersAfter.end())
+ {
+ if (ai->GetUser() == user)
+ {
+ ai->GetUser()->DelCurrIPAfterNotifier(&(*ai));
+ userIPNotifiersAfter.erase(ai);
+ //printfd(__FILE__, "Notifier After removed. User %s\n", ai->GetUser()->GetLogin().c_str());
+ break;
+ }
+ ai++;
+ }
+}
+//-----------------------------------------------------------------------------
+void USERS::AddUserIntoIndexes(user_iter user)
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+loginIndex.insert(pair<string, user_iter>(user->GetLogin(), user));
+}
+//-----------------------------------------------------------------------------
+void USERS::DelUserFromIndexes(user_iter user)
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+loginIndex.erase(user->GetLogin());
+}
+//-----------------------------------------------------------------------------
+bool USERS::TimeToWriteDetailStat(const struct tm * t)
+{
+int statTime = settings->GetDetailStatWritePeriod();
+
+switch (statTime)
+ {
+ case dsPeriod_1:
+ if (t->tm_min == 0)
+ return true;
+ break;
+ case dsPeriod_1_2:
+ if (t->tm_min % 30 == 0)
+ return true;
+ break;
+ case dsPeriod_1_4:
+ if (t->tm_min % 15 == 0)
+ return true;
+ break;
+ case dsPeriod_1_6:
+ if (t->tm_min % 10 == 0)
+ return true;
+ break;
+ }
+return false;
+}
+//-----------------------------------------------------------------------------
+/*int USERS::SendMessage(const string & login,
+ time_t sndTtime,
+ time_t showTime,
+ char type,
+ const string & text) const
+{
+return 0;
+}*/
+//-----------------------------------------------------------------------------
+
+
+
--- /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>
+ */
+
+/*
+$Revision: 1.31 $
+$Date: 2010/10/07 20:04:48 $
+$Author: faust $
+*/
+
+
+#ifndef USERS_H
+#define USERS_H
+
+#include <pthread.h>
+#include <ctime>
+#include <string>
+#include <map>
+#include <list>
+#include <set>
+
+#include "os_int.h"
+
+#include "settings.h"
+#include "user.h"
+#include "tariffs.h"
+#include "stg_logger.h"
+#include "notifer.h"
+#include "actions.h"
+#include "noncopyable.h"
+#include "eventloop.h"
+
+const int userDeleteDelayTime = 120;
+
+using namespace std;
+class USERS;
+//-----------------------------------------------------------------------------
+class PROPERTY_NOTIFER_IP_BEFORE: public PROPERTY_NOTIFIER_BASE<uint32_t>
+{
+public:
+ PROPERTY_NOTIFER_IP_BEFORE(USERS & us, user_iter u) : users(us), user(u) {};
+ void Notify(const uint32_t & oldValue, const uint32_t & newValue);
+ user_iter GetUser() { return user; };
+private:
+ USERS & users;
+ user_iter user;
+};
+//-----------------------------------------------------------------------------
+class PROPERTY_NOTIFER_IP_AFTER: public PROPERTY_NOTIFIER_BASE<uint32_t>
+{
+public:
+ PROPERTY_NOTIFER_IP_AFTER(USERS & us, user_iter u) : users(us), user(u) {};
+ void Notify(const uint32_t & oldValue, const uint32_t & newValue);
+ user_iter GetUser() { return user; };
+private:
+ USERS & users;
+ user_iter user;
+};
+//-----------------------------------------------------------------------------
+struct USER_TO_DEL
+{
+USER_TO_DEL()
+ : iter(),
+ delTime(0)
+{};
+
+list<USER>::iterator iter;
+time_t delTime;
+};
+//-----------------------------------------------------------------------------
+class USERS : private NONCOPYABLE
+ {
+ friend class PROPERTY_NOTIFER_IP_BEFORE;
+ friend class PROPERTY_NOTIFER_IP_AFTER;
+
+public:
+ USERS(SETTINGS * s, BASE_STORE * store, TARIFFS * tariffs, const ADMIN & sysAdmin);
+ ~USERS();
+
+ int FindByName(const string & login, user_iter * user) const;
+ int FindByID(int id, user_iter * user);
+
+ bool TariffInUse(const string & tariffName);
+
+ void AddNotifierUserAdd(NOTIFIER_BASE<user_iter> *);
+ void DelNotifierUserAdd(NOTIFIER_BASE<user_iter> *);
+
+ void AddNotifierUserDel(NOTIFIER_BASE<user_iter> *);
+ void DelNotifierUserDel(NOTIFIER_BASE<user_iter> *);
+
+ int Add(const string & login, const ADMIN & admin);
+ void Del(const string & login, const ADMIN & admin);
+
+ int ReadUsers();
+ int GetUserNum();
+
+ int FindByIPIdx(uint32_t ip, user_iter * user);
+
+ int OpenSearch();
+ int SearchNext(int handler, user_iter * u);
+ int CloseSearch(int handler);
+
+ int Start();
+ int Stop();
+
+ int SendMessage(const string & login, time_t sndTtime, time_t showTime, char type, const string & text) const;
+
+private:
+ void AddToIPIdx(user_iter);
+ void DelFromIPIdx(uint32_t ip);
+
+ int FindByNameNonLock(const string & login, user_iter * user) const;
+ int FindByIDNonLock(int id, user_iter * user);
+
+ void RealDelUser();
+ void ProcessActions();
+
+ void SetUserNotifiers(user_iter user);
+ void UnSetUserNotifiers(user_iter user);
+
+ void AddUserIntoIndexes(user_iter user);
+ void DelUserFromIndexes(user_iter user);
+
+ static void * Run(void *);
+ void NewMinute(const struct tm * t);
+ void NewDay(const struct tm * t);
+ void DayResetTraff(const struct tm * t);
+
+ bool TimeToWriteDetailStat(const struct tm * t);
+
+ list<USER> users;
+ list<USER_TO_DEL> usersToDelete;
+ list<PROPERTY_NOTIFER_IP_BEFORE> userIPNotifiersBefore;
+ list<PROPERTY_NOTIFER_IP_AFTER> userIPNotifiersAfter;
+
+ map<uint32_t, user_iter> ipIndex;
+ map<string, user_iter> loginIndex;
+
+ SETTINGS * settings;
+ TARIFFS * tariffs;
+ BASE_STORE * store;
+ const ADMIN sysAdmin;
+ STG_LOGGER & WriteServLog;
+
+ bool nonstop;
+ bool isRunning;
+
+ mutable pthread_mutex_t mutex;
+ pthread_t thread;
+ mutable unsigned int handle;
+
+ mutable map<int, user_iter> searchDescriptors;
+
+ set <NOTIFIER_BASE<user_iter>*> onAddNotifiers;
+ set <NOTIFIER_BASE<user_iter>*> onDelNotifiers;
+ };
+//-----------------------------------------------------------------------------
+inline
+void PROPERTY_NOTIFER_IP_BEFORE::Notify(const uint32_t & oldValue,
+ const uint32_t &)
+{
+if (!oldValue)
+ return;
+
+//EVENT_LOOP_SINGLETON::GetInstance().Enqueue(users, &USERS::DelFromIPIdx, oldValue);
+// Using explicit call to assure that index is valid, because fast reconnect with delayed call can result in authorization error
+users.DelFromIPIdx(oldValue);
+}
+//-----------------------------------------------------------------------------
+inline
+void PROPERTY_NOTIFER_IP_AFTER::Notify(const uint32_t &,
+ const uint32_t & newValue)
+{
+if (!newValue)
+ return;
+
+//EVENT_LOOP_SINGLETON::GetInstance().Enqueue(users, &USERS::AddToIPIdx, user);
+// Using explicit call to assure that index is valid, because fast reconnect with delayed call can result in authorization error
+users.AddToIPIdx(user);
+}
+//-----------------------------------------------------------------------------
+#endif
+
--- /dev/null
+include make.conf
+
+CFLAGS += -g3 -W -Wall -pedantic
+CFLAGS += $(DEFINES) -D_BSD_SOURCE
+
+CXXFLAGS += $(CFLAGS)
+
+SOURCES=logger.cpp lock.cpp traffcounter.cpp rules.cpp utils.cpp
+RULES_TESTER_SOURCES=logger.cpp rules.cpp utils.cpp rules_tester.cpp
+RULES_FINDER_TESTER_SOURCES=logger.cpp lock.cpp rules.cpp rules_finder.cpp utils.cpp rf_tester.cpp
+TC_TESTER_SOURCES=logger.cpp rules.cpp rules_finder.cpp utils.cpp traffcounter.cpp lock.cpp tc_tester.cpp
+LIBS=-lpthread
+PROG=st_core
+
+.PHONY: all tests clean
+
+#all: $(PROG)
+all: tests
+
+$(PROG): $(subst .cpp,.o,$(SOURCES))
+ $(CXX) $^ $(LDFLAGS) $(LIBS) -o $@
+
+tests: rules_tester rf_tester tc_tester
+
+rules_tester: $(subst .cpp,.o,$(RULES_TESTER_SOURCES))
+ $(CXX) $^ $(LDFLAGS) -o $@
+
+rf_tester: $(subst .cpp,.o,$(RULES_FINDER_TESTER_SOURCES))
+ $(CXX) $^ $(LDFLAGS) -o $@
+
+tc_tester: $(subst .cpp,.o,$(TC_TESTER_SOURCES))
+ $(CXX) $^ $(LDFLAGS) $(LIBS) -o $@
+
+clean:
+ rm -f $(PROG) *.o *d rules_tester rf_tester tc_tester gmon.out
+
+ifneq ($(MAKECMDGOALS),distclean)
+ifneq ($(MAKECMDGOALS),clean)
+ifneq ($(MAKECMDGOALS),uninstall)
+-include $(subst .cpp,.d,$(SOURCES))
+endif
+endif
+endif
+
+%.d: %.cpp
+ @$(CC) -MM $(CFLAGS) $< > $@.$$$$; \
+ sed 's,\($*\).o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
+ rm -f $@.$$$$
--- /dev/null
+#ifndef __CAPTURER_TC_IFACE_H__
+#define __CAPTURER_TC_IFACE_H__
+
+#ifdef HAVE_STDINT
+ #include <stdint.h>
+#else
+ #ifdef HAVE_INTTYPES
+ #include <inttypes.h>
+ #else
+ #error "You need either stdint.h or inttypes.h to compile this!"
+ #endif
+#endif
+
+namespace STG
+{
+
+ class ICAPTURER_TC
+ {
+ public:
+ virtual ~ICAPTURER_TC() {};
+ virtual void AddPacket(const iphdr &, uint16_t, uint16_t) = 0;
+ };
+
+}
+
+#endif
--- /dev/null
+#!/bin/sh
+
+echo -n "checking os type... "
+OS=`uname`
+echo $OS
+
+echo -n "checking stdint.h... "
+if [ -f /usr/include/stdint.h ]
+then
+ DEFINES="$DEFINES -DHAVE_STDINT"
+ echo "ok"
+else
+ echo "fail"
+
+ echo -n "checking inttypes.h... "
+ if [ -f /usr/include/inttypes.h ]
+ then
+ DEFINES="$DEFINES -DHAVE_INTTYPES"
+ echo "ok"
+ else
+ echo "fail"
+ echo "You need either stdint.h or inttypes.h to compile this"
+ exit 1
+ fi
+fi
+
+if [ "$OS"=="Linux" ]
+then
+ DEFINES="$DEFINES -DLINUX"
+ echo -n "checking gmake... "
+ gmake --version > /dev/null 2> /dev/null
+ if [ $? -eq 0 ]
+ then
+ MAKE="gmake"
+ echo "ok"
+ else
+ echo "fail"
+ echo -n "checking make... "
+ make --version > /dev/null 2> /dev/null
+ if [ $? -eq 0 ]
+ then
+ echo "ok"
+ MAKE="make"
+ else
+ echo "fail"
+ echo "You need a GNU Make to compile this"
+ exit 1
+ fi
+ fi
+else
+ if [ "$OS"=="FreeBSD" ]
+ then
+ DEFINES="$DEFINES -DFREEBSD"
+ echo -n "checking gmake... "
+ gmake --version > /dev/null 2> /dev/null
+ if [ $? -eq 0 ]
+ then
+ echo "ok"
+ MAKE="gmake"
+ else
+ echo "fail"
+ echo "You need a GNU Make to use this"
+ exit 1
+ fi
+ else
+ echo "This version of software is only compatible with Linux and FreeBSD"
+ exit 1
+ fi
+fi
+
+echo "Configuration successfull. Details:"
+echo -e "\tOS: $OS"
+echo -e "\tGNU Make utility: $MAKE"
+echo -e "\nType $MAKE and $MAKE install now"
+
+rm -f make.conf
+echo "OS = $OS" >> make.conf
+echo "DEFINES = $DEFINES" >> make.conf
--- /dev/null
+#include <cerrno>
+
+#include <pthread.h>
+
+#include "lock.h"
+
+
+SCOPED_LOCK::SCOPED_LOCK(pthread_mutex_t & mtx)
+ : mutex(mtx)
+{
+pthread_mutex_lock(&mutex);
+}
+
+SCOPED_LOCK::~SCOPED_LOCK()
+{
+pthread_mutex_unlock(&mutex);
+}
--- /dev/null
+#ifndef __SCOPED_LOCK_H__
+#define __SCOPED_LOCK_H__
+
+#include <pthread.h>
+
+class SCOPED_LOCK
+{
+public:
+ SCOPED_LOCK(pthread_mutex_t & mtx);
+ ~SCOPED_LOCK();
+private:
+ pthread_mutex_t & mutex;
+
+ SCOPED_LOCK(const SCOPED_LOCK & lock) : mutex(lock.mutex) {};
+};
+
+#endif
--- /dev/null
+#include <string>
+#include <sstream>
+
+#include <ctime>
+
+#include "logger.h"
+
+using namespace std;
+
+STGLogger::~STGLogger()
+{
+}
+
+ostream & STGLogger::operator <<(const string & val)
+{
+ LogDate();
+ out << " " << val;
+ return out;
+}
+
+void STGLogger::LogDate()
+{
+ time_t t(time(NULL));
+ struct tm * tt = localtime(&t);
+ out << "[" << tt->tm_year + 1900 << "-";
+ out << (tt->tm_mon + 1 < 10 ? "0" : "") << tt->tm_mon + 1 << "-";
+ out << (tt->tm_mday < 10 ? "0" : "") << tt->tm_mday << " ";
+ out << (tt->tm_hour < 10 ? "0" : "") << tt->tm_hour << ":";
+ out << (tt->tm_min < 10 ? "0" : "") << tt->tm_min << ":";
+ out << (tt->tm_sec < 10 ? "0" : "") << tt->tm_sec << "]";
+}
--- /dev/null
+#ifndef __LOGGER_H__
+#define __LOGGER_H__
+
+#include <iostream>
+#include <string>
+
+#define LOG_IT (log << __FILE__ << ":" << __LINE__ << " ")
+
+class STGLogger {
+public:
+ STGLogger() : out(std::cout) {};
+ STGLogger(std::ostream & stream) : out(stream) {};
+ ~STGLogger();
+
+ std::ostream &operator <<(const std::string & val);
+private:
+ void LogDate();
+ std::ostream & out;
+};
+
+extern STGLogger log;
+
+#endif
--- /dev/null
+/*
+ * Network:
+ * - server: 192.168.0.1
+ * - user A: 192.168.0.2
+ * - user B: 192.168.0.3
+ *
+ * External resources:
+ * - host 1: 216.239.59.104
+ * - host 2: 72.14.221.104
+ * - host 3: 66.249.93.104
+ * - host 4: 195.5.61.68
+ *
+ * Directions:
+ * - Local: ALL 192.168.0.0/24
+ * - DNS: TCP_UDP 195.5.61.68/32:53
+ * - FTP: TCP 129.22.8.159/32:20-21
+ * - World: ALL 0.0.0.0/0
+ *
+ */
+
+#include <cstdlib>
+#include <iostream>
+#include <string>
+#include <vector>
+#include <algorithm>
+
+#include <arpa/inet.h>
+
+#include "rules.h"
+#include "rules_finder.h"
+#include "logger.h"
+
+using namespace std;
+using namespace STG;
+
+STGLogger log;
+
+RULE MakeRule(const std::string & ip,
+ const std::string & mask,
+ uint16_t port1,
+ uint16_t port2,
+ int proto,
+ int dir)
+{
+ RULE rule;
+
+ rule.ip = inet_addr(ip.c_str());
+ rule.mask = inet_addr(mask.c_str());
+ rule.port1 = port1;
+ rule.port2 = port2;
+ rule.proto = proto;
+ rule.dir = dir;
+
+ return rule;
+}
+
+RULES PrepareRules()
+{
+ RULES rules;
+ RULE local(MakeRule("192.168.0.0",
+ "255.255.255.0",
+ 0,
+ 65535,
+ -1,
+ 0));
+ RULE dns(MakeRule("195.5.61.68",
+ "255.255.255.255",
+ 53,
+ 53,
+ -1,
+ 1));
+ RULE ftp(MakeRule("129.22.8.159",
+ "255.255.255.255",
+ 20,
+ 21,
+ -1,
+ 2));
+ RULE world(MakeRule("0.0.0.0",
+ "0.0.0.0",
+ 0,
+ 65535,
+ -1,
+ 3));
+
+ rules.push_back(local);
+
+ rules.push_back(dns);
+
+ rules.push_back(ftp);
+
+ rules.push_back(world);
+
+ return rules;
+}
+
+PENDING_PACKET MakePacket(const std::string & from,
+ const std::string & to,
+ uint16_t sport,
+ uint16_t dport,
+ int proto,
+ PENDING_PACKET::DIRECTION direction,
+ int length)
+{
+ iphdr hdr;
+
+ hdr.ihl = 5;
+ hdr.version = 4;
+ hdr.tos = 0;
+ hdr.tot_len = length;
+ hdr.id = 0;
+ hdr.frag_off = 50;
+ hdr.ttl = 64;
+ hdr.protocol = proto;
+ hdr.check = 0;
+ hdr.saddr = inet_addr(from.c_str());
+ hdr.daddr = inet_addr(to.c_str());
+
+ PENDING_PACKET packet(hdr, sport, dport);
+
+ packet.direction = direction;
+
+ return packet;
+}
+
+struct TEST_INFO {
+ int wantedDir;
+ int actualDir; // Parser error status
+ bool stdException; // Parser throws an std execption
+ bool otherException; // Parser throws another exception
+ bool result;
+};
+
+struct RF_TESTER : public std::unary_function<std::pair<PENDING_PACKET, int>, void>
+{
+public:
+ RF_TESTER(RULES_FINDER & r)
+ : rf(r),
+ testLog(),
+ result(true)
+ {
+ };
+ ~RF_TESTER()
+ {
+ PrintLog();
+ if (result)
+ exit(EXIT_SUCCESS);
+ exit(EXIT_FAILURE);
+ }
+ void operator()(const std::pair<PENDING_PACKET, int> & entry)
+ {
+ TEST_INFO info;
+ info.wantedDir = entry.second;
+ info.actualDir = -1;
+ info.stdException = false;
+ info.otherException = false;
+ info.result = true;
+ try
+ {
+ info.actualDir = rf.GetDir(entry.first);
+ }
+ catch (std::exception & ex)
+ {
+ info.stdException = true;
+ info.result = false;
+ }
+ catch (...)
+ {
+ info.otherException = true;
+ info.result = false;
+ }
+ info.result &= (info.actualDir == info.wantedDir);
+ result &= info.result;
+ testLog.push_back(info);
+ };
+
+ void PrintLog()
+ {
+ int testNumber = 1;
+ std::cout << "RF_TESTER results:\n";
+ std::cout << "-----------------------------------------------------------------\n";
+ std::vector<TEST_INFO>::const_iterator it;
+ for (it = testLog.begin(); it != testLog.end(); ++it)
+ {
+ std::cout << "Test no.: " << testNumber++ << "\t"
+ << "Correct dir: " << it->wantedDir << "\t"
+ << "Actual dir:" << it->actualDir << "\t"
+ << "STD exceptions: " << it->stdException << "\t"
+ << "Other exceptions: " << it->otherException << "\t"
+ << "Result: " << it->result << "\n";
+ }
+ std::cout << "-----------------------------------------------------------------\n";
+ std::cout << "Final result: " << (result ? "passed" : "failed") << std::endl;
+ }
+
+ bool Result() const { return result; };
+private:
+ RULES_FINDER & rf;
+ std::vector<TEST_INFO> testLog;
+ bool result;
+};
+
+int main()
+{
+ RULES rules(PrepareRules());
+ RULES_FINDER rf;
+
+ rf.SetRules(rules);
+
+ std::list<std::pair<PENDING_PACKET, int> > tests;
+
+ // Local, SSH
+ tests.push_back(make_pair(MakePacket("192.168.0.2", "192.168.0.1", 3214, 22, 6, PENDING_PACKET::OUTGOING, 0), 0));
+ tests.push_back(make_pair(MakePacket("192.168.0.1", "192.168.0.2", 22, 3214, 6, PENDING_PACKET::OUTGOING, 0), 0));
+ // Local, SSH, incorrect direction detection
+ tests.push_back(make_pair(MakePacket("192.168.0.2", "192.168.0.1", 3214, 22, 6, PENDING_PACKET::INCOMING, 0), 0));
+ tests.push_back(make_pair(MakePacket("192.168.0.1", "192.168.0.2", 22, 3214, 6, PENDING_PACKET::INCOMING, 0), 0));
+ // Local, FTP
+ tests.push_back(make_pair(MakePacket("192.168.0.2", "192.168.0.1", 3214, 20, 6, PENDING_PACKET::OUTGOING, 0), 0));
+ tests.push_back(make_pair(MakePacket("192.168.0.1", "192.168.0.2", 21, 3214, 6, PENDING_PACKET::OUTGOING, 0), 0));
+ // Local, DNS
+ tests.push_back(make_pair(MakePacket("192.168.0.2", "192.168.0.1", 3214, 53, 6, PENDING_PACKET::OUTGOING, 0), 0));
+ tests.push_back(make_pair(MakePacket("192.168.0.1", "192.168.0.2", 53, 3214, 6, PENDING_PACKET::OUTGOING, 0), 0));
+ // Known DNS, DNS
+ tests.push_back(make_pair(MakePacket("192.168.0.2", "195.5.61.68", 3210, 53, 6, PENDING_PACKET::OUTGOING, 0), 1));
+ tests.push_back(make_pair(MakePacket("195.5.61.68", "192.168.0.2", 53, 3210, 6, PENDING_PACKET::INCOMING, 0), 1));
+ // Known DNS, invalid ports
+ tests.push_back(make_pair(MakePacket("192.168.0.2", "195.5.61.68", 3210, 54, 6, PENDING_PACKET::OUTGOING, 0), 3));
+ tests.push_back(make_pair(MakePacket("195.5.61.68", "192.168.0.2", 20, 3210, 6, PENDING_PACKET::INCOMING, 0), 3));
+ // Known FTP, FTP
+ tests.push_back(make_pair(MakePacket("192.168.0.2", "129.22.8.159", 3241, 20, 6, PENDING_PACKET::OUTGOING, 0), 2));
+ tests.push_back(make_pair(MakePacket("129.22.8.159", "192.168.0.2", 21, 3241, 6, PENDING_PACKET::INCOMING, 0), 2));
+ // Known FTP, invalid ports
+ tests.push_back(make_pair(MakePacket("192.168.0.2", "129.22.8.159", 3241, 53, 6, PENDING_PACKET::OUTGOING, 0), 3));
+ tests.push_back(make_pair(MakePacket("129.22.8.159", "192.168.0.2", 22, 3241, 6, PENDING_PACKET::INCOMING, 0), 3));
+
+ std::for_each(tests.begin(),
+ tests.end(),
+ RF_TESTER(rf));
+
+ return EXIT_SUCCESS;
+}
--- /dev/null
+ALL 62.16.0.0/19 DIR0
+ALL 62.64.64.0/18 DIR0
+ALL 62.72.160.0/19 DIR0
+ALL 62.80.160.0/19 DIR0
+ALL 62.149.0.0/19 DIR0
+ALL 62.176.0.0/21 DIR0
+ALL 62.182.80.0/21 DIR0
+ALL 62.182.120.0/21 DIR0
+ALL 62.182.152.0/21 DIR0
+ALL 62.182.160.0/21 DIR0
+ALL 62.205.128.0/19 DIR0
+ALL 62.216.32.0/21 DIR0
+ALL 62.221.32.0/22 DIR0
+ALL 62.221.37.0/24 DIR0
+ALL 62.221.38.0/23 DIR0
+ALL 62.221.40.0/21 DIR0
+ALL 62.221.48.0/20 DIR0
+ALL 62.221.64.0/19 DIR0
+ALL 62.244.0.0/18 DIR0
+ALL 64.18.0.0/20 DIR0
+ALL 64.233.160.0/19 DIR0
+ALL 66.102.0.0/20 DIR0
+ALL 66.249.64.0/19 DIR0
+ALL 72.14.192.0/18 DIR0
+ALL 74.125.0.0/16 DIR0
+ALL 77.47.128.0/17 DIR0
+ALL 77.52.0.0/16 DIR0
+ALL 77.73.88.0/21 DIR0
+ALL 77.75.144.0/21 DIR0
+ALL 77.75.156.0/24 DIR0
+ALL 77.87.32.0/21 DIR0
+ALL 77.87.144.0/20 DIR0
+ALL 77.87.192.0/21 DIR0
+ALL 77.88.0.0/18 DIR0
+ALL 77.88.192.0/18 DIR0
+ALL 77.90.192.0/18 DIR0
+ALL 77.91.128.0/18 DIR0
+ALL 77.93.32.0/20 DIR0
+ALL 77.93.48.0/22 DIR0
+ALL 77.94.160.0/19 DIR0
+ALL 77.95.16.0/21 DIR0
+ALL 77.109.0.0/18 DIR0
+ALL 77.120.32.0/20 DIR0
+ALL 77.120.48.0/22 DIR0
+ALL 77.120.56.0/21 DIR0
+ALL 77.120.64.0/18 DIR0
+ALL 77.120.128.0/18 DIR0
+ALL 77.120.192.0/19 DIR0
+ALL 77.120.224.0/20 DIR0
+ALL 77.120.240.0/22 DIR0
+ALL 77.121.0.0/16 DIR0
+ALL 77.122.0.0/15 DIR0
+ALL 77.222.128.0/19 DIR0
+ALL 77.235.96.0/19 DIR0
+ALL 77.239.160.0/21 DIR0
+ALL 77.239.168.0/24 DIR0
+ALL 77.239.170.0/23 DIR0
+ALL 77.239.172.0/22 DIR0
+ALL 77.239.176.0/20 DIR0
+ALL 77.242.160.0/20 DIR0
+ALL 77.244.32.0/21 DIR0
+ALL 77.244.40.0/22 DIR0
+ALL 77.244.44.0/23 DIR0
+ALL 77.247.16.0/20 DIR0
+ALL 77.247.216.0/21 DIR0
+ALL 78.24.72.0/21 DIR0
+ALL 78.25.0.0/19 DIR0
+ALL 78.25.32.0/20 DIR0
+ALL 78.25.48.0/21 DIR0
+ALL 78.25.58.0/23 DIR0
+ALL 78.25.60.0/22 DIR0
+ALL 78.26.128.0/17 DIR0
+ALL 78.27.128.0/17 DIR0
+ALL 78.30.192.0/18 DIR0
+ALL 78.31.176.0/21 DIR0
+ALL 78.31.232.0/21 DIR0
+ALL 78.31.248.0/21 DIR0
+ALL 78.109.16.0/20 DIR0
+ALL 78.111.16.0/21 DIR0
+ALL 78.111.176.0/20 DIR0
+ALL 78.111.208.0/20 DIR0
+ALL 78.137.0.0/19 DIR0
+ALL 78.137.32.0/24 DIR0
+ALL 78.137.34.0/24 DIR0
+ALL 78.152.160.0/19 DIR0
+ALL 78.154.160.0/19 DIR0
+ALL 78.159.32.0/19 DIR0
+ALL 79.110.16.0/20 DIR0
+ALL 79.110.32.0/19 DIR0
+ALL 79.110.64.0/20 DIR0
+ALL 79.110.96.0/20 DIR0
+ALL 79.110.128.0/18 DIR0
+ALL 79.110.208.0/20 DIR0
+ALL 79.110.224.0/20 DIR0
+ALL 79.124.96.0/21 DIR0
+ALL 79.124.104.0/22 DIR0
+ALL 79.124.108.0/23 DIR0
+ALL 79.124.110.0/24 DIR0
+ALL 79.124.128.0/17 DIR0
+ALL 79.135.192.0/19 DIR0
+ALL 79.140.0.0/20 DIR0
+ALL 79.142.192.0/20 DIR0
+ALL 79.143.32.0/20 DIR0
+ALL 79.171.120.0/21 DIR0
+ALL 79.174.0.0/19 DIR0
+ALL 80.67.208.0/20 DIR0
+ALL 80.70.64.0/20 DIR0
+ALL 80.70.80.0/24 DIR0
+ALL 80.70.82.0/23 DIR0
+ALL 80.73.0.0/20 DIR0
+ALL 80.77.32.0/20 DIR0
+ALL 80.78.32.0/19 DIR0
+ALL 80.84.176.0/20 DIR0
+ALL 80.87.148.0/22 DIR0
+ALL 80.87.152.0/22 DIR0
+ALL 80.90.230.0/23 DIR0
+ALL 80.90.236.0/24 DIR0
+ALL 80.90.238.0/23 DIR0
+ALL 80.91.160.0/19 DIR0
+ALL 80.92.224.0/20 DIR0
+ALL 80.93.112.0/20 DIR0
+ALL 80.94.240.0/20 DIR0
+ALL 80.243.144.0/20 DIR0
+ALL 80.245.112.0/20 DIR0
+ALL 80.249.224.0/20 DIR0
+ALL 80.252.128.0/19 DIR0
+ALL 80.252.240.0/20 DIR0
+ALL 80.254.0.0/20 DIR0
+ALL 80.255.64.0/20 DIR0
+ALL 81.17.128.0/20 DIR0
+ALL 81.21.0.0/20 DIR0
+ALL 81.22.128.0/20 DIR0
+ALL 81.23.16.0/20 DIR0
+ALL 81.24.208.0/20 DIR0
+ALL 81.25.224.0/20 DIR0
+ALL 81.26.144.0/20 DIR0
+ALL 81.30.160.0/20 DIR0
+ALL 81.90.224.0/20 DIR0
+ALL 81.95.176.0/20 DIR0
+ALL 82.144.192.0/19 DIR0
+ALL 82.193.96.0/19 DIR0
+ALL 83.97.104.0/21 DIR0
+ALL 83.137.88.0/21 DIR0
+ALL 83.138.48.0/24 DIR0
+ALL 83.138.51.0/24 DIR0
+ALL 83.138.52.0/22 DIR0
+ALL 83.142.232.0/21 DIR0
+ALL 83.143.232.0/21 DIR0
+ALL 83.170.192.0/18 DIR0
+ALL 83.218.224.0/19 DIR0
+ALL 84.47.128.0/18 DIR0
+ALL 85.90.192.0/19 DIR0
+ALL 85.91.96.0/19 DIR0
+ALL 85.114.192.0/19 DIR0
+ALL 85.117.129.0/24 DIR0
+ALL 85.159.0.0/21 DIR0
+ALL 85.198.128.0/18 DIR0
+ALL 85.202.160.0/20 DIR0
+ALL 85.202.192.0/20 DIR0
+ALL 85.223.128.0/17 DIR0
+ALL 85.238.96.0/19 DIR0
+ALL 86.110.192.0/23 DIR0
+ALL 86.111.224.0/21 DIR0
+ALL 87.238.152.0/23 DIR0
+ALL 87.238.155.0/24 DIR0
+ALL 87.238.157.0/24 DIR0
+ALL 87.238.158.0/23 DIR0
+ALL 87.250.224.0/19 DIR0
+ALL 88.81.224.0/19 DIR0
+ALL 88.84.192.0/19 DIR0
+ALL 88.154.0.0/15 DIR0
+ALL 88.208.8.0/23 DIR0
+ALL 88.214.64.0/18 DIR0
+ALL 89.19.96.0/19 DIR0
+ALL 89.21.64.0/19 DIR0
+ALL 89.28.200.0/21 DIR0
+ALL 89.105.224.0/21 DIR0
+ALL 89.105.236.0/22 DIR0
+ALL 89.105.240.0/20 DIR0
+ALL 89.107.24.0/21 DIR0
+ALL 89.162.128.0/17 DIR0
+ALL 89.185.0.0/19 DIR0
+ALL 89.187.0.0/23 DIR0
+ALL 89.187.3.0/24 DIR0
+ALL 89.187.4.0/24 DIR0
+ALL 89.200.232.0/21 DIR0
+ALL 89.200.248.0/21 DIR0
+ALL 89.207.184.0/21 DIR0
+ALL 89.209.0.0/16 DIR0
+ALL 89.248.238.0/23 DIR0
+ALL 89.251.16.0/21 DIR0
+ALL 89.252.0.0/19 DIR0
+ALL 89.252.32.0/20 DIR0
+ALL 89.252.48.0/21 DIR0
+ALL 89.252.56.0/22 DIR0
+ALL 89.252.60.0/23 DIR0
+ALL 89.252.62.0/24 DIR0
+ALL 91.90.8.0/21 DIR0
+ALL 91.90.16.0/21 DIR0
+ALL 91.103.120.0/21 DIR0
+ALL 91.123.144.0/20 DIR0
+ALL 91.142.160.0/20 DIR0
+ALL 91.145.192.0/18 DIR0
+ALL 91.189.128.0/21 DIR0
+ALL 91.192.4.0/22 DIR0
+ALL 91.192.44.0/22 DIR0
+ALL 91.192.84.0/22 DIR0
+ALL 91.192.128.0/22 DIR0
+ALL 91.192.136.0/22 DIR0
+ALL 91.192.152.0/21 DIR0
+ALL 91.192.160.0/22 DIR0
+ALL 91.192.180.0/22 DIR0
+ALL 91.192.184.0/22 DIR0
+ALL 91.192.216.0/22 DIR0
+ALL 91.193.8.0/22 DIR0
+ALL 91.193.32.0/22 DIR0
+ALL 91.193.68.0/23 DIR0
+ALL 91.193.76.0/22 DIR0
+ALL 91.193.80.0/22 DIR0
+ALL 91.193.104.0/22 DIR0
+ALL 91.193.124.0/22 DIR0
+ALL 91.193.164.0/22 DIR0
+ALL 91.193.172.0/22 DIR0
+ALL 91.193.204.0/22 DIR0
+ALL 91.193.220.0/22 DIR0
+ALL 91.193.232.0/22 DIR0
+ALL 91.193.252.0/22 DIR0
+ALL 91.194.34.0/23 DIR0
+ALL 91.194.50.0/23 DIR0
+ALL 91.194.56.0/23 DIR0
+ALL 91.194.72.0/23 DIR0
+ALL 91.194.78.0/23 DIR0
+ALL 91.194.80.0/23 DIR0
+ALL 91.194.88.0/23 DIR0
+ALL 91.194.124.0/23 DIR0
+ALL 91.194.134.0/23 DIR0
+ALL 91.194.162.0/23 DIR0
+ALL 91.194.238.0/23 DIR0
+ALL 91.194.250.0/23 DIR0
+ALL 91.195.10.0/23 DIR0
+ALL 91.195.12.0/23 DIR0
+ALL 91.195.20.0/23 DIR0
+ALL 91.195.52.0/23 DIR0
+ALL 91.195.68.0/23 DIR0
+ALL 91.195.74.0/23 DIR0
+ALL 91.195.86.0/23 DIR0
+ALL 91.195.90.0/23 DIR0
+ALL 91.195.96.0/23 DIR0
+ALL 91.195.120.0/23 DIR0
+ALL 91.195.156.0/23 DIR0
+ALL 91.195.172.0/23 DIR0
+ALL 91.195.184.0/23 DIR0
+ALL 91.195.214.0/23 DIR0
+ALL 91.195.230.0/23 DIR0
+ALL 91.195.244.0/23 DIR0
+ALL 91.195.248.0/23 DIR0
+ALL 91.196.0.0/22 DIR0
+ALL 91.196.52.0/22 DIR0
+ALL 91.196.60.0/22 DIR0
+ALL 91.196.80.0/22 DIR0
+ALL 91.196.88.0/21 DIR0
+ALL 91.196.96.0/21 DIR0
+ALL 91.196.120.0/22 DIR0
+ALL 91.196.132.0/22 DIR0
+ALL 91.196.148.0/22 DIR0
+ALL 91.196.156.0/22 DIR0
+ALL 91.196.160.0/24 DIR0
+ALL 91.196.164.0/22 DIR0
+ALL 91.196.178.0/24 DIR0
+ALL 91.196.192.0/22 DIR0
+ALL 91.196.196.0/23 DIR0
+ALL 91.196.228.0/22 DIR0
+ALL 91.197.4.0/22 DIR0
+ALL 91.197.16.0/22 DIR0
+ALL 91.197.44.0/22 DIR0
+ALL 91.197.48.0/22 DIR0
+ALL 91.197.56.0/22 DIR0
+ALL 91.197.80.0/22 DIR0
+ALL 91.197.128.0/21 DIR0
+ALL 91.197.144.0/22 DIR0
+ALL 91.197.168.0/22 DIR0
+ALL 91.197.184.0/22 DIR0
+ALL 91.197.216.0/21 DIR0
+ALL 91.197.236.0/22 DIR0
+ALL 91.197.252.0/22 DIR0
+ALL 91.198.1.0/24 DIR0
+ALL 91.198.10.0/24 DIR0
+ALL 91.198.20.0/24 DIR0
+ALL 91.198.34.0/24 DIR0
+ALL 91.198.36.0/24 DIR0
+ALL 91.198.50.0/24 DIR0
+ALL 91.198.83.0/24 DIR0
+ALL 91.198.86.0/24 DIR0
+ALL 91.198.101.0/24 DIR0
+ALL 91.198.116.0/24 DIR0
+ALL 91.198.133.0/24 DIR0
+ALL 91.198.140.0/24 DIR0
+ALL 91.198.143.0/24 DIR0
+ALL 91.198.153.0/24 DIR0
+ALL 91.198.175.0/24 DIR0
+ALL 91.198.188.0/24 DIR0
+ALL 91.198.233.0/24 DIR0
+ALL 91.198.235.0/24 DIR0
+ALL 91.198.249.0/24 DIR0
+ALL 91.199.13.0/24 DIR0
+ALL 91.199.28.0/24 DIR0
+ALL 91.199.33.0/24 DIR0
+ALL 91.199.35.0/24 DIR0
+ALL 91.199.37.0/24 DIR0
+ALL 91.199.54.0/24 DIR0
+ALL 91.199.75.0/24 DIR0
+ALL 91.199.82.0/24 DIR0
+ALL 91.199.91.0/24 DIR0
+ALL 91.199.92.0/23 DIR0
+ALL 91.199.106.0/24 DIR0
+ALL 91.199.115.0/24 DIR0
+ALL 91.199.138.0/23 DIR0
+ALL 91.199.144.0/24 DIR0
+ALL 91.199.182.0/24 DIR0
+ALL 91.199.188.0/24 DIR0
+ALL 91.199.194.0/24 DIR0
+ALL 91.199.206.0/24 DIR0
+ALL 91.199.222.0/24 DIR0
+ALL 91.199.245.0/24 DIR0
+ALL 91.200.0.0/20 DIR0
+ALL 91.200.40.0/23 DIR0
+ALL 91.200.44.0/22 DIR0
+ALL 91.200.52.0/22 DIR0
+ALL 91.200.56.0/22 DIR0
+ALL 91.200.72.0/22 DIR0
+ALL 91.200.104.0/22 DIR0
+ALL 91.200.112.0/22 DIR0
+ALL 91.200.136.0/22 DIR0
+ALL 91.200.160.0/22 DIR0
+ALL 91.200.180.0/22 DIR0
+ALL 91.200.200.0/22 DIR0
+ALL 91.200.212.0/22 DIR0
+ALL 91.200.220.0/22 DIR0
+ALL 91.200.232.0/22 DIR0
+ALL 91.200.244.0/22 DIR0
+ALL 91.200.248.0/21 DIR0
+ALL 91.201.24.0/22 DIR0
+ALL 91.201.36.0/22 DIR0
+ALL 91.201.40.0/22 DIR0
+ALL 91.201.68.0/22 DIR0
+ALL 91.201.84.0/22 DIR0
+ALL 91.201.96.0/22 DIR0
+ALL 91.201.108.0/22 DIR0
+ALL 91.201.124.0/22 DIR0
+ALL 91.201.144.0/22 DIR0
+ALL 91.201.156.0/22 DIR0
+ALL 91.201.168.0/22 DIR0
+ALL 91.201.180.0/22 DIR0
+ALL 91.201.188.0/22 DIR0
+ALL 91.201.196.0/22 DIR0
+ALL 91.201.212.0/22 DIR0
+ALL 91.201.224.0/22 DIR0
+ALL 91.201.232.0/21 DIR0
+ALL 91.201.240.0/21 DIR0
+ALL 91.201.252.0/22 DIR0
+ALL 91.202.0.0/22 DIR0
+ALL 91.202.8.0/22 DIR0
+ALL 91.202.39.0/24 DIR0
+ALL 91.202.52.0/22 DIR0
+ALL 91.202.56.0/22 DIR0
+ALL 91.202.72.0/22 DIR0
+ALL 91.202.104.0/21 DIR0
+ALL 91.202.128.0/21 DIR0
+ALL 91.202.144.0/22 DIR0
+ALL 91.202.160.0/22 DIR0
+ALL 91.202.208.0/21 DIR0
+ALL 91.202.232.0/22 DIR0
+ALL 91.202.240.0/21 DIR0
+ALL 91.203.4.0/22 DIR0
+ALL 91.203.12.0/22 DIR0
+ALL 91.203.24.0/22 DIR0
+ALL 91.203.48.0/22 DIR0
+ALL 91.203.60.0/22 DIR0
+ALL 91.203.76.0/22 DIR0
+ALL 91.203.88.0/21 DIR0
+ALL 91.203.112.0/22 DIR0
+ALL 91.203.136.0/21 DIR0
+ALL 91.203.144.0/22 DIR0
+ALL 91.203.164.0/22 DIR0
+ALL 91.204.36.0/22 DIR0
+ALL 91.204.40.0/21 DIR0
+ALL 91.204.48.0/22 DIR0
+ALL 91.204.60.0/22 DIR0
+ALL 91.204.76.0/22 DIR0
+ALL 91.204.84.0/22 DIR0
+ALL 91.204.92.0/22 DIR0
+ALL 91.204.120.0/22 DIR0
+ALL 91.204.132.0/22 DIR0
+ALL 91.204.180.0/22 DIR0
+ALL 91.204.196.0/22 DIR0
+ALL 91.204.212.0/22 DIR0
+ALL 91.205.16.0/22 DIR0
+ALL 91.205.64.0/22 DIR0
+ALL 91.205.80.0/22 DIR0
+ALL 91.205.108.0/22 DIR0
+ALL 91.205.164.0/22 DIR0
+ALL 91.206.110.0/23 DIR0
+ALL 91.206.186.0/23 DIR0
+ALL 91.206.200.0/23 DIR0
+ALL 91.206.212.0/23 DIR0
+ALL 91.206.218.0/23 DIR0
+ALL 91.206.226.0/23 DIR0
+ALL 91.207.4.0/22 DIR0
+ALL 91.207.8.0/23 DIR0
+ALL 91.207.44.0/22 DIR0
+ALL 91.207.54.0/23 DIR0
+ALL 91.207.60.0/23 DIR0
+ALL 91.207.98.0/23 DIR0
+ALL 91.207.122.0/23 DIR0
+ALL 91.207.146.0/23 DIR0
+ALL 91.207.210.0/23 DIR0
+ALL 91.207.224.0/23 DIR0
+ALL 91.208.25.0/24 DIR0
+ALL 91.208.52.0/24 DIR0
+ALL 91.208.65.0/24 DIR0
+ALL 91.208.97.0/24 DIR0
+ALL 91.208.116.0/24 DIR0
+ALL 91.208.127.0/24 DIR0
+ALL 91.208.153.0/24 DIR0
+ALL 91.208.154.0/24 DIR0
+ALL 91.208.208.0/24 DIR0
+ALL 91.209.11.0/24 DIR0
+ALL 91.209.24.0/24 DIR0
+ALL 91.209.54.0/24 DIR0
+ALL 91.210.8.0/21 DIR0
+ALL 91.210.20.0/22 DIR0
+ALL 91.210.28.0/22 DIR0
+ALL 91.210.32.0/21 DIR0
+ALL 91.210.92.0/22 DIR0
+ALL 91.210.96.0/22 DIR0
+ALL 91.210.120.0/22 DIR0
+ALL 91.210.148.0/22 DIR0
+ALL 92.49.192.0/21 DIR0
+ALL 92.49.208.0/20 DIR0
+ALL 92.49.224.0/19 DIR0
+ALL 92.240.96.0/21 DIR0
+ALL 92.240.104.0/22 DIR0
+ALL 92.240.112.0/21 DIR0
+ALL 92.240.120.0/22 DIR0
+ALL 92.240.124.0/23 DIR0
+ALL 92.240.126.0/24 DIR0
+ALL 92.242.96.0/19 DIR0
+ALL 92.244.96.0/19 DIR0
+ALL 92.249.64.0/18 DIR0
+ALL 93.72.0.0/13 DIR0
+ALL 93.89.208.0/20 DIR0
+ALL 93.126.64.0/18 DIR0
+ALL 93.127.0.0/24 DIR0
+ALL 93.127.6.0/23 DIR0
+ALL 93.127.8.0/21 DIR0
+ALL 93.127.16.0/20 DIR0
+ALL 93.127.32.0/21 DIR0
+ALL 93.127.48.0/21 DIR0
+ALL 93.157.8.0/21 DIR0
+ALL 93.157.24.0/21 DIR0
+ALL 93.158.128.0/18 DIR0
+ALL 93.175.224.0/20 DIR0
+ALL 93.178.192.0/22 DIR0
+ALL 93.178.204.0/23 DIR0
+ALL 93.178.206.0/24 DIR0
+ALL 93.178.210.0/23 DIR0
+ALL 93.180.192.0/18 DIR0
+ALL 93.183.192.0/18 DIR0
+ALL 93.185.192.0/19 DIR0
+ALL 93.188.32.0/21 DIR0
+ALL 93.190.40.0/21 DIR0
+ALL 94.27.0.0/17 DIR0
+ALL 94.74.64.0/18 DIR0
+ALL 94.76.96.0/21 DIR0
+ALL 94.100.208.0/20 DIR0
+ALL 94.124.160.0/21 DIR0
+ALL 94.125.120.0/21 DIR0
+ALL 94.130.0.0/15 DIR0
+ALL 94.153.0.0/16 DIR0
+ALL 94.154.0.0/17 DIR0
+ALL 94.154.128.0/18 DIR0
+ALL 94.158.16.0/20 DIR0
+ALL 94.158.32.0/20 DIR0
+ALL 94.158.64.0/19 DIR0
+ALL 94.158.144.0/20 DIR0
+ALL 94.240.128.0/18 DIR0
+ALL 94.248.0.0/17 DIR0
+ALL 193.0.227.0/24 DIR0
+ALL 193.0.228.0/24 DIR0
+ALL 193.0.240.0/24 DIR0
+ALL 193.0.247.0/24 DIR0
+ALL 193.16.45.0/24 DIR0
+ALL 193.16.47.0/24 DIR0
+ALL 193.16.101.0/24 DIR0
+ALL 193.16.158.0/24 DIR0
+ALL 193.16.233.0/24 DIR0
+ALL 193.16.247.0/24 DIR0
+ALL 193.17.46.0/24 DIR0
+ALL 193.17.69.0/24 DIR0
+ALL 193.17.75.0/24 DIR0
+ALL 193.17.174.0/24 DIR0
+ALL 193.17.208.0/24 DIR0
+ALL 193.17.213.0/24 DIR0
+ALL 193.17.216.0/23 DIR0
+ALL 193.17.253.0/24 DIR0
+ALL 193.19.74.0/23 DIR0
+ALL 193.19.84.0/22 DIR0
+ALL 193.19.100.0/23 DIR0
+ALL 193.19.108.0/22 DIR0
+ALL 193.19.132.0/22 DIR0
+ALL 193.19.144.0/22 DIR0
+ALL 193.19.152.0/23 DIR0
+ALL 193.19.184.0/22 DIR0
+ALL 193.19.228.0/22 DIR0
+ALL 193.19.240.0/21 DIR0
+ALL 193.19.252.0/22 DIR0
+ALL 193.22.84.0/24 DIR0
+ALL 193.22.140.0/24 DIR0
+ALL 193.23.53.0/24 DIR0
+ALL 193.23.60.0/24 DIR0
+ALL 193.23.122.0/24 DIR0
+ALL 193.23.157.0/24 DIR0
+ALL 193.23.181.0/24 DIR0
+ALL 193.23.183.0/24 DIR0
+ALL 193.23.225.0/24 DIR0
+ALL 193.24.25.0/24 DIR0
+ALL 193.24.30.0/24 DIR0
+ALL 193.25.176.0/23 DIR0
+ALL 193.25.255.0/24 DIR0
+ALL 193.26.3.0/24 DIR0
+ALL 193.26.13.0/24 DIR0
+ALL 193.26.20.0/24 DIR0
+ALL 193.26.27.0/24 DIR0
+ALL 193.26.134.0/24 DIR0
+ALL 193.27.0.0/24 DIR0
+ALL 193.27.47.0/24 DIR0
+ALL 193.27.80.0/23 DIR0
+ALL 193.27.234.0/23 DIR0
+ALL 193.27.242.0/23 DIR0
+ALL 193.28.85.0/24 DIR0
+ALL 193.28.87.0/24 DIR0
+ALL 193.28.92.0/24 DIR0
+ALL 193.28.156.0/24 DIR0
+ALL 193.28.177.0/24 DIR0
+ALL 193.28.184.0/24 DIR0
+ALL 193.28.186.0/24 DIR0
+ALL 193.28.190.0/24 DIR0
+ALL 193.28.200.0/24 DIR0
+ALL 193.29.203.0/24 DIR0
+ALL 193.29.204.0/24 DIR0
+ALL 193.29.220.0/24 DIR0
+ALL 193.30.240.0/22 DIR0
+ALL 193.32.21.0/24 DIR0
+ALL 193.33.48.0/23 DIR0
+ALL 193.33.54.0/23 DIR0
+ALL 193.33.64.0/23 DIR0
+ALL 193.33.104.0/23 DIR0
+ALL 193.33.146.0/23 DIR0
+ALL 193.33.172.0/23 DIR0
+ALL 193.33.194.0/23 DIR0
+ALL 193.33.196.0/23 DIR0
+ALL 193.33.202.0/23 DIR0
+ALL 193.33.206.0/23 DIR0
+ALL 193.33.212.0/23 DIR0
+ALL 193.33.236.0/23 DIR0
+ALL 193.34.20.0/22 DIR0
+ALL 193.34.60.0/22 DIR0
+ALL 193.34.72.0/21 DIR0
+ALL 193.34.92.0/22 DIR0
+ALL 193.34.128.0/23 DIR0
+ALL 193.34.140.0/23 DIR0
+ALL 193.34.154.0/23 DIR0
+ALL 193.34.168.0/23 DIR0
+ALL 193.34.172.0/23 DIR0
+ALL 193.35.25.0/24 DIR0
+ALL 193.37.133.0/24 DIR0
+ALL 193.37.141.0/24 DIR0
+ALL 193.37.156.0/24 DIR0
+ALL 193.39.69.0/24 DIR0
+ALL 193.39.72.0/24 DIR0
+ALL 193.39.75.0/24 DIR0
+ALL 193.39.76.0/23 DIR0
+ALL 193.39.114.0/24 DIR0
+ALL 193.39.118.0/24 DIR0
+ALL 193.41.4.0/23 DIR0
+ALL 193.41.38.0/24 DIR0
+ALL 193.41.48.0/23 DIR0
+ALL 193.41.51.0/24 DIR0
+ALL 193.41.60.0/22 DIR0
+ALL 193.41.80.0/24 DIR0
+ALL 193.41.88.0/24 DIR0
+ALL 193.41.128.0/22 DIR0
+ALL 193.41.160.0/22 DIR0
+ALL 193.41.172.0/22 DIR0
+ALL 193.41.184.0/22 DIR0
+ALL 193.41.218.0/23 DIR0
+ALL 193.41.239.0/24 DIR0
+ALL 193.43.95.0/24 DIR0
+ALL 193.43.222.0/23 DIR0
+ALL 193.43.248.0/21 DIR0
+ALL 193.46.46.0/24 DIR0
+ALL 193.46.66.0/24 DIR0
+ALL 193.46.81.0/24 DIR0
+ALL 193.46.86.0/24 DIR0
+ALL 193.46.89.0/24 DIR0
+ALL 193.46.201.0/24 DIR0
+ALL 193.46.210.0/24 DIR0
+ALL 193.47.85.0/24 DIR0
+ALL 193.47.137.0/24 DIR0
+ALL 193.47.145.0/24 DIR0
+ALL 193.47.166.0/24 DIR0
+ALL 193.58.251.0/24 DIR0
+ALL 193.84.17.0/24 DIR0
+ALL 193.84.23.0/24 DIR0
+ALL 193.84.50.0/24 DIR0
+ALL 193.84.72.0/24 DIR0
+ALL 193.84.76.0/23 DIR0
+ALL 193.84.90.0/24 DIR0
+ALL 193.93.12.0/22 DIR0
+ALL 193.93.16.0/22 DIR0
+ALL 193.93.48.0/22 DIR0
+ALL 193.93.76.0/22 DIR0
+ALL 193.93.100.0/22 DIR0
+ALL 193.93.108.0/22 DIR0
+ALL 193.93.116.0/22 DIR0
+ALL 193.93.160.0/22 DIR0
+ALL 193.93.184.0/21 DIR0
+ALL 193.93.192.0/22 DIR0
+ALL 193.93.228.0/22 DIR0
+ALL 193.108.38.0/23 DIR0
+ALL 193.108.46.0/23 DIR0
+ALL 193.108.48.0/22 DIR0
+ALL 193.108.56.0/22 DIR0
+ALL 193.108.102.0/23 DIR0
+ALL 193.108.104.0/23 DIR0
+ALL 193.108.112.0/21 DIR0
+ALL 193.108.120.0/22 DIR0
+ALL 193.108.128.0/22 DIR0
+ALL 193.108.162.0/23 DIR0
+ALL 193.108.170.0/23 DIR0
+ALL 193.108.209.0/24 DIR0
+ALL 193.108.226.0/23 DIR0
+ALL 193.108.236.0/23 DIR0
+ALL 193.108.240.0/22 DIR0
+ALL 193.108.248.0/22 DIR0
+ALL 193.109.8.0/22 DIR0
+ALL 193.109.80.0/24 DIR0
+ALL 193.109.93.0/24 DIR0
+ALL 193.109.100.0/22 DIR0
+ALL 193.109.118.0/24 DIR0
+ALL 193.109.128.0/23 DIR0
+ALL 193.109.144.0/22 DIR0
+ALL 193.109.160.0/21 DIR0
+ALL 193.109.240.0/23 DIR0
+ALL 193.109.248.0/23 DIR0
+ALL 193.110.16.0/21 DIR0
+ALL 193.110.72.0/21 DIR0
+ALL 193.110.89.0/24 DIR0
+ALL 193.110.106.0/23 DIR0
+ALL 193.110.112.0/22 DIR0
+ALL 193.110.124.0/22 DIR0
+ALL 193.110.160.0/22 DIR0
+ALL 193.110.172.0/22 DIR0
+ALL 193.110.176.0/23 DIR0
+ALL 193.110.184.0/23 DIR0
+ALL 193.110.188.0/23 DIR0
+ALL 193.111.6.0/23 DIR0
+ALL 193.111.8.0/23 DIR0
+ALL 193.111.83.0/24 DIR0
+ALL 193.111.114.0/23 DIR0
+ALL 193.111.126.0/23 DIR0
+ALL 193.111.156.0/22 DIR0
+ALL 193.111.173.0/24 DIR0
+ALL 193.111.188.0/22 DIR0
+ALL 193.111.204.0/23 DIR0
+ALL 193.111.239.0/24 DIR0
+ALL 193.111.240.0/22 DIR0
+ALL 193.111.248.0/22 DIR0
+ALL 193.124.48.0/24 DIR0
+ALL 193.124.54.0/24 DIR0
+ALL 193.124.57.0/24 DIR0
+ALL 193.124.59.0/24 DIR0
+ALL 193.124.60.0/23 DIR0
+ALL 193.124.70.0/24 DIR0
+ALL 193.124.76.0/22 DIR0
+ALL 193.124.229.0/24 DIR0
+ALL 193.138.77.0/24 DIR0
+ALL 193.138.84.0/24 DIR0
+ALL 193.138.87.0/24 DIR0
+ALL 193.138.93.0/24 DIR0
+ALL 193.138.114.0/24 DIR0
+ALL 193.138.122.0/24 DIR0
+ALL 193.138.132.0/22 DIR0
+ALL 193.138.144.0/22 DIR0
+ALL 193.138.184.0/22 DIR0
+ALL 193.138.236.0/22 DIR0
+ALL 193.138.244.0/22 DIR0
+ALL 193.142.124.0/24 DIR0
+ALL 193.142.213.0/24 DIR0
+ALL 193.142.218.0/23 DIR0
+ALL 193.142.221.0/24 DIR0
+ALL 193.151.12.0/22 DIR0
+ALL 193.151.56.0/22 DIR0
+ALL 193.151.104.0/22 DIR0
+ALL 193.151.240.0/21 DIR0
+ALL 193.151.252.0/22 DIR0
+ALL 193.164.92.0/22 DIR0
+ALL 193.164.130.0/24 DIR0
+ALL 193.164.149.0/24 DIR0
+ALL 193.178.34.0/24 DIR0
+ALL 193.178.124.0/22 DIR0
+ALL 193.178.144.0/22 DIR0
+ALL 193.178.162.0/24 DIR0
+ALL 193.178.190.0/23 DIR0
+ALL 193.178.228.0/23 DIR0
+ALL 193.178.236.0/23 DIR0
+ALL 193.178.248.0/22 DIR0
+ALL 193.186.9.0/24 DIR0
+ALL 193.186.15.0/24 DIR0
+ALL 193.188.254.0/24 DIR0
+ALL 193.189.96.0/23 DIR0
+ALL 193.189.126.0/23 DIR0
+ALL 193.192.36.0/23 DIR0
+ALL 193.193.192.0/19 DIR0
+ALL 193.200.22.0/24 DIR0
+ALL 193.200.32.0/23 DIR0
+ALL 193.200.36.0/22 DIR0
+ALL 193.200.64.0/23 DIR0
+ALL 193.200.68.0/23 DIR0
+ALL 193.200.84.0/23 DIR0
+ALL 193.200.151.0/24 DIR0
+ALL 193.200.160.0/23 DIR0
+ALL 193.200.173.0/24 DIR0
+ALL 193.200.175.0/24 DIR0
+ALL 193.200.179.0/24 DIR0
+ALL 193.200.183.0/24 DIR0
+ALL 193.200.190.0/24 DIR0
+ALL 193.200.205.0/24 DIR0
+ALL 193.200.209.0/24 DIR0
+ALL 193.200.212.0/24 DIR0
+ALL 193.200.219.0/24 DIR0
+ALL 193.200.229.0/24 DIR0
+ALL 193.200.248.0/24 DIR0
+ALL 193.200.255.0/24 DIR0
+ALL 193.201.60.0/22 DIR0
+ALL 193.201.80.0/22 DIR0
+ALL 193.201.98.0/23 DIR0
+ALL 193.201.100.0/24 DIR0
+ALL 193.201.116.0/23 DIR0
+ALL 193.201.140.0/22 DIR0
+ALL 193.201.175.0/24 DIR0
+ALL 193.201.198.0/23 DIR0
+ALL 193.201.206.0/23 DIR0
+ALL 193.201.208.0/22 DIR0
+ALL 193.201.216.0/22 DIR0
+ALL 193.201.224.0/22 DIR0
+ALL 193.202.21.0/24 DIR0
+ALL 193.202.110.0/24 DIR0
+ALL 193.202.118.0/24 DIR0
+ALL 193.203.110.0/23 DIR0
+ALL 193.203.218.0/23 DIR0
+ALL 193.203.236.0/23 DIR0
+ALL 193.218.144.0/22 DIR0
+ALL 193.219.99.0/24 DIR0
+ALL 193.219.124.0/24 DIR0
+ALL 193.222.111.0/24 DIR0
+ALL 193.222.140.0/24 DIR0
+ALL 193.223.98.0/24 DIR0
+ALL 193.227.97.0/24 DIR0
+ALL 193.227.115.0/24 DIR0
+ALL 193.227.119.0/24 DIR0
+ALL 193.227.120.0/24 DIR0
+ALL 193.227.206.0/23 DIR0
+ALL 193.227.208.0/22 DIR0
+ALL 193.227.230.0/23 DIR0
+ALL 193.227.250.0/23 DIR0
+ALL 193.228.2.0/24 DIR0
+ALL 193.232.65.0/24 DIR0
+ALL 193.238.20.0/22 DIR0
+ALL 193.238.32.0/22 DIR0
+ALL 193.238.96.0/22 DIR0
+ALL 193.238.108.0/22 DIR0
+ALL 193.238.116.0/22 DIR0
+ALL 193.238.152.0/22 DIR0
+ALL 193.238.192.0/22 DIR0
+ALL 193.239.24.0/22 DIR0
+ALL 193.239.68.0/23 DIR0
+ALL 193.239.72.0/22 DIR0
+ALL 193.239.128.0/23 DIR0
+ALL 193.239.132.0/24 DIR0
+ALL 193.239.142.0/23 DIR0
+ALL 193.239.152.0/23 DIR0
+ALL 193.239.170.0/23 DIR0
+ALL 193.239.178.0/23 DIR0
+ALL 193.239.228.0/23 DIR0
+ALL 193.239.234.0/23 DIR0
+ALL 193.239.238.0/23 DIR0
+ALL 193.239.250.0/23 DIR0
+ALL 193.239.254.0/23 DIR0
+ALL 193.242.114.0/24 DIR0
+ALL 193.243.152.0/23 DIR0
+ALL 193.243.156.0/22 DIR0
+ALL 193.254.196.0/23 DIR0
+ALL 193.254.216.0/22 DIR0
+ALL 193.254.220.0/23 DIR0
+ALL 193.254.224.0/22 DIR0
+ALL 193.254.232.0/22 DIR0
+ALL 194.0.88.0/22 DIR0
+ALL 194.0.104.0/22 DIR0
+ALL 194.0.116.0/23 DIR0
+ALL 194.0.131.0/24 DIR0
+ALL 194.0.138.0/24 DIR0
+ALL 194.0.148.0/24 DIR0
+ALL 194.0.150.0/24 DIR0
+ALL 194.0.187.0/24 DIR0
+ALL 194.0.200.0/24 DIR0
+ALL 194.0.206.0/24 DIR0
+ALL 194.0.218.0/24 DIR0
+ALL 194.0.231.0/24 DIR0
+ALL 194.1.193.0/24 DIR0
+ALL 194.1.195.0/24 DIR0
+ALL 194.6.196.0/22 DIR0
+ALL 194.6.231.0/24 DIR0
+ALL 194.6.232.0/23 DIR0
+ALL 194.8.51.0/24 DIR0
+ALL 194.8.56.0/24 DIR0
+ALL 194.8.64.0/23 DIR0
+ALL 194.9.0.0/23 DIR0
+ALL 194.9.14.0/23 DIR0
+ALL 194.9.26.0/23 DIR0
+ALL 194.9.36.0/23 DIR0
+ALL 194.9.50.0/23 DIR0
+ALL 194.9.68.0/23 DIR0
+ALL 194.15.147.0/24 DIR0
+ALL 194.24.162.0/23 DIR0
+ALL 194.24.182.0/23 DIR0
+ALL 194.24.184.0/22 DIR0
+ALL 194.24.190.0/23 DIR0
+ALL 194.24.236.0/23 DIR0
+ALL 194.24.246.0/23 DIR0
+ALL 194.29.60.0/22 DIR0
+ALL 194.29.184.0/22 DIR0
+ALL 194.29.205.0/24 DIR0
+ALL 194.30.163.0/24 DIR0
+ALL 194.30.168.0/24 DIR0
+ALL 194.30.170.0/24 DIR0
+ALL 194.30.172.0/24 DIR0
+ALL 194.33.15.0/24 DIR0
+ALL 194.33.180.0/23 DIR0
+ALL 194.33.188.0/23 DIR0
+ALL 194.37.248.0/24 DIR0
+ALL 194.42.192.0/20 DIR0
+ALL 194.44.0.0/24 DIR0
+ALL 194.44.2.0/23 DIR0
+ALL 194.44.5.0/24 DIR0
+ALL 194.44.7.0/24 DIR0
+ALL 194.44.8.0/22 DIR0
+ALL 194.44.13.0/24 DIR0
+ALL 194.44.14.0/23 DIR0
+ALL 194.44.16.0/22 DIR0
+ALL 194.44.21.0/24 DIR0
+ALL 194.44.22.0/23 DIR0
+ALL 194.44.24.0/23 DIR0
+ALL 194.44.27.0/24 DIR0
+ALL 194.44.28.0/22 DIR0
+ALL 194.44.32.0/20 DIR0
+ALL 194.44.48.0/24 DIR0
+ALL 194.44.50.0/24 DIR0
+ALL 194.44.53.0/24 DIR0
+ALL 194.44.54.0/23 DIR0
+ALL 194.44.56.0/21 DIR0
+ALL 194.44.64.0/24 DIR0
+ALL 194.44.66.0/23 DIR0
+ALL 194.44.69.0/24 DIR0
+ALL 194.44.70.0/23 DIR0
+ALL 194.44.72.0/21 DIR0
+ALL 194.44.80.0/22 DIR0
+ALL 194.44.88.0/23 DIR0
+ALL 194.44.91.0/24 DIR0
+ALL 194.44.92.0/22 DIR0
+ALL 194.44.96.0/21 DIR0
+ALL 194.44.104.0/22 DIR0
+ALL 194.44.108.0/23 DIR0
+ALL 194.44.111.0/24 DIR0
+ALL 194.44.112.0/23 DIR0
+ALL 194.44.114.0/24 DIR0
+ALL 194.44.116.0/22 DIR0
+ALL 194.44.120.0/22 DIR0
+ALL 194.44.126.0/23 DIR0
+ALL 194.44.128.0/20 DIR0
+ALL 194.44.144.0/21 DIR0
+ALL 194.44.152.0/22 DIR0
+ALL 194.44.156.0/23 DIR0
+ALL 194.44.158.0/24 DIR0
+ALL 194.44.160.0/23 DIR0
+ALL 194.44.163.0/24 DIR0
+ALL 194.44.164.0/22 DIR0
+ALL 194.44.168.0/21 DIR0
+ALL 194.44.176.0/22 DIR0
+ALL 194.44.181.0/24 DIR0
+ALL 194.44.182.0/23 DIR0
+ALL 194.44.184.0/22 DIR0
+ALL 194.44.188.0/24 DIR0
+ALL 194.44.190.0/23 DIR0
+ALL 194.44.192.0/18 DIR0
+ALL 194.48.175.0/24 DIR0
+ALL 194.48.212.0/24 DIR0
+ALL 194.50.0.0/24 DIR0
+ALL 194.50.9.0/24 DIR0
+ALL 194.50.85.0/24 DIR0
+ALL 194.50.98.0/24 DIR0
+ALL 194.50.114.0/24 DIR0
+ALL 194.50.116.0/24 DIR0
+ALL 194.50.119.0/24 DIR0
+ALL 194.50.125.0/24 DIR0
+ALL 194.50.161.0/24 DIR0
+ALL 194.50.167.0/24 DIR0
+ALL 194.50.169.0/24 DIR0
+ALL 194.50.254.0/24 DIR0
+ALL 194.54.80.0/22 DIR0
+ALL 194.54.88.0/22 DIR0
+ALL 194.54.152.0/21 DIR0
+ALL 194.54.184.0/22 DIR0
+ALL 194.58.82.0/24 DIR0
+ALL 194.60.69.0/24 DIR0
+ALL 194.60.77.0/24 DIR0
+ALL 194.63.140.0/22 DIR0
+ALL 194.79.8.0/22 DIR0
+ALL 194.79.20.0/22 DIR0
+ALL 194.79.60.0/22 DIR0
+ALL 194.88.1.0/24 DIR0
+ALL 194.88.138.0/23 DIR0
+ALL 194.88.150.0/23 DIR0
+ALL 194.88.152.0/23 DIR0
+ALL 194.88.206.0/23 DIR0
+ALL 194.88.218.0/23 DIR0
+ALL 194.88.220.0/23 DIR0
+ALL 194.93.160.0/19 DIR0
+ALL 194.99.240.0/22 DIR0
+ALL 194.105.136.0/23 DIR0
+ALL 194.105.144.0/23 DIR0
+ALL 194.106.208.0/23 DIR0
+ALL 194.106.216.0/22 DIR0
+ALL 194.107.21.0/24 DIR0
+ALL 194.110.79.0/24 DIR0
+ALL 194.110.126.0/24 DIR0
+ALL 194.110.129.0/24 DIR0
+ALL 194.110.210.0/24 DIR0
+ALL 194.110.219.0/24 DIR0
+ALL 194.110.248.0/24 DIR0
+ALL 194.110.252.0/24 DIR0
+ALL 194.110.254.0/24 DIR0
+ALL 194.114.132.0/22 DIR0
+ALL 194.114.136.0/22 DIR0
+ALL 194.116.162.0/23 DIR0
+ALL 194.116.170.0/23 DIR0
+ALL 194.116.194.0/23 DIR0
+ALL 194.116.228.0/23 DIR0
+ALL 194.116.232.0/23 DIR0
+ALL 194.116.238.0/23 DIR0
+ALL 194.116.244.0/23 DIR0
+ALL 194.125.224.0/22 DIR0
+ALL 194.125.244.0/23 DIR0
+ALL 194.125.248.0/23 DIR0
+ALL 194.126.180.0/22 DIR0
+ALL 194.126.204.0/24 DIR0
+ALL 194.126.224.0/24 DIR0
+ALL 194.135.249.0/24 DIR0
+ALL 194.140.228.0/24 DIR0
+ALL 194.140.237.0/24 DIR0
+ALL 194.143.136.0/23 DIR0
+ALL 194.143.144.0/22 DIR0
+ALL 194.145.117.0/24 DIR0
+ALL 194.145.198.0/23 DIR0
+ALL 194.145.214.0/23 DIR0
+ALL 194.145.216.0/23 DIR0
+ALL 194.145.220.0/23 DIR0
+ALL 194.146.110.0/24 DIR0
+ALL 194.146.112.0/24 DIR0
+ALL 194.146.132.0/22 DIR0
+ALL 194.146.136.0/21 DIR0
+ALL 194.146.156.0/23 DIR0
+ALL 194.146.188.0/22 DIR0
+ALL 194.146.196.0/22 DIR0
+ALL 194.146.220.0/22 DIR0
+ALL 194.146.228.0/22 DIR0
+ALL 194.150.72.0/21 DIR0
+ALL 194.150.92.0/22 DIR0
+ALL 194.150.104.0/22 DIR0
+ALL 194.150.174.0/23 DIR0
+ALL 194.150.192.0/23 DIR0
+ALL 194.150.204.0/23 DIR0
+ALL 194.150.220.0/23 DIR0
+ALL 194.150.232.0/23 DIR0
+ALL 194.153.128.0/23 DIR0
+ALL 194.153.148.0/23 DIR0
+ALL 194.165.46.0/24 DIR0
+ALL 194.165.62.0/24 DIR0
+ALL 194.169.193.0/24 DIR0
+ALL 194.169.205.0/24 DIR0
+ALL 194.169.206.0/23 DIR0
+ALL 194.169.210.0/24 DIR0
+ALL 194.169.238.0/24 DIR0
+ALL 194.176.97.0/24 DIR0
+ALL 194.183.160.0/19 DIR0
+ALL 194.187.28.0/22 DIR0
+ALL 194.187.48.0/22 DIR0
+ALL 194.187.56.0/22 DIR0
+ALL 194.187.104.0/21 DIR0
+ALL 194.187.128.0/22 DIR0
+ALL 194.187.148.0/22 DIR0
+ALL 194.187.152.0/22 DIR0
+ALL 194.187.208.0/24 DIR0
+ALL 194.187.216.0/22 DIR0
+ALL 194.187.228.0/22 DIR0
+ALL 194.213.6.0/24 DIR0
+ALL 194.213.23.0/24 DIR0
+ALL 194.220.139.0/24 DIR0
+ALL 194.220.172.0/24 DIR0
+ALL 194.242.53.0/24 DIR0
+ALL 194.242.60.0/24 DIR0
+ALL 194.242.96.0/22 DIR0
+ALL 194.242.100.0/23 DIR0
+ALL 194.242.102.0/24 DIR0
+ALL 194.242.116.0/22 DIR0
+ALL 194.246.99.0/24 DIR0
+ALL 194.246.104.0/23 DIR0
+ALL 194.246.116.0/23 DIR0
+ALL 194.246.120.0/23 DIR0
+ALL 195.2.236.0/23 DIR0
+ALL 195.2.242.0/23 DIR0
+ALL 195.3.128.0/21 DIR0
+ALL 195.3.148.0/22 DIR0
+ALL 195.3.156.0/22 DIR0
+ALL 195.3.196.0/22 DIR0
+ALL 195.3.204.0/22 DIR0
+ALL 195.3.236.0/22 DIR0
+ALL 195.3.244.0/22 DIR0
+ALL 195.5.108.0/23 DIR0
+ALL 195.5.124.0/23 DIR0
+ALL 195.5.184.0/24 DIR0
+ALL 195.8.200.0/23 DIR0
+ALL 195.8.218.0/23 DIR0
+ALL 195.9.87.0/24 DIR0
+ALL 195.9.247.0/24 DIR0
+ALL 195.10.210.0/24 DIR0
+ALL 195.10.218.0/24 DIR0
+ALL 195.12.36.0/22 DIR0
+ALL 195.14.17.0/24 DIR0
+ALL 195.20.4.0/22 DIR0
+ALL 195.20.28.0/22 DIR0
+ALL 195.20.96.0/23 DIR0
+ALL 195.20.100.0/22 DIR0
+ALL 195.20.118.0/23 DIR0
+ALL 195.20.124.0/23 DIR0
+ALL 195.20.128.0/19 DIR0
+ALL 195.22.112.0/22 DIR0
+ALL 195.22.130.0/23 DIR0
+ALL 195.22.132.0/23 DIR0
+ALL 195.22.140.0/23 DIR0
+ALL 195.24.128.0/19 DIR0
+ALL 195.24.234.0/24 DIR0
+ALL 195.24.252.0/23 DIR0
+ALL 195.26.16.0/22 DIR0
+ALL 195.26.64.0/22 DIR0
+ALL 195.26.80.0/21 DIR0
+ALL 195.26.92.0/22 DIR0
+ALL 195.28.0.0/23 DIR0
+ALL 195.28.186.0/23 DIR0
+ALL 195.34.74.0/23 DIR0
+ALL 195.34.90.0/23 DIR0
+ALL 195.34.94.0/23 DIR0
+ALL 195.34.196.0/22 DIR0
+ALL 195.34.204.0/22 DIR0
+ALL 195.35.65.0/24 DIR0
+ALL 195.38.16.0/23 DIR0
+ALL 195.38.18.0/24 DIR0
+ALL 195.39.196.0/23 DIR0
+ALL 195.39.210.0/23 DIR0
+ALL 195.39.214.0/23 DIR0
+ALL 195.39.232.0/23 DIR0
+ALL 195.39.240.0/22 DIR0
+ALL 195.39.248.0/23 DIR0
+ALL 195.39.252.0/23 DIR0
+ALL 195.42.126.0/23 DIR0
+ALL 195.42.130.0/23 DIR0
+ALL 195.42.136.0/23 DIR0
+ALL 195.43.40.0/22 DIR0
+ALL 195.43.146.0/24 DIR0
+ALL 195.43.148.0/24 DIR0
+ALL 195.46.56.0/22 DIR0
+ALL 195.47.202.0/24 DIR0
+ALL 195.47.219.0/24 DIR0
+ALL 195.47.248.0/24 DIR0
+ALL 195.47.253.0/24 DIR0
+ALL 195.49.128.0/22 DIR0
+ALL 195.49.148.0/22 DIR0
+ALL 195.49.164.0/22 DIR0
+ALL 195.58.224.0/19 DIR0
+ALL 195.60.66.0/23 DIR0
+ALL 195.60.70.0/23 DIR0
+ALL 195.60.174.0/23 DIR0
+ALL 195.60.184.0/23 DIR0
+ALL 195.60.200.0/23 DIR0
+ALL 195.60.224.0/24 DIR0
+ALL 195.60.226.0/24 DIR0
+ALL 195.62.14.0/23 DIR0
+ALL 195.62.24.0/23 DIR0
+ALL 195.62.36.0/23 DIR0
+ALL 195.64.136.0/23 DIR0
+ALL 195.64.142.0/23 DIR0
+ALL 195.64.148.0/23 DIR0
+ALL 195.64.166.0/23 DIR0
+ALL 195.64.190.0/23 DIR0
+ALL 195.64.224.0/19 DIR0
+ALL 195.66.65.0/24 DIR0
+ALL 195.66.66.0/24 DIR0
+ALL 195.66.79.0/24 DIR0
+ALL 195.66.87.0/24 DIR0
+ALL 195.66.93.0/24 DIR0
+ALL 195.66.105.0/24 DIR0
+ALL 195.66.136.0/23 DIR0
+ALL 195.66.140.0/23 DIR0
+ALL 195.66.152.0/23 DIR0
+ALL 195.66.156.0/23 DIR0
+ALL 195.66.192.0/19 DIR0
+ALL 195.68.196.0/23 DIR0
+ALL 195.68.202.0/23 DIR0
+ALL 195.68.210.0/23 DIR0
+ALL 195.68.216.0/22 DIR0
+ALL 195.68.222.0/23 DIR0
+ALL 195.69.76.0/22 DIR0
+ALL 195.69.84.0/22 DIR0
+ALL 195.69.132.0/22 DIR0
+ALL 195.69.168.0/22 DIR0
+ALL 195.69.176.0/23 DIR0
+ALL 195.69.179.0/24 DIR0
+ALL 195.69.184.0/22 DIR0
+ALL 195.69.196.0/22 DIR0
+ALL 195.69.200.0/22 DIR0
+ALL 195.69.220.0/22 DIR0
+ALL 195.69.244.0/22 DIR0
+ALL 195.69.248.0/22 DIR0
+ALL 195.72.144.0/22 DIR0
+ALL 195.72.156.0/22 DIR0
+ALL 195.74.67.0/24 DIR0
+ALL 195.78.38.0/23 DIR0
+ALL 195.78.58.0/23 DIR0
+ALL 195.78.68.0/23 DIR0
+ALL 195.78.92.0/23 DIR0
+ALL 195.78.232.0/22 DIR0
+ALL 195.78.244.0/22 DIR0
+ALL 195.78.252.0/23 DIR0
+ALL 195.80.231.0/24 DIR0
+ALL 195.80.232.0/24 DIR0
+ALL 195.82.150.0/23 DIR0
+ALL 195.85.198.0/24 DIR0
+ALL 195.85.214.0/24 DIR0
+ALL 195.85.219.0/24 DIR0
+ALL 195.85.250.0/24 DIR0
+ALL 195.90.122.0/23 DIR0
+ALL 195.93.138.0/23 DIR0
+ALL 195.93.154.0/23 DIR0
+ALL 195.93.160.0/23 DIR0
+ALL 195.93.172.0/23 DIR0
+ALL 195.93.184.0/23 DIR0
+ALL 195.93.190.0/23 DIR0
+ALL 195.93.204.0/23 DIR0
+ALL 195.93.212.0/22 DIR0
+ALL 195.95.139.0/24 DIR0
+ALL 195.95.147.0/24 DIR0
+ALL 195.95.151.0/24 DIR0
+ALL 195.95.157.0/24 DIR0
+ALL 195.95.165.0/24 DIR0
+ALL 195.95.171.0/24 DIR0
+ALL 195.95.189.0/24 DIR0
+ALL 195.95.206.0/23 DIR0
+ALL 195.95.210.0/23 DIR0
+ALL 195.95.222.0/23 DIR0
+ALL 195.95.232.0/23 DIR0
+ALL 195.110.6.0/23 DIR0
+ALL 195.114.6.0/23 DIR0
+ALL 195.114.30.0/23 DIR0
+ALL 195.114.96.0/23 DIR0
+ALL 195.114.120.0/23 DIR0
+ALL 195.114.128.0/19 DIR0
+ALL 195.123.0.0/16 DIR0
+ALL 195.128.16.0/22 DIR0
+ALL 195.128.56.0/21 DIR0
+ALL 195.128.178.0/23 DIR0
+ALL 195.128.182.0/23 DIR0
+ALL 195.128.230.0/23 DIR0
+ALL 195.128.248.0/23 DIR0
+ALL 195.128.252.0/23 DIR0
+ALL 195.135.196.0/22 DIR0
+ALL 195.137.167.0/24 DIR0
+ALL 195.137.192.0/23 DIR0
+ALL 195.137.196.0/23 DIR0
+ALL 195.137.202.0/23 DIR0
+ALL 195.137.226.0/23 DIR0
+ALL 195.137.232.0/23 DIR0
+ALL 195.137.240.0/23 DIR0
+ALL 195.137.244.0/23 DIR0
+ALL 195.137.250.0/23 DIR0
+ALL 195.138.64.0/19 DIR0
+ALL 195.138.160.0/19 DIR0
+ALL 195.138.193.0/24 DIR0
+ALL 195.138.198.0/24 DIR0
+ALL 195.138.217.0/24 DIR0
+ALL 195.138.218.0/24 DIR0
+ALL 195.140.160.0/22 DIR0
+ALL 195.140.168.0/22 DIR0
+ALL 195.140.176.0/22 DIR0
+ALL 195.140.224.0/22 DIR0
+ALL 195.140.244.0/22 DIR0
+ALL 195.144.6.0/24 DIR0
+ALL 195.144.21.0/24 DIR0
+ALL 195.144.25.0/24 DIR0
+ALL 195.144.28.0/24 DIR0
+ALL 195.149.70.0/24 DIR0
+ALL 195.149.90.0/24 DIR0
+ALL 195.149.96.0/24 DIR0
+ALL 195.149.108.0/23 DIR0
+ALL 195.149.112.0/24 DIR0
+ALL 195.149.114.0/24 DIR0
+ALL 195.149.125.0/24 DIR0
+ALL 195.160.192.0/22 DIR0
+ALL 195.160.220.0/22 DIR0
+ALL 195.160.232.0/22 DIR0
+ALL 195.177.68.0/22 DIR0
+ALL 195.177.72.0/22 DIR0
+ALL 195.177.92.0/22 DIR0
+ALL 195.177.112.0/21 DIR0
+ALL 195.177.124.0/22 DIR0
+ALL 195.177.208.0/23 DIR0
+ALL 195.177.222.0/23 DIR0
+ALL 195.177.236.0/22 DIR0
+ALL 195.177.240.0/23 DIR0
+ALL 195.178.128.0/19 DIR0
+ALL 195.182.0.0/24 DIR0
+ALL 195.182.7.0/24 DIR0
+ALL 195.182.21.0/24 DIR0
+ALL 195.182.22.0/24 DIR0
+ALL 195.182.192.0/22 DIR0
+ALL 195.184.70.0/24 DIR0
+ALL 195.184.80.0/23 DIR0
+ALL 195.184.192.0/19 DIR0
+ALL 195.189.8.0/22 DIR0
+ALL 195.189.16.0/22 DIR0
+ALL 195.189.44.0/22 DIR0
+ALL 195.189.48.0/22 DIR0
+ALL 195.189.60.0/22 DIR0
+ALL 195.189.96.0/22 DIR0
+ALL 195.189.104.0/22 DIR0
+ALL 195.189.200.0/23 DIR0
+ALL 195.189.214.0/23 DIR0
+ALL 195.189.226.0/23 DIR0
+ALL 195.189.228.0/23 DIR0
+ALL 195.189.234.0/23 DIR0
+ALL 195.189.240.0/23 DIR0
+ALL 195.189.246.0/23 DIR0
+ALL 195.189.248.0/23 DIR0
+ALL 195.190.13.0/24 DIR0
+ALL 195.200.64.0/23 DIR0
+ALL 195.200.90.0/23 DIR0
+ALL 195.200.196.0/24 DIR0
+ALL 195.200.221.0/24 DIR0
+ALL 195.206.224.0/21 DIR0
+ALL 195.214.192.0/21 DIR0
+ALL 195.214.208.0/21 DIR0
+ALL 195.214.220.0/22 DIR0
+ALL 195.214.236.0/22 DIR0
+ALL 195.216.204.0/23 DIR0
+ALL 195.216.206.0/24 DIR0
+ALL 195.216.210.0/23 DIR0
+ALL 195.216.212.0/23 DIR0
+ALL 195.216.226.0/24 DIR0
+ALL 195.216.248.0/24 DIR0
+ALL 195.225.52.0/23 DIR0
+ALL 195.225.96.0/22 DIR0
+ALL 195.225.112.0/22 DIR0
+ALL 195.225.144.0/22 DIR0
+ALL 195.225.156.0/22 DIR0
+ALL 195.225.228.0/22 DIR0
+ALL 195.230.96.0/24 DIR0
+ALL 195.230.103.0/24 DIR0
+ALL 195.230.115.0/24 DIR0
+ALL 195.230.128.0/19 DIR0
+ALL 195.234.61.0/24 DIR0
+ALL 195.234.68.0/22 DIR0
+ALL 195.234.72.0/22 DIR0
+ALL 195.234.112.0/22 DIR0
+ALL 195.234.132.0/24 DIR0
+ALL 195.234.148.0/24 DIR0
+ALL 195.234.174.0/24 DIR0
+ALL 195.234.200.0/22 DIR0
+ALL 195.234.212.0/22 DIR0
+ALL 195.234.220.0/22 DIR0
+ALL 195.238.92.0/23 DIR0
+ALL 195.238.176.0/21 DIR0
+ALL 195.238.188.0/22 DIR0
+ALL 195.242.94.0/23 DIR0
+ALL 195.242.112.0/22 DIR0
+ALL 195.242.148.0/22 DIR0
+ALL 195.242.161.0/24 DIR0
+ALL 195.242.200.0/22 DIR0
+ALL 195.244.4.0/23 DIR0
+ALL 195.244.8.0/23 DIR0
+ALL 195.245.76.0/23 DIR0
+ALL 195.245.80.0/23 DIR0
+ALL 195.245.96.0/23 DIR0
+ALL 195.245.112.0/23 DIR0
+ALL 195.245.118.0/23 DIR0
+ALL 195.245.120.0/23 DIR0
+ALL 195.245.200.0/24 DIR0
+ALL 195.245.215.0/24 DIR0
+ALL 195.245.221.0/24 DIR0
+ALL 195.245.249.0/24 DIR0
+ALL 195.245.253.0/24 DIR0
+ALL 195.246.104.0/23 DIR0
+ALL 195.246.217.0/24 DIR0
+ALL 195.248.93.0/24 DIR0
+ALL 195.248.160.0/19 DIR0
+ALL 195.248.234.0/23 DIR0
+ALL 195.250.36.0/24 DIR0
+ALL 195.250.43.0/24 DIR0
+ALL 195.250.62.0/24 DIR0
+ALL 195.254.142.0/23 DIR0
+ALL 195.254.150.0/23 DIR0
+ALL 209.62.181.0/24 DIR0
+ALL 209.62.187.0/24 DIR0
+ALL 209.62.189.0/24 DIR0
+ALL 209.85.128.0/17 DIR0
+ALL 212.1.64.0/18 DIR0
+ALL 212.2.128.0/19 DIR0
+ALL 212.3.96.0/19 DIR0
+ALL 212.8.32.0/19 DIR0
+ALL 212.9.224.0/19 DIR0
+ALL 212.15.128.0/19 DIR0
+ALL 212.22.192.0/20 DIR0
+ALL 212.26.128.0/19 DIR0
+ALL 212.28.64.0/19 DIR0
+ALL 212.35.160.0/19 DIR0
+ALL 212.40.32.0/19 DIR0
+ALL 212.42.64.0/19 DIR0
+ALL 212.58.160.0/19 DIR0
+ALL 212.66.32.0/19 DIR0
+ALL 212.68.160.0/19 DIR0
+ALL 212.74.234.0/24 DIR0
+ALL 212.80.32.0/19 DIR0
+ALL 212.82.192.0/19 DIR0
+ALL 212.86.96.0/19 DIR0
+ALL 212.86.225.0/24 DIR0
+ALL 212.86.226.0/24 DIR0
+ALL 212.86.228.0/22 DIR0
+ALL 212.86.232.0/21 DIR0
+ALL 212.86.240.0/20 DIR0
+ALL 212.87.160.0/19 DIR0
+ALL 212.90.96.0/20 DIR0
+ALL 212.90.112.0/23 DIR0
+ALL 212.90.116.0/23 DIR0
+ALL 212.90.124.0/22 DIR0
+ALL 212.90.160.0/19 DIR0
+ALL 212.92.224.0/19 DIR0
+ALL 212.109.32.0/19 DIR0
+ALL 212.111.192.0/19 DIR0
+ALL 212.113.32.0/20 DIR0
+ALL 212.115.224.0/19 DIR0
+ALL 212.178.0.0/19 DIR0
+ALL 213.130.0.0/20 DIR0
+ALL 213.130.16.0/23 DIR0
+ALL 213.130.18.0/24 DIR0
+ALL 213.130.20.0/22 DIR0
+ALL 213.130.24.0/21 DIR0
+ALL 213.133.160.0/19 DIR0
+ALL 213.135.64.0/23 DIR0
+ALL 213.135.67.0/24 DIR0
+ALL 213.135.68.0/22 DIR0
+ALL 213.135.72.0/21 DIR0
+ALL 213.151.0.0/19 DIR0
+ALL 213.154.192.0/19 DIR0
+ALL 213.155.0.0/19 DIR0
+ALL 213.156.64.0/19 DIR0
+ALL 213.159.224.0/19 DIR0
+ALL 213.160.128.0/19 DIR0
+ALL 213.169.64.0/19 DIR0
+ALL 213.180.192.0/19 DIR0
+ALL 213.186.112.0/20 DIR0
+ALL 213.186.192.0/19 DIR0
+ALL 213.200.32.0/23 DIR0
+ALL 213.200.43.0/24 DIR0
+ALL 213.208.160.0/19 DIR0
+ALL 213.227.192.0/18 DIR0
+ALL 213.231.0.0/18 DIR0
+ALL 213.238.0.0/22 DIR0
+ALL 213.238.16.0/24 DIR0
+ALL 213.238.20.0/24 DIR0
+ALL 213.238.24.0/24 DIR0
+ALL 213.238.28.0/24 DIR0
+ALL 216.73.80.0/24 DIR0
+ALL 216.73.87.0/24 DIR0
+ALL 216.239.32.0/19 DIR0
+ALL 217.9.0.0/24 DIR0
+ALL 217.9.4.0/24 DIR0
+ALL 217.12.192.0/19 DIR0
+ALL 217.19.208.0/20 DIR0
+ALL 217.24.160.0/20 DIR0
+ALL 217.25.192.0/20 DIR0
+ALL 217.27.144.0/20 DIR0
+ALL 217.28.254.0/24 DIR0
+ALL 217.65.240.0/21 DIR0
+ALL 217.66.96.0/20 DIR0
+ALL 217.73.128.0/20 DIR0
+ALL 217.76.192.0/20 DIR0
+ALL 217.77.208.0/20 DIR0
+ALL 217.112.208.0/20 DIR0
+ALL 217.114.32.0/20 DIR0
+ALL 217.117.64.0/20 DIR0
+ALL 217.144.64.0/20 DIR0
+ALL 217.146.240.0/20 DIR0
+ALL 217.147.160.0/21 DIR0
+ALL 217.147.168.0/24 DIR0
+ALL 217.175.80.0/20 DIR0
+ALL 217.196.160.0/20 DIR0
+ALL 217.198.128.0/20 DIR0
+ALL 217.199.208.0/20 DIR0
+ALL 217.199.224.0/20 DIR0
--- /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>
+ */
+
+/*
+ $Revision: 1.1.1.1 $
+ $Date: 2009/02/24 08:13:03 $
+ $Author: faust $
+ */
+
+#include <fstream>
+#include <sstream>
+#include <cstdlib>
+#include <limits>
+#include <cerrno>
+#include <locale>
+
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include "rules.h"
+#include "utils.h"
+
+using namespace std;
+
+STG::RULES_PARSER::RULES_PARSER()
+ : rules(),
+ error(false),
+ errorStream(""),
+ protocols()
+{
+error = InitProtocols();
+}
+
+STG::RULES_PARSER::RULES_PARSER(const string & fileName)
+ : rules(),
+ error(false),
+ errorStream(""),
+ protocols()
+{
+error = InitProtocols();
+SetFile(fileName);
+}
+
+void STG::RULES_PARSER::SetFile(const string & fileName)
+{
+errorStream.str("");
+
+ifstream rulesFile(fileName.c_str());
+
+int lineNumber = 0;
+
+if (!rulesFile)
+ {
+ error = true;
+ errorStream << "RULES_PARSER::SetFile - Error opening file '" << fileName << "'\n";
+ return;
+ }
+
+string line;
+
+rules.erase(rules.begin(), rules.end());
+
+while (getline(rulesFile, line))
+ {
+ lineNumber++;
+ if (ParseLine(line))
+ {
+ error = true;
+ errorStream << "RULES_PARSER::SetFile - Error parsing line at '" << fileName << ":" << lineNumber << "'\n";
+ return;
+ }
+ }
+
+STG::RULE rule;
+
+// Adding lastest rule: ALL 0.0.0.0/0 NULL
+rule.dir = -1; //NULL
+rule.ip = 0; //0.0.0.0
+rule.mask = 0;
+rule.port1 = 0;
+rule.port2 = 65535;
+rule.proto = -1;
+
+rules.push_back(rule);
+
+errorStream.str("");
+
+return;
+}
+
+bool STG::RULES_PARSER::ParseLine(string line)
+{
+size_t pos;
+
+pos = line.find('#');
+if (pos != string::npos)
+ {
+ line = line.substr(0, pos);
+ }
+
+if (line.empty())
+ {
+ return false;
+ }
+
+size_t lpos = line.find_first_not_of("\t ", 0, 2);
+
+if (lpos == string::npos)
+ {
+ return false;
+ }
+
+size_t rpos = line.find_first_of("\t ", lpos, 2);
+
+if (rpos == string::npos)
+ {
+ return false;
+ }
+
+string proto(line.begin() + lpos, line.begin() + rpos);
+
+lpos = line.find_first_not_of("\t ", rpos, 2);
+
+if (lpos == string::npos)
+ {
+ return false;
+ }
+
+rpos = line.find_first_of("\t ", lpos, 2);
+
+if (rpos == string::npos)
+ {
+ return false;
+ }
+
+string address(line.begin() + lpos, line.begin() + rpos);
+
+lpos = line.find_first_not_of("\t ", rpos, 2);
+
+if (lpos == string::npos)
+ {
+ return false;
+ }
+string direction(line.begin() + lpos, line.end());
+
+if (proto.empty() ||
+ address.empty() ||
+ direction.empty())
+ {
+ return false;
+ }
+
+map<string, int>::const_iterator it(protocols.find(proto));
+
+if (it == protocols.end())
+ {
+ errorStream << "RULES_PARSER::ParseLine - Invalid protocol\n";
+ return true;
+ }
+
+STG::RULE rule;
+
+rule.proto = it->second;
+
+if (direction.length() < 4)
+ {
+ errorStream << "RULES_PARSER::ParseLine - Invalid direction\n";
+ return true;
+ }
+
+if (direction == "NULL")
+ {
+ rule.dir = -1;
+ }
+else
+ {
+ string prefix(direction.begin(), direction.begin() + 3);
+ direction = direction.substr(3, direction.length() - 3);
+ if (prefix != "DIR")
+ {
+ errorStream << "RULES_PARSER::ParseLine - Invalid direction prefix\n";
+ return true;
+ }
+ char * endptr;
+ /*
+ * 'cause strtol don't change errno on success
+ * according to: http://www.opengroup.org/onlinepubs/000095399/functions/strtol.html
+ */
+ errno = 0;
+ rule.dir = strtol(direction.c_str(), &endptr, 10);
+
+ // Code from strtol(3) release 3.10
+ if ((errno == ERANGE && (rule.dir == numeric_limits<int>::max() ||
+ rule.dir == numeric_limits<int>::min()))
+ || (errno != 0 && rule.dir == 0))
+ {
+ errorStream << "RULES_PARSER::ParseLine - Direction out of range\n";
+ return true;
+ }
+ if (endptr == direction.c_str())
+ {
+ errorStream << "RULES_PARSER::ParseLine - Invalid direction\n";
+ return true;
+ }
+ }
+
+if (ParseAddress(address, &rule))
+ {
+ errorStream << "RULES_PARSER::ParseLine - Invalid address\n";
+ return true;
+ }
+
+rules.push_back(rule);
+
+return false;
+}
+
+bool STG::RULES_PARSER::ParseAddress(const string & address, RULE * rule) const
+{
+// Format: <address>[/<mask>[:<port1>[-<port2>]]]
+size_t pos = address.find('/');
+string ip;
+string mask;
+string ports;
+
+if (pos != string::npos)
+ {
+ ip = address.substr(0, pos);
+ mask = address.substr(pos + 1, address.length() - pos - 1);
+ pos = mask.find(':');
+ if (pos != string::npos)
+ {
+ ports = mask.substr(pos + 1, mask.length() - pos - 1);
+ mask = mask.substr(0, pos);
+ }
+ else
+ {
+ ports = "0-65535";
+ }
+ }
+else
+ {
+ mask = "32";
+ pos = address.find(':');
+ if (pos != string::npos)
+ {
+ ip = address.substr(0, pos);
+ ports = address.substr(pos + 1, address.length() - pos - 1);
+ }
+ else
+ {
+ ip = address;
+ ports = "0-65536";
+ }
+ }
+
+struct in_addr ipaddr;
+
+if (!inet_aton(ip.c_str(), &ipaddr))
+ {
+ errorStream << "RULES_PARSER::ParseAddress - Invalid IP\n";
+ return true;
+ }
+
+rule->ip = ntohl(ipaddr.s_addr);
+
+if (ParseMask(mask, rule))
+ {
+ errorStream << "RULES_PARSER::ParseAddress - Error parsing mask\n";
+ return true;
+ }
+
+pos = ports.find('-');
+string port1;
+string port2;
+
+if (pos != string::npos)
+ {
+ port1 = ports.substr(0, pos);
+ port2 = ports.substr(pos + 1, ports.length() - pos - 1);
+ }
+else
+ {
+ port1 = port2 = ports;
+ }
+
+if (ParsePorts(port1, port2, rule))
+ {
+ errorStream << "RULES_PARSER::ParseAddress - Error pasing ports\n";
+ return true;
+ }
+
+return false;
+}
+
+bool STG::RULES_PARSER::ParseMask(const string & mask, RULE * rule) const
+{
+char * endptr;
+
+errno = 0;
+/*
+ * 'cause strtol don't change errno on success
+ * according to: http://www.opengroup.org/onlinepubs/000095399/functions/strtol.html
+ */
+rule->mask = strtol(mask.c_str(), &endptr, 10);
+
+if ((errno == ERANGE && (rule->mask == numeric_limits<uint32_t>::max() ||
+ rule->mask == numeric_limits<uint32_t>::min()))
+ || (errno != 0 && rule->mask == 0))
+ {
+ errorStream << "RULES_PARSER::ParseMask - Mask is out of range\n";
+ return true;
+ }
+
+if (endptr == NULL)
+ {
+ errorStream << "RULES_PARSER::ParseMask - NULL endptr\n";
+ return true;
+ }
+
+if (*endptr != '\0')
+ {
+ errorStream << "RULES_PARSER::ParseMask - Invalid mask\n";
+ return true;
+ }
+
+if (rule->mask > 32)
+ {
+ errorStream << "RULES_PARSER::ParseMask - Mask is greater than 32\n";
+ return true;
+ }
+
+rule->mask = 0xffFFffFF >> (32 - rule->mask);
+
+return false;
+}
+
+bool STG::RULES_PARSER::ParsePorts(const string & port1,
+ const string & port2,
+ RULE * rule) const
+{
+char * endptr;
+
+errno = 0;
+/*
+ * 'cause strtol don't change errno on success
+ * according to: http://www.opengroup.org/onlinepubs/000095399/functions/strtol.html
+ */
+rule->port1 = strtol(port1.c_str(), &endptr, 10);
+
+if ((errno == ERANGE && (rule->port1 == numeric_limits<uint16_t>::max() ||
+ rule->port1 == numeric_limits<uint16_t>::min()))
+ || (errno != 0 && rule->port1 == 0))
+ {
+ errorStream << "RULES_PARSER::ParsePorts - Min port is out of range\n";
+ return true;
+ }
+
+if (endptr == NULL)
+ {
+ errorStream << "RULES_PARSER::ParsePorts - NULL endptr on min port\n";
+ return true;
+ }
+
+if (*endptr != '\0')
+ {
+ errorStream << "RULES_PARSER::ParsePorts - Invalid min port\n";
+ return true;
+ }
+
+errno = 0;
+/*
+ * 'cause strtol don't change errno on success
+ * according to: http://www.opengroup.org/onlinepubs/000095399/functions/strtol.html
+ */
+rule->port2 = strtol(port2.c_str(), &endptr, 10);
+
+if ((errno == ERANGE && (rule->port2 == numeric_limits<uint16_t>::max() ||
+ rule->port2 == numeric_limits<uint16_t>::min()))
+ || (errno != 0 && rule->port2 == 0))
+ {
+ errorStream << "RULES_PARSER::ParseAddress - Max port is out of range\n";
+ return true;
+ }
+
+if (endptr == NULL)
+ {
+ errorStream << "RULES_PARSER::ParsePorts - NULL endptr on max port\n";
+ return true;
+ }
+
+if (*endptr != '\0')
+ {
+ errorStream << "RULES_PARSER::ParsePorts - Invalid max port\n";
+ return true;
+ }
+
+return false;
+}
+
+bool STG::RULES_PARSER::InitProtocols()
+{
+struct protoent * pe;
+
+locale loc("");
+
+protocols.erase(protocols.begin(), protocols.end());
+
+setprotoent(true); // Open link to /etc/protocols
+
+while ((pe = getprotoent()) != NULL)
+ {
+ string proto(pe->p_name);
+ protocols.insert(make_pair(STG::ToUpper(pe->p_name, loc), pe->p_proto));
+ }
+
+endprotoent();
+
+protocols["ALL"] = -1;
+protocols["TCP_UDP"] = -2;
+
+errorStream.str("");
+
+return protocols.empty();
+}
--- /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>
+ */
+
+ /*
+ $Revision: 1.1.1.1 $
+ $Date: 2009/02/24 08:13:03 $
+ $Author: faust $
+ */
+
+
+#ifndef __RULES_H__
+#define __RULES_H__
+
+#include <list>
+#include <string>
+#include <sstream>
+#include <map>
+
+#ifdef HAVE_STDINT
+ #include <stdint.h>
+#else
+ #ifdef HAVE_INTTYPES
+ #include <inttypes.h>
+ #else
+ #error "You need either stdint.h or inttypes.h to compile this!"
+ #endif
+#endif
+
+namespace STG
+{
+
+ //-----------------------------------------------------------------------------
+ struct RULE
+ {
+ uint32_t ip; // IP
+ uint32_t mask; // Netmask
+ uint16_t port1; // Port 1
+ uint16_t port2; // Port 2
+ int proto; // Protocol
+ int dir; // Direction
+ };
+ //-----------------------------------------------------------------------------
+ typedef std::list<RULE> RULES;
+ //-----------------------------------------------------------------------------
+ class RULES_PARSER
+ {
+ public:
+ RULES_PARSER();
+
+ RULES_PARSER(const std::string & fileName);
+
+ ~RULES_PARSER() {};
+
+ void SetFile(const std::string & fileName);
+
+ const RULES & GetRules() const { return rules; };
+ bool IsError() const { return error; };
+ const std::string ErrorMsg() const { return errorStream.str(); };
+
+ private:
+ RULES rules;
+ bool error;
+ mutable std::stringstream errorStream;
+ std::map<std::string, int> protocols;
+
+ bool InitProtocols();
+ bool ParseLine(std::string line);
+ bool ParseAddress(const std::string & address, RULE * rule) const;
+ bool ParseMask(const std::string & mask, RULE * rule) const;
+ bool ParsePorts(const std::string & port1,
+ const std::string & port2,
+ RULE * rule) const;
+ };
+
+}
+
+#endif // __RULES_H__
--- /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>
+ */
+
+/*
+ $Revision: 1.3 $
+ $Date: 2009/10/12 08:46:05 $
+ $Author: faust $
+ */
+
+#include "rules_finder.h"
+#include "logger.h"
+#include "lock.h"
+
+STG::RULES_FINDER::RULES_FINDER()
+{
+ pthread_mutex_init(&mutex, NULL);
+}
+
+STG::RULES_FINDER::~RULES_FINDER()
+{
+ pthread_mutex_destroy(&mutex);
+}
+
+void STG::RULES_FINDER::SetRules(const RULES & r)
+{
+SCOPED_LOCK lock(mutex);
+rules = r;
+}
+
+int STG::RULES_FINDER::GetDir(const PENDING_PACKET & packet) const
+{
+bool addrMatch;
+bool portMatch;
+
+STG::RULES::const_iterator ln;
+int ruleLine(1);
+
+SCOPED_LOCK lock(mutex);
+
+ln = rules.begin();
+
+while (ln != rules.end())
+ {
+ addrMatch = false;
+ portMatch = false;
+
+ // Port range
+ switch (packet.direction) {
+ case PENDING_PACKET::INCOMING:
+ portMatch = (packet.sport >= ln->port1) &&
+ (packet.sport <= ln->port2);
+ break;
+ case PENDING_PACKET::OUTGOING:
+ portMatch = (packet.dport >= ln->port1) &&
+ (packet.dport <= ln->port2);
+ break;
+ case PENDING_PACKET::LOCAL:
+ portMatch = ((packet.sport >= ln->port1) &&
+ (packet.sport <= ln->port2)) ||
+ ((packet.dport >= ln->port1) &&
+ (packet.dport <= ln->port2));
+ break;
+ default:
+ ++ruleLine;
+ ++ln;
+ continue;
+ }
+
+ if (!portMatch) {
+ ++ruleLine;
+ ++ln;
+ continue;
+ }
+
+ /*portMatch = ((packet.sport >= ln->port1) &&
+ (packet.sport <= ln->port2) &&
+ (packet.direction == PENDING_PACKET::INCOMING)) ||
+ ((packet.dport >= ln->port1) &&
+ (packet.dport <= ln->port2) &&
+ (packet.direction == PENDING_PACKET::OUTGOING));*/
+
+ if (ln->proto != packet.proto)
+ {
+ // Is it a normal protcol number?
+ if (ln->proto >= 0)
+ {
+ ++ruleLine;
+ ++ln;
+ continue;
+ }
+ else if (ln->proto == -2)
+ {
+ // -2 - TCP_UDP
+ if (packet.proto != 6 &&
+ packet.proto != 17)
+ {
+ ++ruleLine;
+ ++ln;
+ continue;
+ }
+ }
+ // -1 - ALL
+ }
+
+ switch (packet.direction) {
+ case PENDING_PACKET::INCOMING:
+ // From outer world to us
+ addrMatch = (packet.saddr & ln->mask) == ln->ip;
+ break;
+ case PENDING_PACKET::OUTGOING:
+ // From us to outer world
+ addrMatch = (packet.daddr & ln->mask) == ln->ip;
+ break;
+ case PENDING_PACKET::LOCAL:
+ // From us to us
+ addrMatch = (packet.saddr & ln->mask) == ln->ip ||
+ (packet.daddr & ln->mask) == ln->ip;
+ break;
+ default:
+ // From outer world to outer world
+ ++ruleLine;
+ ++ln;
+ continue;
+ }
+
+
+ if (addrMatch)
+ {
+ // At this point ports and protocol are matched
+ return ln->dir;
+ }
+
+ ++ruleLine;
+ ++ln;
+ } //while (ln != rules.end())
+
+return -1;
+}
--- /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>
+ */
+
+ /*
+ $Revision: 1.2 $
+ $Date: 2009/02/26 18:32:59 $
+ $Author: faust $
+ */
+
+
+#ifndef __RULES_FINDER_H__
+#define __RULES_FINDER_H__
+
+#include <pthread.h>
+
+#include "rules.h"
+#include "tc_packets.h"
+
+namespace STG
+{
+
+ class RULES_FINDER
+ {
+ public:
+ RULES_FINDER();
+ ~RULES_FINDER();
+
+ void SetRules(const RULES & r);
+
+ int GetDir(const PENDING_PACKET & packet) const;
+
+ private:
+ RULES rules;
+ mutable pthread_mutex_t mutex;
+ };
+
+}
+
+#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 : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+/*
+ $Revision: 1.1.1.1 $
+ $Date: 2009/02/24 08:13:03 $
+ $Author: faust $
+ */
+
+#include <iostream>
+#include <cstdlib>
+#include <string>
+#include <map>
+#include <algorithm>
+#include <functional>
+
+#include "rules.h"
+#include "logger.h"
+
+using namespace STG;
+
+STGLogger log;
+
+typedef std::pair<std::string, bool> TEST_ENTRY;
+struct TEST_INFO {
+ bool wantedError;
+ bool actualError; // Parser error status
+ bool stdException; // Parser throws an std execption
+ bool otherException; // Parser throws another exception
+ std::string message; // Parser error message
+};
+
+class RULES_PARSER_TESTER : public std::unary_function<std::pair<std::string, bool>, void> {
+public:
+ RULES_PARSER_TESTER(RULES_PARSER & p) : parser(p),
+ testLog(),
+ testResult(),
+ result(true)
+ {
+ };
+ ~RULES_PARSER_TESTER()
+ {
+ PrintLog();
+ if (result)
+ exit(EXIT_SUCCESS);
+ exit(EXIT_FAILURE);
+ }
+ void operator()(const std::pair<std::string, bool> & entry)
+ {
+ testLog[entry.first].wantedError = entry.second;
+ testLog[entry.first].actualError = false;
+ testLog[entry.first].stdException = false;
+ testLog[entry.first].otherException = false;
+ testLog[entry.first].message = "";
+ testResult[entry.first] = true;
+ try
+ {
+ parser.SetFile(entry.first);
+ }
+ catch (std::exception & ex)
+ {
+ testLog[entry.first].stdException = true;
+ testResult[entry.first] &= false;
+ }
+ catch (...)
+ {
+ testLog[entry.first].otherException = true;
+ testResult[entry.first] &= false;
+ }
+ testLog[entry.first].actualError = parser.IsError();
+ testLog[entry.first].message = parser.ErrorMsg();
+ testResult[entry.first] &= (parser.IsError() == entry.second);
+ result &= testResult[entry.first];
+ };
+
+ void PrintLog()
+ {
+ std::cout << "RULES_PARSER_TESTER results:\n";
+ std::cout << "-----------------------------------------------------------------\n";
+ std::map<std::string, bool>::const_iterator it;
+ for (it = testResult.begin(); it != testResult.end(); ++it)
+ {
+ std::cout << "File: '" << it->first << "'\t"
+ << "Correct: " << testLog[it->first].wantedError << "\t"
+ << "Actual:" << testLog[it->first].actualError << "\t"
+ << "STD exceptions: " << testLog[it->first].stdException << "\t"
+ << "Other exceptions: " << testLog[it->first].otherException << "\t"
+ << "Result: " << it->second << "\n";
+ if (!testLog[it->first].message.empty())
+ {
+ std::cout << "Messages: \n" << testLog[it->first].message << "\n";
+ }
+ }
+ std::cout << "-----------------------------------------------------------------\n";
+ std::cout << "Final result: " << (result ? "passed" : "failed") << std::endl;
+ }
+
+ bool Result() const { return result; };
+private:
+ RULES_PARSER & parser;
+ std::map<std::string, TEST_INFO> testLog;
+ std::map<std::string, bool> testResult;
+ bool result;
+};
+
+int main(int argc, char ** argv)
+{
+RULES_PARSER parser;
+std::map<std::string, bool> tests;
+
+tests["./test_rules"] = false;
+tests["./rules"] = false;
+tests["./test_rules_bad_address"] = true;
+tests["./test_rules_bad_port"] = true;
+tests["./test_rules_bad_mask"] = true;
+tests["./test_rules_bad_proto"] = true;
+tests["./test_rules_bad_dir_prefix"] = true;
+tests["./test_rules_bad_dir_range"] = true;
+tests["./test_rules_bad_dir"] = true;
+
+/*parser.SetFile("./rules");
+std::cout << parser.ErrorMsg() << std::endl;*/
+
+// TODO: find errors and write checks for regression
+
+std::for_each(tests.begin(),
+ tests.end(),
+ RULES_PARSER_TESTER(parser));
+
+return EXIT_FAILURE;
+}
--- /dev/null
+ | ips | pendingPackets| sessions | ip2sessions | rules |
+________________|_______________|_______________|_______________|_______________|_______________|
+SetRules | | | | | w |
+________________|_______________|_______________|_______________|_______________|_______________|
+AddPacket | r | w | | | |
+________________|_______________|_______________|_______________|_______________|_______________|
+AddIP | w | | | | |
+________________|_______________|_______________|_______________|_______________|_______________|
+GetIP | | | w | r | |
+________________|_______________|_______________|_______________|_______________|_______________|
+DeleteIP | w | | w | w | |
+________________|_______________|_______________|_______________|_______________|_______________|
+Process | | w | w | w | r |
+________________|_______________|_______________|_______________|_______________|_______________|
--- /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>
+ */
+
+ /*
+ $Revision: 1.3 $
+ $Date: 2009/04/10 14:14:49 $
+ $Author: faust $
+ */
+
+
+#ifndef __TC_PACKETS_H__
+#define __TC_PACKETS_H__
+
+#include <netinet/ip.h>
+
+#ifdef HAVE_STDINT
+ #include <stdint.h>
+#else
+ #ifdef HAVE_INTTYPES
+ #include <inttypes.h>
+ #else
+ #error "You need either stdint.h or inttypes.h to compile this!"
+ #endif
+#endif
+
+namespace STG
+{
+
+ //-----------------------------------------------------------------------------
+ /*
+ * Session identifier
+ * A session is an amount of bytes transfered in one direction between two
+ * fixed addresses by one protocol.
+ * In case of UDP/TCP session is also identified by ports.
+ */
+ struct SESSION_ID
+ {
+ SESSION_ID()
+ : saddr(0),
+ daddr(0),
+ sport(0),
+ dport(0),
+ proto(0)
+ {
+ }
+
+ SESSION_ID(const iphdr & ipHdr, uint16_t sp, uint16_t dp)
+ : saddr(ipHdr.saddr),
+ daddr(ipHdr.daddr),
+ sport(sp),
+ dport(dp),
+ proto(ipHdr.protocol)
+ {
+ }
+
+ uint32_t saddr;
+ uint32_t daddr;
+ uint16_t sport;
+ uint16_t dport;
+ uint8_t proto;
+
+ bool operator ==(const SESSION_ID & rval)
+ {
+ return saddr == rval.saddr &&
+ sport == rval.sport &&
+ daddr == rval.daddr &&
+ dport == rval.dport &&
+ proto == rval.proto;
+ }
+ };
+ //-----------------------------------------------------------------------------
+ /*
+ * Ordering functor to use SESSION_ID as key-type in maps
+ */
+ struct SESSION_LESS
+ : public std::binary_function<SESSION_ID, SESSION_ID, bool> {
+ bool operator()(const SESSION_ID & lval, const SESSION_ID & rval) const
+ {
+ if (lval.saddr > rval.saddr)
+ return false;
+ if (lval.saddr < rval.saddr)
+ return true;
+ if (lval.daddr > rval.daddr)
+ return false;
+ if (lval.daddr < rval.daddr)
+ return true;
+ if (lval.sport > rval.sport)
+ return false;
+ if (lval.sport < rval.sport)
+ return true;
+ if (lval.dport > rval.dport)
+ return false;
+ if (lval.dport < rval.dport)
+ return true;
+ if (lval.proto > rval.proto)
+ return false;
+ if (lval.proto < rval.proto)
+ return true;
+ return false;
+ };
+ };
+ //-----------------------------------------------------------------------------
+ /*
+ * A packet in the incoming queue
+ * Can create a new session or be attached to an existing one
+ */
+ struct PENDING_PACKET : public SESSION_ID
+ {
+ PENDING_PACKET()
+ {
+ }
+ PENDING_PACKET(const iphdr & ipHdr, uint16_t sp, uint16_t dp)
+ : SESSION_ID(ipHdr, sp, dp),
+ length(ipHdr.tot_len),
+ direction(FOREIGN)
+ {
+ }
+
+ uint16_t length;
+ enum DIRECTION
+ {
+ INCOMING = 0, // From outer world to user
+ OUTGOING, // From user to outer world
+ LOCAL, // From user to user
+ FOREIGN // From outer world to outer world
+ } direction;
+ };
+ //-----------------------------------------------------------------------------
+ /*
+ * Session length and meta-information
+ * Used to identify data cost
+ */
+ struct SESSION_DATA
+ {
+ SESSION_DATA()
+ {
+ dir = -1; // NULL direction
+ length = 0;
+ };
+
+ SESSION_DATA(const SESSION_DATA & sp)
+ {
+ dir = sp.dir;
+ length = sp.length;
+ };
+
+ int dir;
+ uint32_t length;
+ };
+ //-----------------------------------------------------------------------------
+ /*
+ * User-related types
+ */
+ typedef std::pair<SESSION_ID, SESSION_DATA> TRAFF_ITEM;
+ typedef std::list<TRAFF_ITEM> TRAFF_DATA;
+
+}
+
+#endif
--- /dev/null
+/*
+ * Network:
+ * - server: 192.168.0.1
+ * - user A: 192.168.0.2
+ * - user B: 192.168.0.3
+ *
+ * External resources:
+ * - host 1: 216.239.59.104
+ * - host 2: 72.14.221.104
+ * - host 3: 66.249.93.104
+ * - host 4: 195.5.61.68
+ *
+ * Directions:
+ * - Local: ALL 192.168.0.0/24
+ * - DNS: TCP_UDP 195.5.61.68/32:53
+ * - FTP: TCP 129.22.8.159/32:20-21
+ * - World: ALL 0.0.0.0/0
+ *
+ */
+
+
+
+#include <iostream>
+#include <algorithm>
+#include <functional>
+
+#include <arpa/inet.h>
+#include <netinet/ip.h>
+#include <sys/time.h>
+
+#include "rules.h"
+#include "traffcounter.h"
+#include "logger.h"
+
+using namespace std;
+using namespace STG;
+
+class StatPrinter: public unary_function<const TRAFF_ITEM &, void> {
+public:
+ void operator()(const TRAFF_ITEM & item) const
+ {
+ LOG_IT << inet_ntoa(*(in_addr *)(&item.first.saddr));
+ cout << ":" << item.first.sport;
+ cout << " -> " << inet_ntoa(*(in_addr *)(&item.first.daddr));
+ cout << ":" << item.first.dport;
+ cout << "\tproto: " << item.first.proto;
+ cout << "\tlength: " << item.second.length;
+ cout << endl;
+ }
+};
+
+STGLogger log;
+
+struct PACKET
+{
+ iphdr hdr;
+ uint16_t sport;
+ uint16_t dport;
+};
+
+RULE MakeRule(const string & ip,
+ const string & mask,
+ uint16_t port1,
+ uint16_t port2,
+ int proto,
+ int dir)
+{
+ RULE rule;
+
+ rule.ip = inet_addr(ip.c_str());
+ rule.mask = inet_addr(mask.c_str());
+ rule.port1 = port1;
+ rule.port2 = port2;
+ rule.proto = proto;
+ rule.dir = dir;
+
+ return rule;
+}
+
+RULES PrepareRules()
+{
+ RULES rules;
+ RULE local(MakeRule("192.168.0.0",
+ "255.255.255.0",
+ 0,
+ 65535,
+ -1,
+ 0));
+ RULE dns(MakeRule("195.5.61.68",
+ "255.255.255.255",
+ 53,
+ 53,
+ -1,
+ 1));
+ RULE ftp(MakeRule("129.22.8.159",
+ "255.255.255.255",
+ 20,
+ 21,
+ -1,
+ 2));
+ RULE world(MakeRule("0.0.0.0",
+ "0.0.0.0",
+ 0,
+ 65535,
+ -1,
+ 3));
+
+ rules.push_back(local);
+
+ rules.push_back(dns);
+
+ rules.push_back(ftp);
+
+ rules.push_back(world);
+
+ return rules;
+}
+
+iphdr MakePacket(const string & from,
+ const string & to,
+ int proto,
+ uint16_t length)
+{
+ iphdr hdr;
+
+ hdr.ihl = 5;
+ hdr.version = 4;
+ hdr.tos = 0;
+ hdr.tot_len = length;
+ hdr.id = 0;
+ hdr.frag_off = 50;
+ hdr.ttl = 64;
+ hdr.protocol = proto;
+ hdr.check = 0;
+ hdr.saddr = inet_addr(from.c_str());
+ hdr.daddr = inet_addr(to.c_str());
+
+ return hdr;
+}
+
+void PrepareTraffic(vector<PACKET> & pckts,
+ const iphdr & skel,
+ uint16_t sport,
+ uint16_t dport,
+ uint32_t in,
+ uint32_t out,
+ int packets)
+{
+ PACKET inpacket;
+ PACKET outpacket;
+
+ inpacket.hdr = skel;
+ outpacket.hdr = skel;
+
+ outpacket.hdr.saddr ^= outpacket.hdr.daddr;
+ outpacket.hdr.daddr ^= outpacket.hdr.saddr;
+ outpacket.hdr.saddr ^= outpacket.hdr.daddr;
+
+ inpacket.sport = sport;
+ inpacket.dport = dport;
+ outpacket.sport = dport;
+ outpacket.dport = sport;
+
+ inpacket.hdr.tot_len = in / packets;
+ outpacket.hdr.tot_len = out / packets;
+
+ for (int i = 0; i < packets; ++i) {
+ //inpacket.hdr.daddr = outpacket.hdr.saddr = rand() * 32768 + rand();
+ pckts.push_back(inpacket);
+ pckts.push_back(outpacket);
+ }
+}
+
+struct TC_TESTER : public unary_function<const PACKET &, void>
+{
+public:
+ TC_TESTER(TRAFFCOUNTER & t)
+ : tc(t)
+ {}
+
+ void operator () (const PACKET & p)
+ {
+ tc.AddPacket(p.hdr, p.sport, p.dport);
+ }
+private:
+ TRAFFCOUNTER & tc;
+};
+
+int main()
+{
+ RULES rules(PrepareRules());
+
+ TRAFFCOUNTER tc;
+
+ vector<PACKET> packets;
+
+ tc.SetRules(rules);
+
+ if (tc.Start()) {
+ LOG_IT << "::main() Error: traffcounter not started" << endl;
+ return EXIT_FAILURE;
+ }
+
+ tc.AddIP(inet_addr("192.168.0.1")); // Server
+ tc.AddIP(inet_addr("192.168.0.2")); // User A
+ tc.AddIP(inet_addr("192.168.0.3")); // User B
+
+ for (int i = 0; i < 10000; ++i) {
+ tc.AddIP(rand() * 32768 + rand());
+ }
+
+ /*
+ * A -> S
+ * S -> A
+ * A -> B
+ * B -> A
+ * A -> h1
+ * h1 -> A
+ * A -> h2
+ * h2 -> A
+ * A -> h3
+ * h3 -> A
+ * A -> h4
+ * h4 -> A
+ */
+
+ timeval tv_from;
+ timeval tv_to;
+ gettimeofday(&tv_from, NULL);
+ // S - local, A - local
+ PrepareTraffic(packets, MakePacket("192.168.0.2", "192.168.0.1", 6, 0), 3215, 20, 1024 * 1024, 2048 * 1024, 512 * 2);
+ // S - local, B - local
+ PrepareTraffic(packets, MakePacket("192.168.0.3", "192.168.0.1", 6, 0), 5432, 22, 2048 * 1024, 1024 * 1024, 512 * 2);
+ // A - local, B - local
+ PrepareTraffic(packets, MakePacket("192.168.0.3", "192.168.0.2", 6, 0), 9875, 21, 2048 * 1024, 2048 * 1024, 512 * 2);
+ // A - DNS
+ //PrepareTraffic(packets, MakePacket("192.168.0.2", "195.5.61.68", 6, 0), 4521, 53, 1024 * 1024, 2048 * 1024, 512 * 2);
+ // A - World
+ //PrepareTraffic(packets, MakePacket("192.168.0.2", "195.5.61.68", 6, 0), 4521, 80, 1024 * 1024, 2048 * 1024, 512 * 2);
+ // A - FTP
+ //PrepareTraffic(packets, MakePacket("192.168.0.2", "129.22.8.159", 6, 0), 4522, 20, 512 * 1024, 512 * 1024, 512 * 2);
+ // A - FTP
+ //PrepareTraffic(packets, MakePacket("192.168.0.2", "129.22.8.159", 6, 0), 4522, 21, 512 * 1024, 4096 * 1024, 512 * 2);
+ // B - World
+ //PrepareTraffic(packets, MakePacket("192.168.0.3", "66.249.93.104", 6, 0), 3541, 80, 1024 * 1024, 1024 * 1024, 512 * 2);
+ gettimeofday(&tv_to, NULL);
+
+ uint64_t diff = tv_to.tv_sec - tv_from.tv_sec;
+ diff *= 1000000;
+ diff -= tv_from.tv_usec;
+ diff += tv_to.tv_usec;
+
+ LOG_IT << "::main() Prepared " << packets.size() << " packets by " << diff << " usecs" << endl;
+
+ gettimeofday(&tv_from, NULL);
+ for_each(packets.begin(),
+ packets.end(),
+ TC_TESTER(tc));
+ gettimeofday(&tv_to, NULL);
+
+ diff = tv_to.tv_sec - tv_from.tv_sec;
+ diff *= 1000000;
+ diff -= tv_from.tv_usec;
+ diff += tv_to.tv_usec;
+
+ LOG_IT << "::main() Recorded " << packets.size() << " packets by " << diff << " usecs" << endl;
+
+ int p;
+ while ((p = tc.PendingCount())) {
+ LOG_IT << "::main() Pending packets: " << p << " at " << time(NULL) << endl;
+ sleep(1);
+ }
+
+ TRAFF_DATA data;
+
+ tc.DeleteIP(inet_addr("192.168.0.1"), &data);
+ for_each(data.begin(),
+ data.end(),
+ StatPrinter());
+ data.erase(data.begin(), data.end());
+ tc.DeleteIP(inet_addr("192.168.0.2"), &data);
+ for_each(data.begin(),
+ data.end(),
+ StatPrinter());
+ data.erase(data.begin(), data.end());
+ tc.DeleteIP(inet_addr("192.168.0.3"), &data);
+ for_each(data.begin(),
+ data.end(),
+ StatPrinter());
+ data.erase(data.begin(), data.end());
+
+ if (tc.Stop()) {
+ LOG_IT << "::main() Error: traffcounter not stopped" << endl;
+ return EXIT_FAILURE;
+ }
+
+ LOG_IT << "::main() Sessions: " << tc.SessionsCount() << endl;
+ LOG_IT << "::main() Cache hits: " << tc.CacheHits() << endl;
+ LOG_IT << "::main() Cache misses: " << tc.CacheMisses() << endl;
+ LOG_IT << "::main() Stream quality: " << tc.StreamQuality() << endl;
+
+ return EXIT_SUCCESS;
+}
--- /dev/null
+# foo bar baz
+
+UDP 10.0.0.0/24:1024-65535 DIR0 #blah-blah-blah
+
+TCP 192.168.1.1:21-22 DIR1
+
+ALL 192.168.2.0/16 DIR2
+
+GRE 192.168.3.0/24 NULL
+
+ALL 0.0.0.0 DIR3
+
--- /dev/null
+
+UDP 10.0.0.0/24:1024-65535 DIR0
+
+TCP 192.168.1.1:21-22 DIR1
+ALL 192.168.2.0/16 DIR2
+ALL 0.0.0.a DIR3
+
--- /dev/null
+
+UDP 10.0.0.0/24:1024-65535 DIR0
+
+TCP 192.168.1.1:21-22 DIRA
+ALL 192.168.2.0/16 DIR2
+ALL 0.0.0.0 DIR3
+
--- /dev/null
+
+UDP 10.0.0.0/24:1024-65535 DIR0
+
+TCP 192.168.1.1:21-22 WOR1
+ALL 192.168.2.0/16 DIR2
+ALL 0.0.0.0 DIR3
+
+
--- /dev/null
+
+
+UDP 10.0.0.0/24:1024-65535 DIR0
+
+TCP 192.168.1.1:21-22 DIR8945298579834755982745892734958
+ALL 192.168.2.0/16 DIR2
+ALL 0.0.0.0 DIR3
+
--- /dev/null
+
+UDP 10.0.0.0/2a:1024-65535 DIR0
+
+TCP 192.168.1.1:21-22 DIR1
+ALL 192.168.2.0/16 DIR2
+ALL 0.0.0.0 DIR3
+
--- /dev/null
+
+UDP 10.0.0.0/24:1024-65535 DIR0
+
+TCP 192.168.1.1:21-2a DIR1
+ALL 192.168.2.0/16 DIR2
+ALL 0.0.0.0 DIR3
+
--- /dev/null
+
+UDP 10.0.0.0/24:1024-65535 DIR0
+
+TCP 192.168.1.1:21-22 DIR1
+QMTSP 192.168.2.0/16 DIR2
+ALL 0.0.0.0 DIR3
+
--- /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>
+ */
+
+/*
+ $Revision: 1.5 $
+ $Date: 2009/10/12 08:43:32 $
+ $Author: faust $
+ */
+
+#include <csignal>
+#include <cassert>
+#include <algorithm>
+
+#include "traffcounter.h"
+#include "logger.h"
+#include "lock.h"
+#include "utils.h"
+
+//-----------------------------------------------------------------------------
+STG::TRAFFCOUNTER::TRAFFCOUNTER()
+ : rulesFinder(),
+ pendingPackets(),
+ sessions(),
+ cacheHits(0),
+ cacheMisses(0),
+ pendingCount(0),
+ maxPending(0),
+ ip2sessions(),
+ stopped(true),
+ running(false)
+{
+LOG_IT << "TRAFFCOUNTER::TRAFFCOUNTER()\n";
+pthread_mutex_init(&sessionMutex, NULL);
+pthread_mutex_init(&pendingMutex, NULL);
+pthread_mutex_init(&ipMutex, NULL);
+pthread_mutex_init(&rulesMutex, NULL);
+pthread_cond_init(&pendingCond, NULL);
+}
+//-----------------------------------------------------------------------------
+STG::TRAFFCOUNTER::~TRAFFCOUNTER()
+{
+LOG_IT << "TRAFFCOUNTER::~TRAFFCOUNTER()\n";
+pthread_cond_destroy(&pendingCond);
+pthread_mutex_destroy(&rulesMutex);
+pthread_mutex_destroy(&ipMutex);
+pthread_mutex_destroy(&pendingMutex);
+pthread_mutex_destroy(&sessionMutex);
+}
+//-----------------------------------------------------------------------------
+// Starting processing thread
+bool STG::TRAFFCOUNTER::Start()
+{
+LOG_IT << "TRAFFCOUNTER::Start()\n";
+
+if (running)
+ return false;
+
+running = true;
+stopped = true;
+
+if (pthread_create(&thread, NULL, Run, this))
+ {
+ LOG_IT << "TRAFFCOUNTER::Start() Error: Cannot start thread!\n";
+ return true;
+ }
+
+return false;
+}
+//-----------------------------------------------------------------------------
+bool STG::TRAFFCOUNTER::Stop()
+{
+LOG_IT << "TRAFFCOUNTER::Stop()\n";
+LOG_IT << "maxPending: " << maxPending << std::endl;
+
+if (!running)
+ return false;
+
+running = false;
+// Awake thread
+pthread_cond_signal(&pendingCond);
+
+//5 seconds to thread stops itself
+for (int i = 0; i < 25 && !stopped; ++i)
+ {
+ usleep(200000);
+ }
+
+//after 5 seconds waiting thread still running. now kill it
+if (!stopped)
+ {
+ LOG_IT << "TRAFFCOUNTER::Stop() Killing thread\n";
+ if (pthread_kill(thread, SIGINT))
+ {
+ return true;
+ }
+ LOG_IT << "TRAFFCOUNTER::Stop() Thread killed\n";
+ }
+
+return false;
+}
+//-----------------------------------------------------------------------------
+double STG::TRAFFCOUNTER::StreamQuality() const
+{
+if (!cacheHits && !cacheMisses)
+ {
+ return 0;
+ }
+
+double quality = cacheHits;
+return quality / (quality + cacheMisses);
+}
+//-----------------------------------------------------------------------------
+void STG::TRAFFCOUNTER::AddPacket(const iphdr & ipHdr, uint16_t sport, uint16_t dport)
+{
+/*
+ * Intersects with AddIP (from user thread), DeleteIP (from user thread) and
+ * Process (internal thread). AddPacket is calling from capturer's thread
+ *
+ * ips is affected by AddIP (logarithmic lock time) and
+ * DeleteIP (from user thread)
+ *
+ * May be locked by AddIP or DeleteIP (from user thread)
+ *
+ * Lock AddIP (user thread) or DeleteIP (user thread)
+ * Logarithmic lock time
+ */
+
+bool srcExists;
+bool dstExists;
+
+ {
+ SCOPED_LOCK lock(ipMutex);
+ srcExists = std::binary_search(ips.begin(), ips.end(), ipHdr.saddr);
+ dstExists = std::binary_search(ips.begin(), ips.end(), ipHdr.daddr);
+ }
+
+if (!srcExists &&
+ !dstExists)
+ {
+ // Just drop the packet
+ return;
+ }
+
+STG::PENDING_PACKET p(ipHdr, sport, dport);
+
+// Packet classification
+if (srcExists)
+ {
+ if (dstExists)
+ {
+ // Both src and dst are countable
+ p.direction = PENDING_PACKET::LOCAL;
+ }
+ else
+ {
+ // Src is countable
+ p.direction = PENDING_PACKET::OUTGOING;
+ }
+ }
+else
+ {
+ if (dstExists)
+ {
+ // Dst is countable
+ p.direction = PENDING_PACKET::INCOMING;
+ }
+ else
+ {
+ assert(0);
+ // Not src nor dst are countable
+ p.direction = PENDING_PACKET::FOREIGN;
+ }
+ }
+
+/*
+ * pendingPackets is affected by Process (from internal thread)
+ *
+ * May be locked by Process (internal thread)
+ *
+ * Lock Process (internal thread)
+ * Constant lock time
+ */
+SCOPED_LOCK lock(pendingMutex);
+pendingPackets.push_back(p);
+pendingCount++;
+#ifdef STATISTIC
+if (pendingCount > maxPending)
+ maxPending = pendingCount;
+#endif
+pthread_cond_signal(&pendingCond);
+
+}
+//-----------------------------------------------------------------------------
+void STG::TRAFFCOUNTER::AddIP(uint32_t ip)
+{
+/*
+ * AddIP is calling from users and affect DeleteIP and AddPacket.
+ * DeleteIP cannot be called concurrently with AddIP - it's the same
+ * thread. AddPacket is calling from capturer's thread - concurrently
+ * with AddIP.
+ *
+ * May be locked by AddPacket (from capturer's thread)
+ * Logarithmic lock time
+ *
+ * Lock AddPacket (capturer's thread)
+ * Logarithmic lock time
+ */
+SCOPED_LOCK lock(ipMutex);
+IP_ITER it(std::lower_bound(ips.begin(), ips.end(), ip));
+
+if (it != ips.end() && *it == ip)
+ {
+ return;
+ }
+// Insertion
+ips.insert(it, ip);
+}
+//-----------------------------------------------------------------------------
+void STG::TRAFFCOUNTER::DeleteIP(uint32_t ip, STG::TRAFF_DATA * traff)
+{
+/*
+ * DeleteIP is calling from users and affect AddIP, AddPacket, GetIP and
+ * Process. AddIP and GetIP cannot be called concurrently with DeleteIP - it's
+ * the same thread. AddPacket is calling from capturer's thread - concurrently
+ * with DeleteIP. Process is calling from internal thread - concurrently with
+ * DeleteIP.
+ *
+ * May be locked by AddPacket (from capturer's thread)
+ * Logarithmic lock time
+ *
+ * Lock AddPacket (capturer's thread)
+ * Logarithmic lock time
+ */
+
+ {
+ SCOPED_LOCK lock(ipMutex);
+
+ IP_ITER it(std::lower_bound(ips.begin(), ips.end(), ip));
+ if (it == ips.end())
+ {
+ return;
+ }
+ if (*it != ip)
+ {
+ return;
+ }
+
+ ips.erase(it);
+ }
+
+// Get sessions for this ip
+std::pair<INDEX_ITER,
+ INDEX_ITER> range;
+
+SCOPED_LOCK lock(sessionMutex);
+range = ip2sessions.equal_range(ip);
+std::list<INDEX_ITER> toDelete;
+
+// Lock session growing
+for (INDEX_ITER it = range.first; it != range.second; ++it)
+ {
+ traff->push_back(STG::TRAFF_ITEM(it->second->first, it->second->second));
+
+ // Include self
+ toDelete.push_back(it);
+
+ /*if (ip == it->second->first.saddr)
+ {
+ toDelete.push_back(it->second->second.dIdx);
+ }
+ else
+ {
+ toDelete.push_back(it->second->second.sIdx);
+ }*/
+
+ --it->second->second.refCount;
+
+ // Remove session
+ /*
+ * Normally we will lock here only in case of session between
+ * two users from ips list
+ */
+ if (!it->second->second.refCount)
+ {
+ sessions.erase(it->second);
+ }
+ }
+
+// Remove indexes
+for (std::list<INDEX_ITER>::iterator it = toDelete.begin();
+ it != toDelete.end();
+ ++it)
+ {
+ ip2sessions.erase(*it);
+ }
+}
+//-----------------------------------------------------------------------------
+void STG::TRAFFCOUNTER::GetIP(uint32_t ip, STG::TRAFF_DATA * traff)
+{
+/*
+ * Normally we will lock here only in case of session between
+ * two users from ips list
+ */
+std::pair<INDEX_ITER,
+ INDEX_ITER> range;
+
+SCOPED_LOCK lock(sessionMutex);
+range = ip2sessions.equal_range(ip);
+std::list<INDEX_ITER> toDelete;
+
+// TODO: replace with foreach
+for (SESSION_INDEX::iterator it = range.first;
+ it != range.second;
+ ++it)
+ {
+ traff->push_back(STG::TRAFF_ITEM(it->second->first, it->second->second));
+ toDelete.push_back(it);
+ --it->second->second.refCount;
+ if (!it->second->second.refCount)
+ {
+ sessions.erase(it->second);
+ }
+ }
+
+for (std::list<INDEX_ITER>::iterator it = toDelete.begin();
+ it != toDelete.end();
+ ++it)
+ {
+ ip2sessions.erase(*it);
+ }
+}
+//-----------------------------------------------------------------------------
+void * STG::TRAFFCOUNTER::Run(void * data)
+{
+STG::TRAFFCOUNTER * tc = static_cast<STG::TRAFFCOUNTER *>(data);
+tc->stopped = false;
+
+while (tc->running)
+ {
+ STG::PENDING_PACKET packet;
+ {
+ SCOPED_LOCK lock(tc->pendingMutex);
+ if (tc->pendingPackets.empty())
+ {
+ pthread_cond_wait(&tc->pendingCond, &tc->pendingMutex);
+ }
+ if (!tc->running)
+ {
+ break;
+ }
+ packet = *tc->pendingPackets.begin();
+ tc->pendingPackets.pop_front();
+ --tc->pendingCount;
+ }
+ tc->Process(packet);
+ }
+
+tc->stopped = true;
+return NULL;
+}
+//-----------------------------------------------------------------------------
+void STG::TRAFFCOUNTER::Process(const STG::PENDING_PACKET & p)
+{
+// Bypass on stop
+if (!running)
+ return;
+
+// Fail on foreign packets
+if (p.direction == PENDING_PACKET::FOREIGN) {
+ assert(0);
+}
+
+// Searching a new packet in a tree.
+SESSION_ITER si;
+ {
+ SCOPED_LOCK lock(sessionMutex);
+ si = sessions.find(STG::SESSION_ID(p));
+ }
+
+// Packet found - update length and time
+if (si != sessions.end())
+ {
+ // Grow session
+ SCOPED_LOCK lock(sessionMutex);
+ si->second.length += p.length;
+ ++cacheHits;
+ return;
+ }
+
+++cacheMisses;
+
+// Packet not found - add new packet
+
+// This packet is alowed to create session
+STG::SESSION_ID sid(p);
+SESSION_FULL_DATA sd;
+
+// Identify a packet
+ {
+ SCOPED_LOCK lock(rulesMutex);
+ sd.dir = rulesFinder.GetDir(p);
+ }
+
+sd.length = p.length;
+
+if (p.direction == PENDING_PACKET::LOCAL)
+ {
+ sd.refCount = 2;
+ }
+else
+ {
+ sd.refCount = 1;
+ }
+
+// Create a session
+std::pair<SESSION_ITER,
+ bool> sIt(sessions.insert(std::make_pair(sid, sd)));
+ {
+ SCOPED_LOCK lock(sessionMutex);
+ std::pair<SESSION_ITER,
+ bool> sIt(sessions.insert(std::make_pair(sid, sd)));
+
+ // Create an indexes
+ sIt.first->second.sIdx = ip2sessions.insert(std::make_pair(p.saddr, sIt.first));
+ sIt.first->second.dIdx = ip2sessions.insert(std::make_pair(p.daddr, sIt.first));
+ }
+
+}
+//-----------------------------------------------------------------------------
+void STG::TRAFFCOUNTER::SetRules(const STG::RULES & data)
+{
+/*
+ * SetRules is calling from outside internel thread. Process is calling
+ * from internal thread and calls DeterminateDir which use rules data.
+ *
+ * May be locked by DeterminateDir (Process) from internal thread.
+ *
+ * Lock DeterminateDir (Process) - internal thread.
+ * Linear lock time
+ */
+SCOPED_LOCK lock(rulesMutex);
+rulesFinder.SetRules(data);
+}
--- /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>
+ */
+
+ /*
+ $Revision: 1.3 $
+ $Date: 2009/04/10 14:15:46 $
+ $Author: faust $
+ */
+
+
+#ifndef TRAFFCOUNTER_H
+#define TRAFFCOUNTER_H
+
+#include <pthread.h>
+#include <netinet/ip.h>
+
+#ifdef HAVE_STDINT
+ #include <stdint.h>
+#else
+ #ifdef HAVE_INTTYPES
+ #include <inttypes.h>
+ #else
+ #error "You need either stdint.h or inttypes.h to compile this!"
+ #endif
+#endif
+
+#include <ctime>
+#include <list>
+#include <vector>
+#include <map>
+
+#include "rules.h"
+#include "rules_finder.h"
+#include "tc_packets.h"
+#include "user_tc_iface.h"
+#include "capturer_tc_iface.h"
+
+#define PACKET_TIMEOUT 300
+
+namespace STG
+{
+
+ class TRAFFCOUNTER : public IUSER_TC, public ICAPTURER_TC
+ {
+ public:
+ TRAFFCOUNTER();
+ ~TRAFFCOUNTER();
+
+ void SetRules(const RULES & data);
+
+ bool Start();
+ bool Stop();
+
+ // Capturer API
+ void AddPacket(const iphdr & ipHdr, uint16_t sport, uint16_t dport);
+
+ // User API
+ void AddIP(uint32_t ip);
+ void DeleteIP(uint32_t ip, TRAFF_DATA * traff);
+ void GetIP(uint32_t ip, TRAFF_DATA * traff);
+
+ /*
+ * Stream quality represents a "scatterness" of data stream
+ * When sessions represend a large amount of information - it's a good
+ * stream. Most of common-use protocols (HTTP, FTP, etc.) shows a good
+ * stream quality.
+ * When there are a lot of packet that creates a new streams - it's a
+ * bad stream. p2p traffic has a bias to show a bad stream quality.
+ */
+ double StreamQuality() const;
+ uint64_t PendingCount() const { return pendingCount; };
+ uint64_t SessionsCount() const { return sessions.size(); };
+ uint64_t IndexesCount() const { return ip2sessions.size(); };
+ uint64_t CacheHits() const { return cacheHits; };
+ uint64_t CacheMisses() const { return cacheMisses; };
+
+ private:
+ static void * Run(void * data);
+
+ void Process(const PENDING_PACKET & p);
+
+ RULES_FINDER rulesFinder;
+
+ /*
+ * SESSION_INDEX: ip -> SESSION_ITER
+ * SESSIONS: SESSION_ID -> SESSION_DATA
+ * -> SESSION_INDEX (saddr)
+ * -> SESSION_INDEX (daddr)
+ */
+ struct SESSION_FULL_DATA; // Forward declaration
+ typedef std::map<SESSION_ID, SESSION_FULL_DATA, SESSION_LESS> SESSIONS;
+ typedef SESSIONS::iterator SESSION_ITER;
+ /*
+ * This structure is used to take a fast session access by IP
+ * Normally, one IP can reffer multiple sessions. For each data stream there
+ * are 2 sessions: incoming data and outgoing data.
+ */
+ typedef std::multimap<uint32_t, SESSION_ITER> SESSION_INDEX;
+ typedef SESSION_INDEX::iterator INDEX_ITER;
+ /*
+ * Append session meta-information with back-indexes
+ * In process of removing IP from TRAFFCOUNTER we need to remove indexes of
+ * sessions, reffered by this IP. To prevent slow searching by index tree we
+ * use 2 back-references: for source and destination IP.
+ */
+ struct SESSION_FULL_DATA : public SESSION_DATA
+ {
+ INDEX_ITER sIdx; // Back reference for fast index removing
+ INDEX_ITER dIdx; // Back reference for fast index removing
+ int refCount; // Reference count for packet removing
+ };
+
+ std::list<PENDING_PACKET> pendingPackets;
+
+ SESSIONS sessions; // A map with sessions data
+
+ /*
+ * When pending packet appends a session - it's a "cache hit"
+ * When pending packet creates a new session - it's a "cache miss"
+ */
+ uint64_t cacheHits;
+ uint64_t cacheMisses;
+ uint64_t pendingCount;
+ uint64_t maxPending;
+
+ SESSION_INDEX ip2sessions; // IP index for sessions data
+
+ /*
+ * A sorted vector of allowed/disallowed ips
+ */
+ std::vector<uint32_t> ips;
+ typedef std::vector<uint32_t>::iterator IP_ITER;
+
+ bool stopped;
+ bool running;
+
+ mutable pthread_mutex_t sessionMutex; // For sessions
+ mutable pthread_mutex_t pendingMutex; // For pendinPackets
+ mutable pthread_cond_t pendingCond; //
+ mutable pthread_mutex_t ipMutex; // For ip list
+ mutable pthread_mutex_t rulesMutex; // For rules list
+ pthread_t thread;
+
+ };
+
+}
+
+#endif //TRAFFCOUNTER_H
--- /dev/null
+#ifndef __USER_TC_IFACE_H__
+#define __USER_TC_IFACE_H__
+
+#ifdef HAVE_STDINT
+ #include <stdint.h>
+#else
+ #ifdef HAVE_INTTYPES
+ #include <inttypes.h>
+ #else
+ #error "You need either stdint.h or inttypes.h to compile this!"
+ #endif
+#endif
+
+#include "tc_packets.h"
+
+namespace STG
+{
+
+ class IUSER_TC
+ {
+ public:
+ virtual ~IUSER_TC() {};
+ virtual void AddIP(uint32_t) = 0;
+ virtual void DeleteIP(uint32_t, TRAFF_DATA *) = 0;
+ virtual void GetIP(uint32_t, TRAFF_DATA *) = 0;
+ };
+
+}
+
+#endif
--- /dev/null
+#include <algorithm>
+#include <functional>
+
+#include <iostream>
+#include <cerrno>
+#include <cstring>
+
+#include <arpa/inet.h>
+
+#include "utils.h"
+
+using namespace std;
+
+string STG::ToLower(const string & val, const locale & loc)
+{
+ std::string res;
+ transform(val.begin(),
+ val.end(),
+ back_inserter(res),
+ STG::ToLowerHelper(loc));
+ return res;
+}
+
+string STG::ToUpper(const string & val, const locale & loc)
+{
+ std::string res;
+ transform(val.begin(),
+ val.end(),
+ back_inserter(res),
+ STG::ToUpperHelper(loc));
+ return res;
+}
+
+string STG::Trim(const string & val, const locale & loc)
+{
+ if (val.empty())
+ return std::string();
+ string::const_iterator first(find_if(
+ val.begin(),
+ val.end(),
+ STG::IsNotSpace(loc)));
+ string::const_reverse_iterator last(find_if(
+ val.rbegin(),
+ val.rend(),
+ STG::IsNotSpace(loc)));
+ if (first == val.end())
+ return std::string();
+ return std::string(first, last.base());
+}
+std::string inet_ntostring(uint32_t ip)
+{
+ char buf[INET_ADDRSTRLEN + 1];
+
+ return inet_ntop(AF_INET, &ip, buf, INET_ADDRSTRLEN);
+}
--- /dev/null
+#ifndef __UTILS_H__
+#define __UTILS_H__
+
+#include <string>
+#include <locale>
+
+namespace STG
+{
+
+class IsNotSpace : public std::unary_function<bool, char> {
+public:
+ IsNotSpace(const std::locale & l) : loc(l) {};
+ bool operator() (char c)
+ {
+ return !std::use_facet<casefacet>(loc).is(std::ctype_base::space, c);
+ };
+private:
+ const std::locale & loc;
+
+ typedef std::ctype<char> casefacet;
+};
+
+class ToLowerHelper : public std::unary_function<char, char> {
+public:
+ ToLowerHelper(const std::locale & l) : loc(l) {};
+ char operator() (char c)
+ {
+ return std::tolower(c, loc);
+ };
+private:
+ const std::locale & loc;
+};
+
+class ToUpperHelper : public std::unary_function<char, char> {
+public:
+ ToUpperHelper(const std::locale & l) : loc(l) {};
+ char operator() (char c)
+ {
+ return std::toupper(c, loc);
+ };
+private:
+ const std::locale & loc;
+};
+
+std::string Trim(const std::string & val, const std::locale & loc);
+std::string ToLower(const std::string & val, const std::locale & loc);
+std::string ToUpper(const std::string & val, const std::locale & loc);
+
+inline std::string Trim(const std::string & val)
+ {
+ return Trim(val, std::locale(""));
+ }
+
+inline std::string ToLower(const std::string & val)
+ {
+ return ToLower(val, std::locale(""));
+ }
+
+inline std::string ToUpper(const std::string & val)
+ {
+ return ToUpper(val, std::locale(""));
+ }
+
+}
+
+std::string inet_ntostring(uint32_t ip);
+
+#endif
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.7 2008/03/10 14:00:00 faust Exp $
+###############################################################################
+
+include ../Makefile.conf
+
+.PHONY: all $(STG_LIBS)
+.PHONY: clean install uninstall includes
+all: $(STG_LIBS)
+
+$(STG_LIBS):
+ $(MAKE) $(MAKECMDGOALS) -C $@
+
+includes: all
+
+clean: all
+ rm -f $(DIR_LIB)/*
+
+install: all
+
+uninstall: all
+
--- /dev/null
+###############################################################################
+# $Id: Makefile.in,v 1.28 2009/03/03 15:50:14 faust Exp $
+###############################################################################
+
+include ../../Makefile.conf
+
+PROG = lib$(LIB_NAME).so
+
+ifeq ($(PROT), on)
+DEFS += -DLINPROT
+endif
+
+ifeq ($(DEMO), on)
+DEFS += -DDEMO
+endif
+
+ifeq ($(OS), bsd)
+ ifeq ($(PROT), on)
+ DEFS += -DFREEBDSPROT
+ endif
+MAKE = gmake
+endif
+
+ifeq ($(OS), bsd5)
+ ifeq ($(PROT), on)
+ DEFS += -DFREEBDSPROT
+ endif
+MAKE = gmake
+endif
+
+ifeq ($(STG_TIME), yes)
+DEFS += -DSTG_TIME
+endif
+
+ifneq ($(ADD_DEFS_1),)
+DEFS += $(ADD_DEFS_1)
+endif
+
+SEARCH_DIRS = -I $(DIR_INCLUDE) -I ./
+
+OBJS = $(notdir $(patsubst %.cpp, %.o, $(patsubst %.c, %.o, $(SRCS))))
+
+INST_INCS = $(addprefix $(DIR_INCLUDE)/, $(notdir $(INCS)))
+INST_LIBS = $(DIR_LIB)/lib$(LIB_NAME)
+
+CXXFLAGS += -fPIC
+LDFLAGS += -shared -Wl,-rpath,$(PREFIX)/usr/lib/stg
+
+ifneq ($(ADD_CXXFLAGS_1),)
+CXXFLAGS += $(ADD_CXXFLAGS_1)
+endif
+
+vpath %.so $(DIR_LIB)
+
+all: $(PROG)
+
+$(PROG): $(OBJS) $(STGLIBS)
+ g++ $(LDFLAGS) -Wl,-soname,$(PROG) $^ $(LIBS) -o $(PROG) -L $(DIR_LIB)
+ ar rc lib$(LIB_NAME).a $(OBJS)
+ ranlib lib$(LIB_NAME).a
+ cp *.so $(DIR_LIB)
+ cp *.a $(DIR_LIB)
+
+includes: $(INCS)
+ cp -p $(INCS) $(DIR_INCLUDE)
+
+clean:
+ rm -f deps $(PROG) *.o *.a *.so tags *.*~
+ for file in $(INCS); do \
+ rm -f $(DIR_INCLUDE)/$$file; \
+ done
+
+install: $(PROG)
+ mkdir -m $(BIN_MODE) -p $(PREFIX)/usr/lib/stg
+ install -m $(BIN_MODE) -o $(OWNER) -s $(PROG) $(PREFIX)/usr/lib/stg/$(PROG)
+
+uninstall:
+ rm -f $(PREFIX)/usr/lib/stg/$(PROG)
+
+ifneq ($(MAKECMDGOALS),includes)
+ifneq ($(MAKECMDGOALS),clean)
+ifneq ($(MAKECMDGOALS),uninstall)
+-include deps
+endif
+endif
+endif
+
+deps: $(SRCS) ../../Makefile.conf
+ @>deps ;\
+ for file in $(SRCS); do\
+ echo "`$(CC) $(CXXFLAGS) $(SEARCH_DIRS) $(DEFS) -MM -MG $$file` Makefile ../../Makefile.conf" >> deps ;\
+ echo -e '\t$$(CC) $(CXXFLAGS) $(SEARCH_DIRS) $(DEFS) -c $$<' >> deps ;\
+ done
+
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.9 2010/01/21 13:02:12 faust Exp $
+###############################################################################
+
+include ../../Makefile.conf
+
+LIB_NAME = stg_common
+PROG = lib$(LIB_NAME)
+
+SRCS = debug.c \
+ stg_error.c \
+ common.cpp \
+ stg_strptime.cpp
+
+INCS = debug.h \
+ stg_error.h \
+ common.h
+
+ifneq ($(OS),linux)
+LIBS += -liconv
+endif
+
+include ../Makefile.in
--- /dev/null
+//---------------------------------------------------------------------------
+
+#include <vcl.h>
+#pragma hdrstop
+#define Library
+
+// To add a file to the library use the Project menu 'Add to Project'.
+
+
\ No newline at end of file
--- /dev/null
+<?xml version='1.0' encoding='utf-8' ?>
+<!-- C++Builder XML Project -->
+<PROJECT>
+ <MACROS>
+ <VERSION value="BCB.06.00"/>
+ <PROJECT value="..\..\lib\common.lib"/>
+ <OBJFILES value="common.obj"/>
+ <RESFILES value=""/>
+ <IDLFILES value=""/>
+ <IDLGENFILES value=""/>
+ <DEFFILE value=""/>
+ <RESDEPEN value="$(RESFILES)"/>
+ <LIBFILES value=""/>
+ <LIBRARIES value=""/>
+ <PACKAGES value=""/>
+ <PATHCPP value=".;"/>
+ <PATHPAS value=".;"/>
+ <PATHRC value=".;"/>
+ <PATHASM value=".;"/>
+ <LINKER value="TLib"/>
+ <USERDEFINES value="_DEBUG;WIN32"/>
+ <SYSDEFINES value="_RTLDLL;NO_STRICT"/>
+ <MAINSOURCE value="common.bpf"/>
+ <INCLUDEPATH value="$(BCB)\include;$(BCB)\include\vcl;..\..\include"/>
+ <LIBPATH value="$(BCB)\lib\obj;$(BCB)\lib;..\..\lib"/>
+ <WARNINGS value="-w-par"/>
+ <LISTFILE value=""/>
+ <OTHERFILES value=""/>
+ </MACROS>
+ <OPTIONS>
+ <IDLCFLAGS value="-I$(BCB)\include -I$(BCB)\include\vcl -I..\..\include -src_suffix cpp
+ -D_DEBUG -DWIN32 -boa"/>
+ <CFLAG1 value="-Od -H=$(BCB)\lib\vcl60.csm -Hc -Vx -Ve -X- -r- -a8 -b- -k -y -v -vi- -c
+ -tW -tWM"/>
+ <PFLAGS value="-$YD -$W -$O- -$A8 -v -JPHNE -M"/>
+ <AFLAGS value="/mx /w2 /zd"/>
+ <LFLAGS value=""/>
+ <OTHERFILES value=""/>
+ </OPTIONS>
+ <LINKER>
+ <ALLOBJ value="$(OBJFILES)"/>
+ <ALLLIB value=""/>
+ <OTHERFILES value=""/>
+ </LINKER>
+ <FILELIST>
+ <FILE FILENAME="common.bpf" FORMNAME="" UNITNAME="common" CONTAINERID="BPF" DESIGNCLASS="" LOCALCOMMAND=""/>
+ <FILE FILENAME="common.cpp" FORMNAME="" UNITNAME="common.cpp" CONTAINERID="CCompiler" DESIGNCLASS="" LOCALCOMMAND=""/>
+ <FILE FILENAME="common.h" FORMNAME="" UNITNAME="common.h" CONTAINERID="" DESIGNCLASS="" LOCALCOMMAND=""/>
+ </FILELIST>
+ <BUILDTOOLS>
+ </BUILDTOOLS>
+
+ <IDEOPTIONS>
+[Version Info]
+IncludeVerInfo=0
+AutoIncBuild=0
+MajorVer=1
+MinorVer=0
+Release=0
+Build=0
+Debug=0
+PreRelease=0
+Special=0
+Private=0
+DLL=0
+Locale=1049
+CodePage=1251
+
+[Version Info Keys]
+CompanyName=
+FileDescription=
+FileVersion=1.0.0.0
+InternalName=
+LegalCopyright=
+LegalTrademarks=
+OriginalFilename=
+ProductName=
+ProductVersion=1.0.0.0
+Comments=
+
+[HistoryLists\hlIncludePath]
+Count=2
+Item0=$(BCB)\include;$(BCB)\include\vcl;..\..\include
+Item1=$(BCB)\include;$(BCB)\include\vcl
+
+[HistoryLists\hlLibraryPath]
+Count=2
+Item0=$(BCB)\lib\obj;$(BCB)\lib;..\..\lib
+Item1=$(BCB)\lib\obj;$(BCB)\lib
+
+[HistoryLists\hlDebugSourcePath]
+Count=1
+Item0=$(BCB)\source\vcl
+
+[HistoryLists\hlConditionals]
+Count=2
+Item0=_DEBUG;WIN32
+Item1=_DEBUG
+
+[HistoryLists\hlFinalOutputDir]
+Count=2
+Item0=..\..\lib\
+Item1=..\..\lib
+
+[Debugging]
+DebugSourceDirs=$(BCB)\source\vcl
+
+[Parameters]
+RunParams=
+Launcher=
+UseLauncher=0
+DebugCWD=
+HostApplication=
+RemoteHost=
+RemotePath=
+RemoteLauncher=
+RemoteCWD=
+RemoteDebug=0
+
+[Compiler]
+ShowInfoMsgs=0
+LinkDebugVcl=0
+LinkCGLIB=0
+
+[CORBA]
+AddServerUnit=1
+AddClientUnit=1
+PrecompiledHeaders=1
+ </IDEOPTIONS>
+</PROJECT>
\ No newline at end of file
--- /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>
+ */
+
+ /*
+ $Revision: 1.41 $
+ $Date: 2010/11/03 10:26:30 $
+ $Author: faust $
+ */
+
+
+/*#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <iconv.h>
+
+
+#include <stdarg.h>
+
+
+#include <sys/types.h>
+#include <math.h>
+
+#ifdef WIN32
+#include <sysutils.hpp>
+#else
+#include <unistd.h>
+#include <sys/wait.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#endif*/
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <iconv.h>
+
+#include <cstdlib>
+#include <cstdarg>
+#include <cstdio>
+#include <cstring>
+#include <cerrno>
+#include <cassert>
+
+#include "common.h"
+
+#ifndef INET_ADDRSTRLEN
+# define INET_ADDRSTRLEN 16
+#endif
+
+using namespace std;
+
+//-----------------------------------------------------------------------------
+int strtodouble2(const char * s, double &a)
+{
+char *res;
+
+a = strtod(s, &res);
+
+if (*res != 0)
+ return EINVAL;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+#ifdef DEBUG
+int printfd(const char * __file__, const char * fmt, ...)
+#else
+int printfd(const char *, const char *, ...)
+#endif
+{
+#ifdef DEBUG
+char buff[1024];
+
+time_t t = time(NULL);
+
+va_list vl;
+va_start(vl, fmt);
+vsnprintf(buff, sizeof(buff), fmt, vl);
+va_end(vl);
+
+printf("%18s > %s > ", __file__, LogDate(t)+11);
+printf("%s", buff);
+
+#endif
+return 0;
+}
+//-----------------------------------------------------------------------------
+int strprintf(string * str, const char * fmt, ...)
+{
+char buff[1024];
+
+va_list vl;
+va_start(vl, fmt);
+int n = vsnprintf(buff, sizeof(buff), fmt, vl);
+va_end(vl);
+buff[1023] = 0;
+*str = buff;
+
+return n;
+}
+//-----------------------------------------------------------------------------
+const char *IntToKMG(long long a, int stat)
+{
+static int64_t M = 1024*1024;
+static int64_t G = 1024*1024*1024;
+static char str[30];
+
+switch (stat)
+ {
+ case ST_B:
+ #ifdef __WIN32__
+ sprintf(str, "%Ld", a);
+ #else
+ sprintf(str, "%lld", a);
+ #endif
+ break;
+ case ST_KB:
+ sprintf(str, "%.2f kb", double(a)/1024.0);
+ break;
+ case ST_MB:
+ sprintf(str, "%.2f Mb", double(a)/(1024.0*1024.0));
+ break;
+ default:
+ if (a > G)
+ {
+ sprintf(str, "%.2f Gb", double(a)/double(G));
+ return &str[0];
+ }
+ if (a < -G)
+ {
+ sprintf(str, "%.2f Gb", double(a)/double(G));
+ return &str[0];
+ }
+ if (a > M)
+ {
+ sprintf(str, "%.2f Mb", double(a)/double(M));
+ return &str[0];
+ }
+ if (a < -M)
+ {
+ sprintf(str, "%.2f Mb", double(a)/double(M));
+ return &str[0];
+ }
+
+ sprintf(str, "%.2f kb", double(a)/1024.0);
+ break;
+ }
+return str;
+}
+//---------------------------------------------------------------------------
+unsigned char koi2win[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
+ 0xA0, 0xA1, 0xA2, 0xB8, 0xBA, 0xA5, 0xB3, 0xBF,
+ 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xB4, 0xAE, 0xAF,
+ 0xB0, 0xB1, 0xB2, 0xA8, 0xAA, 0xB5, 0xB2, 0xAF,
+ 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xA5, 0xBE, 0xBF,
+ 0xFE, 0xE0, 0xE1, 0xF6, 0xE4, 0xE5, 0xF4, 0xE3,
+ 0xF5, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE,
+ 0xEF, 0xFF, 0xF0, 0xF1, 0xF2, 0xF3, 0xE6, 0xE2,
+ 0xFC, 0xFB, 0xE7, 0xF8, 0xFD, 0xF9, 0xF7, 0xFA,
+ 0xDE, 0xC0, 0xC1, 0xD6, 0xC4, 0xC5, 0xD4, 0xC3,
+ 0xD5, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE,
+ 0xCF, 0xDF, 0xD0, 0xD1, 0xD2, 0xD3, 0xC6, 0xC2,
+ 0xDC, 0xDB, 0xC7, 0xD8, 0xDD, 0xD9, 0xD7, 0xDA};
+
+
+unsigned char win2koi[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
+ 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xBD, 0xA6, 0xA7,
+ 0xB3, 0xA9, 0xB4, 0xAB, 0xAC, 0xAD, 0xAE, 0xB7,
+ 0xB0, 0xB1, 0xB6, 0xA6, 0xAD, 0xB5, 0xB6, 0xB7,
+ 0xA3, 0xB9, 0xA4, 0xBB, 0xBC, 0xBD, 0xBE, 0xA7,
+ 0xE1, 0xE2, 0xF7, 0xE7, 0xE4, 0xE5, 0xF6, 0xFA,
+ 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0,
+ 0xF2, 0xF3, 0xF4, 0xF5, 0xE6, 0xE8, 0xE3, 0xFE,
+ 0xFB, 0xFD, 0xFF, 0xF9, 0xF8, 0xFC, 0xE0, 0xF1,
+ 0xC1, 0xC2, 0xD7, 0xC7, 0xC4, 0xC5, 0xD6, 0xDA,
+ 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0,
+ 0xD2, 0xD3, 0xD4, 0xD5, 0xC6, 0xC8, 0xC3, 0xDE,
+ 0xDB, 0xDD, 0xDF, 0xD9, 0xD8, 0xDC, 0xC0, 0xD1};
+//---------------------------------------------------------------------------
+void KOIToWin(const char * s1, char * s2, int l)
+{
+unsigned char t;
+for (int j = 0; j < l; j++)
+ {
+ t = s1[j];
+ s2[j] = koi2win[t];
+
+ if (s1[j] == 0)
+ break;
+ }
+}
+//---------------------------------------------------------------------------
+void WinToKOI(const char * s1, char * s2, int l)
+{
+unsigned char t;
+for (int j = 0; j < l; j++)
+ {
+ t = s1[j];
+ s2[j] = win2koi[t];
+
+ if (s1[j] == 0)
+ break;
+ }
+}
+//---------------------------------------------------------------------------
+void KOIToWin(const string & s1, string * s2)
+{
+s2->erase(s2->begin(), s2->end());
+unsigned char t;
+s2->reserve(s1.length());
+for (int j = 0; j < (int)s1.length(); j++)
+ {
+ t = s1[j];
+ s2->push_back(koi2win[t]);
+ }
+}
+//---------------------------------------------------------------------------
+void WinToKOI(const string & s1, string * s2)
+{
+s2->erase(s2->begin(), s2->end());
+unsigned char t;
+s2->reserve(s1.length());
+for (int j = 0; j < (int)s1.length(); j++)
+ {
+ t = s1[j];
+ s2->push_back(win2koi[t]);
+ }
+}
+//---------------------------------------------------------------------------
+void Encode12str(string & dst, const string & src)
+{
+dst.erase(dst.begin(), dst.end());
+for (size_t i = 0; i < src.length(); i++)
+ {
+ dst.push_back('a' + (src[i] & 0x0f));
+ dst.push_back('a' + ((src[i] & 0xf0) >> 4));
+ }
+}
+//---------------------------------------------------------------------------
+void Decode21str(std::string & dst, const std::string & src)
+{
+dst.erase(dst.begin(), dst.end());
+for (size_t i = 0; i < src.length() / 2; i++)
+ {
+ char c1 = src[i * 2];
+ char c2 = src[i * 2 + 1];
+
+ c1 -= 'a';
+ c2 -= 'a';
+
+ dst.push_back(c1 + (c2 << 4));
+ }
+}
+//---------------------------------------------------------------------------
+void Encode12(char * dst, const char * src, size_t srcLen)
+{
+for (size_t i = 0; i <= srcLen; i++)
+ {
+ if (src[i] == 0)
+ {
+ dst[i * 2] = 'a';
+ dst[i * 2 + 1] = 'a';
+ break;
+ }
+ char c1 = src[i] & 0x0f;
+ char c2 = (src[i] & 0xf0) >> 4;
+
+ c1 += 'a';
+ c2 += 'a';
+
+ dst[i * 2] = c1;
+ dst[i * 2 + 1] = c2;
+ }
+dst[srcLen * 2] = 0;
+}
+//---------------------------------------------------------------------------
+void Decode21(char * dst, const char * src)
+{
+for (size_t i = 0; ; i++)
+ {
+ if (src[i * 2] == 0)
+ break;
+
+ char c1 = src[i * 2];
+ char c2 = src[i * 2 + 1];
+
+ c1 -= 'a';
+ c2 -= 'a';
+
+ dst[i] = c1 + (c2 << 4);
+ }
+dst[strlen(src) / 2] = 0;
+}
+//---------------------------------------------------------------------------
+int ParseIPString(const char * str, uint32_t * ips, int maxIP)
+{
+/*
+ *Function Name:ParseIPString
+ *
+ *Parameters:
+ ÓÔÒÏËÁ ÄÌÑ ÒÁÚÂÏÒÁ É ÍÁÓÓÉ× ËÕÄÁ ÚÁÎÏÓÉÔØ ÐÏÌÕÞÅÎÎÙÅ ÁÄÒÅÓÁ
+ *
+ *Description:
+ îÁ ×ÈÏÄÅ ÄÏÌÖÎÁ ÂÙÔØ ÓÔÒÏËÁ ×ÉÄÁ "ip1,ip2,ip3" ÉÌÉ "*"
+ ÷ ÐÅÒ×ÏÍ ÓÌÕÞÁÅ × ÍÁÓÓÉ× ÚÁÎÏÓÑÔÓÑ ÒÁÚÏÂÒÁÎÎÙÅ ÁÄÒÅÓÁ.
+ åÓÌÉ ÉÈ ÍÅÎØÛÅ MAX_IP?, ÔÏ ÐÏÓÌÅÄÎÉÊ ÁÄÒÅÓ ÂÕÄÅÔ 255.255.255.255
+ åÓÌÉ ÓÔÒÏËÁ * , ÔÏ ÐÅÒ×ÁÙÊ ÁÄÒÅÓ ÂÕÄÅÔ 0.0.0.0, Ô.Å. ÌÀÂÏÊ
+ *
+ *Returns: 0 ÅÓÌÉ ×ÓÅ ïë
+ *
+ */
+
+char p[255];
+char * p1, *pp;
+int n = 0;
+
+strncpy(p, str, 254);
+pp = p;
+
+memset(ips, 0xFF, sizeof(unsigned long) * maxIP);
+
+if (str[0] == '*' && strlen(str) == 1)
+ {
+ ips[0] = 0;
+ return 0;
+ }
+
+for (int i = 0; i < maxIP; i++)
+ {
+ p1 = strtok(pp, ",\n ");
+ pp = NULL;
+
+ if (p1 == NULL && n == 0)// ÕËÁÚÁÔÅÌØ ÎÕÌØ É ÐÒÏÞÉÔÁÎÏ ÁÄÒÅÓÏ× ÔÏÖÅ ÎÏÌØ
+ {
+ return EINVAL;
+ }
+
+ if (p1 == NULL && n)
+ {
+ return 0;
+ }
+
+ struct in_addr in;
+ if (!inet_aton(p1, &in))
+ {
+ //printf("INADDR_NONE\n");
+ return EINVAL;
+ }
+
+ ips[n] = in.s_addr;
+
+ /*if (ips[n] == INADDR_NONE)
+ return EINVAL;*/
+
+ n++;
+
+ if (n >= maxIP)
+ return 0;
+
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int DaysInCurrentMonth()
+{
+time_t t = time(NULL);
+
+struct tm * lt = localtime(&t);
+
+return DaysInMonth(lt->tm_year, lt->tm_mon);
+}
+//-----------------------------------------------------------------------------
+int DaysInMonth(unsigned year, unsigned mon)
+{
+assert(mon < 12 && "Month number should be 0 - 11");
+switch (mon)
+ {
+ case 0: return 31; //jan
+ case 1:
+ if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))
+ return 29;
+ return 28; //feb
+ case 2: return 31; //mar
+ case 3: return 30; //apr
+ case 4: return 31; //may
+ case 5: return 30; //june
+ case 6: return 31; //jule
+ case 7: return 31; //aug
+ case 8: return 30; //sep
+ case 9: return 31; //oct
+ case 10: return 30; //nov
+ case 11: return 31; //dec
+ }
+return -1; // We will never reach here
+}
+//-----------------------------------------------------------------------------
+int Min8(int a)
+{
+/*
+æÕÎËÃÉÑ ×ÏÚ×ÒÁÝÁÅÔ ÎÁÉÍÅÎØÛÅÅ ÞÉÓÌÏ ËÒÁÔÎÏÅ 8-ÍÉ ÂÏÌØÛÅÅ ÉÌÉ ÒÁ×ÎÏÅ ÚÁÄÁÎÎÏÍÕ
+ * */
+if (a % 8 == 0)
+ return a;
+
+return a + (8 - a % 8);
+}
+//-----------------------------------------------------------------------------
+/*char * inet_ntostr(unsigned long ip)
+{
+struct in_addr addr = {ip};
+return inet_ntoa(addr);
+}*/
+//-----------------------------------------------------------------------------
+std::string inet_ntostring(uint32_t ip)
+{
+ char buf[INET_ADDRSTRLEN + 1];
+ return inet_ntop(AF_INET, &ip, buf, INET_ADDRSTRLEN);
+}
+//-----------------------------------------------------------------------------
+uint32_t inet_strington(const std::string & value)
+{
+ uint32_t result;
+
+ if (inet_pton(AF_INET, value.c_str(), &result) <= 0)
+ return 0;
+
+ return result;
+}
+//-----------------------------------------------------------------------------
+int ParseTariffTimeStr(const char * str, int &h1, int &m1, int &h2, int &m2)
+{
+char hs1[10], ms1[10], hs2[10], ms2[10];
+char s1[25], s2[25];
+char ss[49];
+char *p1, *p2;
+
+strncpy(ss, str, 48);
+
+p1 = strtok(ss, "-");
+if (!p1)
+ return -1;
+
+strncpy(s1, p1, 24);
+
+p2 = strtok(NULL, "-");
+if (!p2)
+ return -1;
+
+strncpy(s2, p2, 24);
+
+p1 = strtok(s1, ":");
+if (!p1)
+ return -1;
+
+strncpy(hs1, p1, 9);
+
+p2 = strtok(NULL, ":");
+if (!p2)
+ return -1;
+
+strncpy(ms1, p2, 9);
+
+p1 = strtok(s2, ":");
+if (!p1)
+ return -1;
+
+strncpy(hs2, p1, 9);
+
+p2 = strtok(NULL, ":");
+if (!p2)
+ return -1;
+
+strncpy(ms2, p2, 9);
+
+if (str2x(hs1, h1) != 0)
+ return -1;
+
+if (str2x(ms1, m1) != 0)
+ return -1;
+
+if (str2x(hs2, h2) != 0)
+ return -1;
+
+if (str2x(ms2, m2) != 0)
+ return -1;
+
+return 0;
+}
+/*//---------------------------------------------------------------------------
+bool IsDigit(char c)
+{
+if (c >= '0' && c <= '9')
+ return true;
+return false;
+}
+//-----------------------------------------------------------------------------
+bool IsAlpha(char c)
+{
+if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))
+ return true;
+return false;
+}*/
+//-----------------------------------------------------------------------------
+const char * LogDate(time_t t)
+{
+static char s[32];
+struct tm * tt = localtime(&t);
+
+snprintf(s, 20, "%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;
+}
+//-----------------------------------------------------------------------------
+uint32_t CalcMask(uint32_t msk)
+{
+if (msk >= 32) return 0xFFffFFff;
+if (msk == 0) return 0;
+return htonl(0xFFffFFff << (32 - msk));
+}
+//---------------------------------------------------------------------------
+void TouchFile(const string & fileName)
+{
+FILE * f = fopen(fileName.c_str(), "w");
+if (f)
+ fclose(f);
+}
+//---------------------------------------------------------------------------
+#ifdef WIN32
+void EncodeStr(char * str, unsigned long serial, int useHDD)
+{
+int len = strlen(str);
+char stren[100];
+int i, j = 0;
+char c1, c2;
+char serial_c[sizeof(serial)];
+memcpy(serial_c, &serial, sizeof(serial));
+
+for (i = 0; i < len; i++)
+ {
+ if (!useHDD)
+ str[i] = str[i]^49;
+ else
+ {
+ str[i] = str[i]^serial_c[j%sizeof(serial)];
+ j++;
+ }
+ }
+
+for (i = 0; i < 2*len; i++)
+ {
+ if (i%2)
+ {
+ c1 = (str[i/2] >> 4);
+ c1 = c1 + 50;
+ stren[i] = c1;
+ }
+ else
+ {
+ c2 = (str[i/2] & 0x0f);
+ c2 += 50;
+ stren[i] = c2;
+ }
+ }
+stren[i] = 0;
+strcpy(str, stren);
+}
+//---------------------------------------------------------------------------
+void DecodeStr(char * str, unsigned long serial, int useHDD)
+{
+int len = strlen(str);
+char strdc[100];
+int i, j = 0;
+char c1, c2;
+char serial_c[sizeof(serial)];
+memcpy(serial_c, &serial, sizeof(serial));
+
+for (i = 0; i < len; i += 2)
+ {
+ c1 = (str[i] - 50);
+ c2 = (str[i+1] - 50)<<4;
+ strdc[i/2] = c1+c2;
+ }
+for (i = 0; i < len/2; i++)
+ {
+ if (!useHDD)
+ strdc[i] = strdc[i]^49;
+ else
+ {
+ strdc[i] = strdc[i]^serial_c[j%sizeof(serial)];
+ j++;
+ }
+ }
+strdc[i] = 0;
+strcpy(str, strdc);
+}
+//---------------------------------------------------------------------------
+#endif //WIN32
+void SwapBytes(uint16_t & value)
+{
+ value = (value >> 8) |
+ (value << 8);
+}
+//---------------------------------------------------------------------------
+void SwapBytes(uint32_t & value)
+{
+ value = (value >> 24) |
+ ((value << 8) & 0x00FF0000L)|
+ ((value >> 8) & 0x0000FF00L)|
+ (value << 24);
+}
+//---------------------------------------------------------------------------
+void SwapBytes(uint64_t & value)
+{
+ value = (value >> 56) |
+ ((value << 40) & 0x00FF000000000000LL) |
+ ((value << 24) & 0x0000FF0000000000LL) |
+ ((value << 8) & 0x000000FF00000000LL) |
+ ((value >> 8) & 0x00000000FF000000LL) |
+ ((value >> 24) & 0x0000000000FF0000LL) |
+ ((value >> 40) & 0x000000000000FF00LL) |
+ (value << 56);
+}
+//---------------------------------------------------------------------------
+void SwapBytes(int16_t & value)
+{
+ uint16_t temp = value;
+ SwapBytes(temp);
+ value = temp;
+}
+//---------------------------------------------------------------------------
+void SwapBytes(int32_t & value)
+{
+ uint32_t temp = value;
+ SwapBytes(temp);
+ value = temp;
+}
+//---------------------------------------------------------------------------
+void SwapBytes(int64_t & value)
+{
+ uint64_t temp = value;
+ SwapBytes(temp);
+ value = temp;
+}
+//---------------------------------------------------------------------------
+int str2x(const std::string & str, int & x)
+{
+x = strtol(str.c_str(), NULL, 10);
+
+if (errno == ERANGE)
+ return -1;
+
+return 0;
+}
+//---------------------------------------------------------------------------
+int str2x(const std::string & str, unsigned & x)
+{
+x = strtoul(str.c_str(), NULL, 10);
+
+if (errno == ERANGE)
+ return -1;
+
+return 0;
+}
+//---------------------------------------------------------------------------
+int str2x(const std::string & str, long long & x)
+{
+x = strtoll(str.c_str(), NULL, 10);
+
+if (errno == ERANGE)
+ return -1;
+
+return 0;
+}
+//---------------------------------------------------------------------------
+int str2x(const std::string & str, unsigned long long & x)
+{
+x = strtoull(str.c_str(), NULL, 10);
+
+if (errno == ERANGE)
+ return -1;
+
+return 0;
+}
+//---------------------------------------------------------------------------
+const std::string & x2str(unsigned x, std::string & s)
+{
+return unsigned2str(x, s);
+}
+//---------------------------------------------------------------------------
+const std::string & x2str(unsigned long long x, std::string & s)
+{
+return unsigned2str(x, s);
+}
+//---------------------------------------------------------------------------
+std::string & TrimL(std::string & val)
+{
+size_t pos = val.find_first_not_of(" \t");
+if (pos == std::string::npos)
+ {
+ val.erase(val.begin(), val.end());
+ }
+else
+ {
+ val.erase(0, pos);
+ }
+return val;
+}
+//---------------------------------------------------------------------------
+std::string & TrimR(std::string & val)
+{
+size_t pos = val.find_last_not_of(" \t");
+if (pos != std::string::npos)
+ {
+ val.erase(pos + 1);
+ }
+return val;
+}
+//---------------------------------------------------------------------------
+std::string & Trim(std::string & val)
+{
+return TrimR(TrimL(val));
+}
+//---------------------------------------------------------------------------
+time_t stg_timegm(struct tm * brokenTime)
+{
+#ifdef HAVE_TIMEGM
+return timegm(brokenTime);
+#else
+time_t ret;
+char *tz;
+tz = getenv("TZ");
+setenv("TZ", "", 1);
+tzset();
+ret = mktime(brokenTime);
+if (tz)
+ setenv("TZ", tz, 1);
+else
+ unsetenv("TZ");
+tzset();
+return ret;
+#endif
+}
+//---------------------------------------------------------------------------
+std::string IconvString(const std::string & source,
+ const std::string & from,
+ const std::string & to)
+{
+if (source.empty())
+ return std::string();
+
+size_t inBytesLeft = source.length() + 1;
+size_t outBytesLeft = source.length() * 2 + 1;
+
+char * inBuf = new char[inBytesLeft];
+char * outBuf = new char[outBytesLeft];
+
+strncpy(inBuf, source.c_str(), source.length());
+
+inBuf[source.length()] = 0;
+
+#if defined(FREE_BSD) || defined(FREE_BSD5)
+const char * srcPos = inBuf;
+#else
+char * srcPos = inBuf;
+#endif
+char * dstPos = outBuf;
+
+iconv_t handle = iconv_open(to.c_str(),
+ from.c_str());
+
+if (handle == iconv_t(-1))
+ {
+ if (errno == EINVAL)
+ {
+ printfd(__FILE__, "IconvString(): iconv from %s to %s failed\n", from.c_str(), to.c_str());
+ delete[] outBuf;
+ delete[] inBuf;
+ return source;
+ }
+ else
+ printfd(__FILE__, "IconvString(): iconv_open error\n");
+
+ delete[] outBuf;
+ delete[] inBuf;
+ return source;
+ }
+
+size_t res = iconv(handle,
+ &srcPos, &inBytesLeft,
+ &dstPos, &outBytesLeft);
+
+if (res == size_t(-1))
+ {
+ printfd(__FILE__, "IconvString(): '%s'\n", strerror(errno));
+
+ iconv_close(handle);
+ delete[] outBuf;
+ delete[] inBuf;
+ return source;
+ }
+
+dstPos = 0;
+
+std::string dst(outBuf);
+
+iconv_close(handle);
+
+delete[] outBuf;
+delete[] inBuf;
+
+return dst;
+}
+//---------------------------------------------------------------------------
--- /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>
+ */
+
+ /*
+ $Revision: 1.31 $
+ $Date: 2010/11/03 10:26:30 $
+ $Author: faust $
+ */
+
+#ifndef common_h
+#define common_h
+
+#include <ctime>
+#include <string>
+
+#include "os_int.h"
+#include "stg_const.h"
+
+#define STAT_TIME_3 (1)
+#define STAT_TIME_2 (2)
+#define STAT_TIME_1 (3)
+#define STAT_TIME_1_2 (4)
+#define STAT_TIME_1_4 (5)
+#define STAT_TIME_1_6 (6)
+
+#define FN_STR_LEN (NAME_MAX)
+
+#define ST_F 0
+#define ST_B 1
+#define ST_KB 2
+#define ST_MB 3
+
+//-----------------------------------------------------------------------------
+const char * IntToKMG(long long a, int statType = ST_F);
+const char * LogDate(time_t t);
+int ParesTimeStat(const char * str);
+int IsTimeStat(struct tm * t, int statTime);
+/*bool IsDigit(char c);
+bool IsAlpha(char c);*/
+int strtodouble2(const char * s, double &a);
+int printfd(const char * __file__, const char * fmt, ...);
+void Encode12(char * dst, const char * src, size_t srcLen);
+void Decode21(char * dst, const char * src);
+
+void Encode12str(std::string & dst, const std::string & src);
+void Decode21str(std::string & dst, const std::string & src);
+
+int ParseIPString(const char * str, uint32_t * ips, int maxIP);
+void KOIToWin(const char * s1, char * s2, int l);
+void WinToKOI(const char * s1, char * s2, int l);
+void KOIToWin(const std::string & s1, std::string * s2);
+void WinToKOI(const std::string & s1, std::string * s2);
+int DaysInMonth(unsigned year, unsigned mon);
+int DaysInCurrentMonth();
+int Min8(int a);
+//char * inet_ntostr(unsigned long);
+std::string inet_ntostring(uint32_t);
+uint32_t inet_strington(const std::string & value);
+int strprintf(std::string * str, const char * fmt, ...);
+int ParseTariffTimeStr(const char * str, int &h1, int &m1, int &h2, int &m2);
+uint32_t CalcMask(uint32_t msk);
+void TouchFile(const std::string & fileName);
+#ifdef WIN32
+void EncodeStr(char * str, unsigned long serial, int useHDD);
+void DecodeStr(char * str, unsigned long serial, int useHDD);
+#endif //WIN32
+void SwapBytes(uint16_t & value);
+void SwapBytes(uint32_t & value);
+void SwapBytes(uint64_t & value);
+void SwapBytes(int16_t & value);
+void SwapBytes(int32_t & value);
+void SwapBytes(int64_t & value);
+
+std::string & TrimL(std::string & val);
+std::string & TrimR(std::string & val);
+std::string & Trim(std::string & val);
+
+std::string IconvString(const std::string & source, const std::string & from, const std::string & to);
+
+//-----------------------------------------------------------------------------
+template <typename varT>
+int str2x(const std::string & str, varT & x)
+{
+ int pos = 0;
+ int minus = 1;
+
+ if (str.empty())
+ return -1;
+
+ if (str[0] == '+')
+ pos++;
+
+ if (str[0] == '-')
+ {
+ pos++;
+ minus = -1;
+ }
+
+ if ((str[pos] < '0' || str[pos] > '9'))
+ return -1;
+
+ x = str[pos++] - '0';
+
+ for (unsigned i = pos; i < str.size(); i++)
+ {
+ if ((str[i] < '0' || str[i] > '9'))
+ return -1;
+
+ x *= 10;
+ x += str[i] - '0';
+ }
+
+ x*= minus;
+
+ return 0;
+}
+//-----------------------------------------------------------------------------
+template <typename varT>
+const std::string & x2str(varT x, std::string & s)
+{
+ varT xx = x;
+ int pos = 1;
+
+ x /= 10;
+ while (x != 0)
+ {
+ x /= 10;
+ pos++;
+ }
+
+ if (xx < 0)
+ {
+ pos++;
+ s.resize(pos, 0);
+ s[0] = '-';
+ }
+ else if (xx > 0)
+ {
+ s.resize(pos, 0);
+ }
+ else
+ {
+ s.resize(1, 0);
+ s[0] = '0';
+ return s;
+ }
+
+ x = xx;
+
+ while (x != 0)
+ {
+ if (x < 0)
+ s[--pos] = -(x % 10) + '0';
+ else
+ s[--pos] = x % 10 + '0';
+
+ x /= 10;
+ }
+
+ return s;
+}
+//-----------------------------------------------------------------------------
+template <typename varT>
+const std::string & unsigned2str(varT x, std::string & s)
+{
+ varT xx = x;
+ int pos = 1;
+
+ x /= 10;
+ while (x != 0)
+ {
+ x /= 10;
+ pos++;
+ }
+
+ if (xx > 0)
+ {
+ s.resize(pos, 0);
+ }
+ else
+ {
+ s.resize(1, 0);
+ s[0] = '0';
+ return s;
+ }
+
+ x = xx;
+
+ while (x != 0)
+ {
+ s[--pos] = x % 10 + '0';
+
+ x /= 10;
+ }
+
+ return s;
+}
+//-----------------------------------------------------------------------------
+int str2x(const std::string & str, int & x);
+int str2x(const std::string & str, unsigned & x);
+int str2x(const std::string & str, long long & x);
+int str2x(const std::string & str, unsigned long long & x);
+//-----------------------------------------------------------------------------
+const std::string & x2str(unsigned x, std::string & s);
+const std::string & x2str(unsigned long long x, std::string & s);
+//-----------------------------------------------------------------------------
+char * stg_strptime(const char *, const char *, struct tm *);
+time_t stg_timegm(struct tm *);
+
+#endif
--- /dev/null
+/*
+ *****************************************************************************
+ *
+ * File: debug.c
+ *
+ * Description: ÷Ù×ÏÄ ÏÔÌÁÄÏÞÎÏÊ ÉÎÆÏÒÍÁÃÉÉ × log ÆÁÊÌ
+ *
+ * $Id: debug.c,v 1.2 2005/11/16 16:19:40 nobunaga Exp $
+ *
+ *****************************************************************************
+ */
+
+#include <stdarg.h>
+#include <time.h>
+#include <string.h>
+
+#include "debug.h"
+
+
+/*
+ *****************************************************************************
+ * -= óÏÚÄÁÎÉÅ ÚÁÐÉÓÉ × log-ÆÁÊÌÅ =-
+ *****************************************************************************
+ */
+void PrintfLog(FILE * logFile, char * scriptName, char * fmt, ...)
+{
+ #ifndef DEMO
+ va_list vaList;
+ char buff[MAX_LOG_BUFF_LEN];
+ time_t curTime;
+ char curTimeCh[26];
+
+ if (logFile)
+ {
+ va_start(vaList, fmt);
+ vsprintf(buff, fmt, vaList);
+ va_end(vaList);
+
+ curTime = time(NULL);
+ ctime_r(&curTime, curTimeCh);
+ curTimeCh[strlen(curTimeCh)-1] = 0;
+ fprintf(logFile, "%s [%s]: %s\n", scriptName, curTimeCh, buff);
+ }
+ #endif
+ return;
+} /* PrintfLog() */
+
+/* EOF */
+
--- /dev/null
+/*
+ *****************************************************************************
+ *
+ * File: debug.h
+ *
+ * Description: ÷Ù×ÏÄ ÏÔÌÁÄÏÞÎÏÊ ÉÎÆÏÒÍÁÃÉÉ × log ÆÁÊÌ
+ *
+ * $Id: debug.h,v 1.2 2006/03/07 18:33:56 nobunaga Exp $
+ *
+ *****************************************************************************
+ */
+
+#ifndef _DEBUG_H_
+#define _DEBUG_H_
+
+
+#include <stdio.h>
+
+
+#define MAX_LOG_BUFF_LEN (2048)
+
+
+void PrintfLog(FILE * logFile, char * scriptName, char * fmt, ...);
+
+#endif /* _DEBUG_H_ */
+
+/* EOF */
+
--- /dev/null
+/*
+ *****************************************************************************
+ *
+ * File: stg_common.h
+ *
+ * Description: çÌÏÂÁÌØÎÏÅ ÄÌÑ ×ÓÅÇÏ ÐÒÏÅËÔÁ STG
+ *
+ * $Id: stg_common.h,v 1.1.1.1 2005/09/29 11:33:18 boris Exp $
+ *
+ *****************************************************************************
+ */
+
+#ifndef _STG_COMMON_H_
+#define _STG_COMMON_H_
+
+
+#define LOGIN_LEN (32)
+#define PASSWD_LEN (32)
+
+#endif /* _STG_COMMON_H_ */
+
+/* EOF */
+
--- /dev/null
+/*
+ *****************************************************************************
+ *
+ * File: stg_error.c
+ *
+ * Description: ëÏÄÙ ïÛÉÂÏË ÐÒÏÅËÔÁ StarGazer
+ *
+ * $Id: stg_error.c,v 1.1.1.1 2005/09/29 11:33:18 boris Exp $
+ *
+ *****************************************************************************
+ */
+
+#include "stg_error.h"
+//#include "debug.h"
+
+
+/*
+ *****************************************************************************
+ * -= ðÏÉÓË ÓÏÏÂÝÅÎÉÑ Ï ÏÛÉÂËÅ ÐÏ ËÏÄÕ ÏÛÉÂËÉ =-
+ *****************************************************************************
+ */
+char * GetErrorString(RESULT_DATA res)
+{
+ char * errorString;
+
+ switch (res)
+ {
+ case SUCCESS:
+ {
+ errorString = "OK: Work finished successfully";
+ break;
+ }
+ /* astat.cgi */
+ case ERROR_CONFIG_READ:
+ {
+ errorString = "FAIL: Read config file";
+ break;
+ }
+ case ERROR_PORT_NUM:
+ {
+ errorString = "FAIL: Port value incorrect";
+ break;
+ }
+ case ERROR_CLEAR_SID_DIR:
+ {
+ errorString = "FAIL: ClearSidDir() return fail";
+ break;
+ }
+ case ERROR_UNKNOWN_HTTP_METHOD:
+ {
+ errorString = "FAIL: Umknown HTTP method";
+ break;
+ }
+ case ERROR_NULL_HTTP_METHOD:
+ {
+ errorString = "FAIL: NULL HTTP method";
+ break;
+ }
+ case ERROR_UNKNOWN_QUERY:
+ {
+ errorString = "FAIL: Unknown query";
+ break;
+ }
+ case ERROR_LOGIN:
+ {
+ errorString = "FAIL: Login Error";
+ break;
+ }
+ case ERROR_PREPARE_USER_SELECTION_PAGE_0:
+ {
+ errorString = "FAIL: Prepare user selection page [0]";
+ break;
+ }
+ case ERROR_ADD_IFACE:
+ {
+ errorString = "FAIL: Add iface";
+ break;
+ }
+ case ERROR_ADD_TARIFF:
+ {
+ errorString = "FAIL: Add tariff";
+ break;
+ }
+ case ERROR_ADD_GROUP:
+ {
+ errorString = "FAIL: Add group";
+ break;
+ }
+ case ERROR_ADD_USER:
+ {
+ errorString = "FAIL: Add user";
+ break;
+ }
+ case ERROR_CREATE_SID:
+ {
+ errorString = "FAIL: Create sid";
+ break;
+ }
+ case ERROR_SET_SID:
+ {
+ errorString = "FAIL: Set sid";
+ break;
+ }
+ case ERROR_UPDATE_SID:
+ {
+ errorString = "FAIL: Update sid";
+ break;
+ }
+ case ERROR_READ_SID_DATA:
+ {
+ errorString = "FAIL: Read sid data";
+ break;
+ }
+ case ERROR_WRITE_SID_DATA:
+ {
+ errorString = "FAIL: Write sid data";
+ break;
+ }
+ case ERROR_REMOVE_EXPIRED_SID:
+ {
+ errorString = "FAIL: Remove expired sids";
+ break;
+ }
+ /* qParam.lib */
+ case ERROR_MEMORY_ALLOCATE:
+ {
+ errorString = "FAIL: Error memory allocation";
+ break;
+ }
+ case ERROR_MEMORY_DESPOSE:
+ {
+ errorString = "FAIL: Error memory depose";
+ break;
+ }
+ case ERROR_NULL_QUERY:
+ {
+ errorString = "FAIL: Query is NULL";
+ break;
+ }
+ case ERROR_QUERY:
+ {
+ errorString = "FAIL: Error query";
+ break;
+ }
+ /* diagram.lib */
+ case ERROR_ARC_DATA_FULL:
+ {
+ errorString = "FAIL: Arc data is full";
+ break;
+ }
+ case ERROR_ARC_PERCENT:
+ {
+ errorString = "FAIL: Arc percent != 100%";
+ break;
+ }
+ default:
+ {
+ errorString = "FAIL: Unknown error";
+ }
+ } /* switch (res) */
+
+ return (errorString);
+}/* GetErrorString() */
+
+/* EOF */
+
--- /dev/null
+/*
+ *****************************************************************************
+ *
+ * File: stg_error.h
+ *
+ * Description: ëÏÄÙ ÏÛÉÂÏË
+ *
+ * $Id: stg_error.h,v 1.1.1.1 2005/09/29 11:33:18 boris Exp $
+ *
+ *****************************************************************************
+ */
+
+#ifndef _STG_ERROR_H_
+#define _STG_ERROR_H_
+
+
+/* îÁÞÁÌÏ ÏÂÌÁÓÔÉ ÏÛÉÂÏË ÍÏÄÕÌÑ astat.cgi */
+#define ERROR_ASTAT_START (100000)
+/* îÁÞÁÌÏ ÏÂÌÁÓÔÉ ÏÛÉÂÏË ÂÉÂÌÉÔÅËÉ qparam.lib */
+#define ERROR_QPARAM_START (102000)
+/* îÁÞÁÌÏ ÏÂÌÁÓÔÉ ÏÛÉÂÏË ÂÉÂÌÉÔÅËÉ diagram.lib */
+#define ERROR_DIAGRAM_START (103000)
+
+
+typedef enum
+{
+ SUCCESS = 0,
+
+ ERROR_CONFIG_READ = ERROR_ASTAT_START,
+ ERROR_PORT_NUM,
+ ERROR_CLEAR_SID_DIR,
+ ERROR_UNKNOWN_HTTP_METHOD,
+ ERROR_NULL_HTTP_METHOD,
+ ERROR_UNKNOWN_QUERY,
+ ERROR_LOGIN, // ÐÏËÁ ÞÔÏ ÏÄÎÁ ÏÛÉÂËÁ ÎÁ ÍÎÏÇÏ ÓÉÔÕÁÃÉÊ:
+ // * ÎÅ ×ÅÒÎÏÅ ÉÍÑ É ÐÁÒÏÌØ
+ // * ÎÅÔ Ó×ÑÚÉ Ó ÓÅÒ×ÅÒÏÍ
+ // * ....
+ // ÜÔÏ Ó×ÑÚÁÎÏ Ó ËÏÄÁÍÉ ÏÛÉÂÏË ÍÏÄÕÌÑ srvconf.lib
+ // × ÄÁÌØÎÅÊÛÅÍ ÎÁÄÏ ÐÅÒÅÄÁÌÁÔØ ×ÓÅ ÎÁ ÏÄÉÎ
+ // enum ÏÛÉÂÏË
+ ERROR_PREPARE_USER_SELECTION_PAGE_0,
+ ERROR_ADD_IFACE,
+ ERROR_ADD_TARIFF,
+ ERROR_ADD_GROUP,
+ ERROR_ADD_USER,
+ ERROR_CREATE_SID,
+ ERROR_SET_SID,
+ ERROR_UPDATE_SID,
+ ERROR_READ_SID_DATA,
+ ERROR_WRITE_SID_DATA,
+ ERROR_REMOVE_EXPIRED_SID,
+
+ ERROR_MEMORY_ALLOCATE = ERROR_QPARAM_START,
+ ERROR_MEMORY_DESPOSE,
+ ERROR_NULL_QUERY, // ÚÁÐÒÏÓ ÎÅ ÐÏÌÕÞÅÎ
+ ERROR_QUERY, // ÏÛÉÂËÁ × ÚÁÐÒÏÓÅ - ÎÅÓÏÏÔ×ÅÔÓÔ×ÉÅ ÓÔÁÎÄÁÒÔÕ
+
+ ERROR_ARC_DATA_FULL = ERROR_DIAGRAM_START,
+ ERROR_ARC_PERCENT,
+ TODO
+} RESULT_DATA;
+
+
+char * GetErrorString(RESULT_DATA res);
+
+#endif /* _STG_ERROR_H_ */
+
+/* EOF */
+
--- /dev/null
+/*
+ * $Revision: 1.1 $
+ * $Date: 2007/05/17 08:25:58 $
+ *
+ * This file contain a replacement of commonly used function strptime
+ * Under some OS's it appears only with _XOPEN_SOURCE definition
+ *
+ */
+
+#define _XOPEN_SOURCE
+#include <time.h>
+
+char * stg_strptime(const char * a, const char * b, struct tm * tm)
+{
+return strptime(a, b, tm);
+}
+
--- /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
+ */
+
+ /*
+ $Revision: 1.6 $
+ $Date: 2009/06/10 10:31:15 $
+ $Author: faust $
+ */
+
+#include <iostream>
+#include <limits.h>
+#include <arpa/inet.h>
+
+using namespace std;
+
+#include "common.h"
+#include "test.h"
+
+time_t stgTime;
+
+int main(void)
+{
+char buf1[256];
+BLOWFISH_CTX ctx;
+int functions = 0, ok = 0;
+
+cout << "Testing common.lib" << endl << "---------------\
+--------------------" << endl;
+
+if (!TestIntToKMG())
+ ok++;
+functions++;
+if (!Teststrtodouble2())
+ ok++;
+functions++;
+if (!TestIsDigit())
+ ok++;
+functions++;
+if (!TestIsAlpha())
+ ok++;
+functions++;
+if (!TestEncodeDecode())
+ ok++;
+functions++;
+if (!TestParseIPString())
+ ok++;
+functions++;
+if (!TestKOIToWIN())
+ ok++;
+functions++;
+if (!TestDaysInMonth())
+ ok++;
+functions++;
+if (!TestBlowfish())
+ ok++;
+functions++;
+if (!TestMin8())
+ ok++;
+functions++;
+if (!Testinet_ntostr())
+ ok++;
+functions++;
+if (!TestParseTariffTimeStr())
+ ok++;
+functions++;
+if (!TestStr2XX2Str())
+ ok++;
+functions++;
+
+cout << "------------------------------------" << endl;
+cout << "Functions: \t\t\t" << functions << endl;
+cout << "OK's: \t\t\t\t" << ok << endl;
+cout << "Fails: \t\t\t\t" << functions - ok << endl;
+
+return (functions != ok);
+}
+
+int TestIntToKMG()
+{
+int res = 1;
+cout << "Testing IntToKMG: \t\t";
+res = res && (strcmp(IntToKMG(LONG_LONG_MAX), TEST1_LLMAX) == 0);
+//cout << IntToKMG(LONG_LONG_MAX) << " " << TEST1_LLMAX << endl;
+
+res = res && (strcmp(IntToKMG(1024 * 1024 + 1), TEST1_1) == 0);
+//cout << IntToKMG(1024 * 1024 + 1) << " " << TEST1_1 << endl;
+
+res = res && (strcmp(IntToKMG(0), TEST1_0) == 0);
+//cout << IntToKMG(0) << " " << TEST1_0 << endl;
+
+res = res && (strcmp(IntToKMG(LONG_LONG_MIN), TEST1_LLMIN) == 0);
+//cout << IntToKMG(LONG_LONG_MIN) << " " << TEST1_LLMIN << endl;
+
+if (res)
+ cout << "OK" << endl;
+else
+ cout << "Fail" << endl;
+return !res;
+}
+
+int Teststrtodouble2()
+{
+double a;
+int res = 1;
+cout << "Testing strtodouble2: \t\t";
+res = res && !strtodouble2("0.0", a);
+res = res && (a == 0.0);
+res = res && !strtodouble2("0.123456", a);
+res = res && (a == 0.123456);
+res = res && !strtodouble2("123456.0", a);
+res = res && (a == 123456.0);
+res = res && !strtodouble2("123456.123456", a);
+res = res && (a == 123456.123456);
+res = res && !strtodouble2("-0.123456", a);
+res = res && (a == -0.123456);
+res = res && !strtodouble2("-123456.0", a);
+res = res && (a == -123456.0);
+res = res && !strtodouble2("-123456.123456", a);
+res = res && (a == -123456.123456);
+if (res)
+ cout << "OK" << endl;
+else
+ cout << "Fail" << endl;
+return !res;
+}
+
+int TestIsDigit()
+{
+char a;
+int res = 1;
+cout << "Testing IsDigit: \t\t";
+for(a = '0'; a < '9'; a++)
+ res = res && IsDigit(a);
+for(a = 'a'; a < 'z'; a++)
+ res = res && !IsDigit(a);
+if (res)
+ cout << "OK" << endl;
+else
+ cout << "Fail" << endl;
+return !res;
+}
+
+int TestIsAlpha()
+{
+char a;
+int res = 1;
+cout << "Testing IsAlpha: \t\t";
+for(a = '0'; a < '9'; a++)
+ res = res && !IsAlpha(a);
+for(a = 'a'; a < 'z'; a++)
+ res = res && IsAlpha(a);
+if (res)
+ cout << "OK" << endl;
+else
+ cout << "Fail" << endl;
+return !res;
+}
+
+int TestEncodeDecode()
+{
+char enc[256], dec[512];
+int res = 1;
+cout << "Testing EncodeDecode: \t\t";
+Encode12(enc, TEST2_STRING, strlen(TEST2_STRING));
+Decode21(dec, enc);
+res = res && !strcmp(dec, TEST2_STRING);
+Encode12(enc, TEST2_STRING, 256); // Overflow
+Decode21(dec, enc);
+res = res && !strcmp(dec, TEST2_STRING);
+Encode12(enc, TEST2_STRING, 5); // Underflow
+Decode21(dec, enc);
+res = res && !strcmp(dec, TEST2_PART);
+if (res)
+ cout << "OK" << endl;
+else
+ cout << "Fail" << endl;
+return !res;
+}
+
+int TestParseIPString()
+{
+unsigned int ips[4];
+int res = 1;
+cout << "Testing ParseIPString: \t\t";
+res = res && (ParseIPString("127.0.0.1, 192.168.58.1, 10.0.0.1", ips, 4) == 0);
+res = res && ips[0] == 0x0100007F;
+res = res && ips[1] == 0x013AA8C0;
+res = res && ips[2] == 0x0100000A;
+if (res)
+ cout << "OK" << endl;
+else
+ cout << "Fail" << endl;
+return !res;
+}
+
+int TestKOIToWIN()
+{
+char enc[256], dec[256];
+int res = 1;
+cout << "Testing KOIToWin: \t\t";
+KOIToWin(TEST3_STRING, enc, 256);
+WinToKOI(enc, dec, 256);
+res = res && !strcmp(dec, TEST3_STRING);
+KOIToWin(TEST3_STRING, enc, strlen(TEST3_STRING) - 5);
+WinToKOI(enc, dec, strlen(TEST3_STRING) - 5);
+res = res && !strcmp(dec, TEST3_STRING);
+KOIToWin(TEST3_STRING, enc, strlen(TEST3_STRING) + 5);
+WinToKOI(enc, dec, strlen(TEST3_STRING) + 5);
+res = res && !strcmp(dec, TEST3_STRING);
+if (res)
+ cout << "OK" << endl;
+else
+ cout << "Fail" << endl;
+return !res;
+}
+
+int TestDaysInMonth()
+{
+int res = 1;
+cout << "Testing DaysInMonth: \t\t";
+res = res && (DaysInMonth(2000, 0) == 31);
+res = res && (DaysInMonth(2000, 1) == 29);
+res = res && (DaysInMonth(2001, 1) == 28);
+res = res && (DaysInMonth(2100, 1) == 28);
+res = res && (DaysInMonth(2400, 1) == 29);
+res = res && (DaysInMonth(2000, 2) == 31);
+res = res && (DaysInMonth(2000, 3) == 30);
+res = res && (DaysInMonth(2000, 4) == 31);
+res = res && (DaysInMonth(2000, 5) == 30);
+res = res && (DaysInMonth(2000, 6) == 31);
+res = res && (DaysInMonth(2000, 7) == 31);
+res = res && (DaysInMonth(2000, 8) == 30);
+res = res && (DaysInMonth(2000, 9) == 31);
+res = res && (DaysInMonth(2000, 10) == 30);
+res = res && (DaysInMonth(2000, 11) == 31);
+res = res && (DaysInMonth(2000, 20) == 33);
+if (res)
+ cout << "OK" << endl;
+else
+ cout << "Fail" << endl;
+return !res;
+}
+
+int TestBlowfish()
+{
+BLOWFISH_CTX ctx;
+char enc[256], dec[256];
+int res = 1, i, len = strlen(TEST4_STRING);
+cout << "Testing Blowfish: \t\t";
+EnDecodeInit(TEST4_PASSWORD, strlen(TEST4_PASSWORD), &ctx);
+strcpy(dec, TEST4_STRING);
+for(i = 0; i < len; i += 8)
+ EncodeString(&enc[i], &dec[i], &ctx);
+for(i = 0; i < len; i += 8)
+ DecodeString(&dec[i], &enc[i], &ctx);
+res = res && !strcmp(dec, TEST4_STRING);
+if (res)
+ cout << "OK" << endl;
+else
+ cout << "Fail" << endl;
+return !res;
+}
+
+int TestMin8()
+{
+int res = 1;
+cout << "Testing Min8: \t\t\t";
+res = res && (Min8(INT_MAX) == INT_MAX + 1);
+res = res && (Min8(INT_MIN) == INT_MIN);
+res = res && (Min8(0) == 0);
+res = res && (Min8(7) == 8);
+res = res && (Min8(8) == 8);
+res = res && (Min8(9) == 16);
+if (res)
+ cout << "OK" << endl;
+else
+ cout << "Fail" << endl;
+return !res;;
+}
+
+int Testinet_ntostr()
+{
+unsigned long ip;
+char buf[32];
+int res = 1;
+cout << "Testing inet_ntostr: \t\t";
+res = res && (strcmp(inet_ntostr(inet_addr("127.0.0.1")), "127.0.0.1") == 0);
+res = res && (strcmp(inet_ntostr(inet_addr("255.255.255.255")), "255.255.255.255") == 0);
+res = res && (strcmp(inet_ntostr(inet_addr("0.0.0.0")), "0.0.0.0") == 0);
+res = res && (strcmp(inet_ntostr(inet_addr("10.0.0.1")), "10.0.0.1") == 0);
+res = res && (strcmp(inet_ntostr(inet_addr("192.168.58.240")), "192.168.58.240") == 0);
+if (res)
+ cout << "OK" << endl;
+else
+ cout << "Fail" << endl;
+return !res;
+}
+
+int TestParseTariffTimeStr()
+{
+int h1, m1, h2, m2;
+int res = 1;
+cout << "Testing ParseTariffTimeStr: \t";
+res = res && !ParseTariffTimeStr("00:00-00:00", h1, m1, h2, m2);
+res = res && (h1 == 0 && m1 == 0 && h2 == 0 && m2 == 0);
+res = res && !ParseTariffTimeStr("0:0-0:0", h1, m1, h2, m2);
+res = res && (h1 == 0 && m1 == 0 && h2 == 0 && m2 == 0);
+res = res && !ParseTariffTimeStr("99:99-99:99", h1, m1, h2, m2);
+res = res && (h1 == 99 && m1 == 99 && h2 == 99 && m2 == 99);
+res = res && !ParseTariffTimeStr("12:34-56:78", h1, m1, h2, m2);
+res = res && (h1 == 12 && m1 == 34 && h2 == 56 && m2 == 78);
+if (res)
+ cout << "OK" << endl;
+else
+ cout << "Fail" << endl;
+return !res;
+}
+//-----------------------------------------------------------------------------
+int TestStr2XX2Str()
+{
+cout << "Testing Str2XX2Str: \t\t";
+
+# define INT8_MIN (-128)
+# define INT16_MIN (-32767-1)
+# define INT32_MIN (-2147483647-1)
+# define INT64_MIN (-__INT64_C(9223372036854775807)-1)
+# define INT8_MAX (127)
+# define INT16_MAX (32767)
+# define INT32_MAX (2147483647)
+# define INT64_MAX (__INT64_C(9223372036854775807))
+
+int xx;
+string s;
+for (int i = -5000000; i < 5000000; i+=10)
+{
+ x2str(i, s);
+ str2x(s, xx);
+ if (i != xx)
+ {
+ cout << "Fail" << endl;
+ return 1;
+ }
+}
+
+x2str(INT32_MIN, s);
+str2x(s, xx);
+if (xx != INT32_MIN)
+{
+ cout << INT32_MIN << " " << s << endl;
+ cout << INT32_MIN << " " << xx << endl;
+cout << "Fail" << endl;
+ return 1;
+}
+
+x2str(INT32_MAX, s);
+str2x(s, xx);
+if (xx != INT32_MAX)
+{
+cout << "Fail" << endl;
+ return 1;
+}
+cout << "OK" << endl;
+return 0;
+}
+//-----------------------------------------------------------------------------
+
--- /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
+ */
+
+ /*
+ $Revision: 1.4 $
+ $Date: 2007/12/02 18:52:05 $
+ $Author: nobunaga $
+ */
+
+#undef STG_TIME
+
+#define TEST1_LLMAX "8589934592.00 Gb"
+#define TEST1_LLMIN "-8589934592.00 Gb"
+#define TEST1_0 "0.00 kb"
+#define TEST1_1 "1.00 Mb"
+#define TEST2_STRING "This is a test string! 0123456789+-*/"
+#define TEST2_PART "This i"
+#define TEST3_STRING "üÔÏ ÔÅÓÔÏ×ÁÑ ÓÔÒÏËÁ! 0123456789+-*/"
+#define TEST3_PART "üÔÏ ÔÅÓÔÏ×ÁÑ ÓÔÒÏËÁ! 012345678"
+#define TEST4_STRING "Try to encode this using blowfish"
+#define TEST4_PASSWORD "Ha*yN).3zqL!"
+
+int TestIntToKMG();
+int Teststrtodouble2();
+int TestIsDigit();
+int TestIsAlpha();
+int TestEncodeDecode();
+int TestParseIPString();
+int TestKOIToWIN();
+int TestDaysInMonth();
+int TestBlowfish();
+int TestMin8();
+int Testinet_ntostr();
+int TestParseTariffTimeStr();
+int TestStr2XX2Str();
+
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.3 2007/05/08 14:40:09 nobunaga Exp $
+###############################################################################
+
+LIB_NAME = common_settings
+PROG = lib$(LIB_NAME)
+
+SRCS = common_settings.cpp
+
+INCS = common_settings.h
+
+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
+ */
+
+/*
+ * Date: 29.03.2007
+ * Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+/*
+$Revision: 1.2 $
+$Date: 2007/04/07 13:29:07 $
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <string>
+
+using namespace std;
+
+#include "common_settings.h"
+#include "common.h"
+
+//-----------------------------------------------------------------------------
+COMMON_SETTINGS::COMMON_SETTINGS()
+{
+
+}
+//-----------------------------------------------------------------------------
+COMMON_SETTINGS::~COMMON_SETTINGS()
+{
+
+}
+//-----------------------------------------------------------------------------
+int COMMON_SETTINGS::ParseYesNo(const string & value, bool * val)
+{
+if (0 == strcasecmp(value.c_str(), "yes"))
+ {
+ *val = true;
+ return 0;
+ }
+if (0 == strcasecmp(value.c_str(), "no"))
+ {
+ *val = false;
+ return 0;
+ }
+
+strError = "Incorrect value \'" + value + "\'.";
+return -1;
+}
+//-----------------------------------------------------------------------------
+int COMMON_SETTINGS::ParseInt(const string & value, int * val)
+{
+char *res;
+*val = strtol(value.c_str(), &res, 10);
+if (*res != 0)
+ {
+ strError = "Cannot convert \'" + value + "\' to integer.";
+ return -1;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int COMMON_SETTINGS::ParseIntInRange(const string & value, int min, int max, int * val)
+{
+if (ParseInt(value, val) != 0)
+ return -1;
+
+if (*val < min || *val > max)
+ {
+ strError = "Value \'" + value + "\' out of range.";
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int COMMON_SETTINGS::ParseDouble(const std::string & value, double * val)
+{
+char *res;
+*val = strtod(value.c_str(), &res);
+if (*res != 0)
+ {
+ strError = "Cannot convert \'" + value + "\' to double.";
+ return -1;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int COMMON_SETTINGS::ParseDoubleInRange(const std::string & value, double min, double max, double * val)
+{
+if (ParseDouble(value, val) != 0)
+ return -1;
+
+if (*val < min || *val > max)
+ {
+ strError = "Value \'" + value + "\' out of range.";
+ return -1;
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+string COMMON_SETTINGS::GetStrError() const
+{
+return strError;
+}
+//-----------------------------------------------------------------------------
+int COMMON_SETTINGS::Reload ()
+{
+return ReadSettings();
+}
+//-----------------------------------------------------------------------------
+
--- /dev/null
+ /*
+ $Revision: 1.3 $
+ $Date: 2007/10/24 08:04:07 $
+ */
+
+/*
+ * 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: 29.03.2007
+ * Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+ /*
+ $Revision: 1.3 $
+ $Date: 2007/10/24 08:04:07 $
+ */
+
+
+#ifndef common_settingsh_h
+#define common_settingsh_h 1
+
+#include <sys/types.h>
+#include <vector>
+//#include <dotconfpp.h>
+
+#include "common.h"
+#include "base_settings.h"
+
+//-----------------------------------------------------------------------------
+class COMMON_SETTINGS
+{
+public:
+ COMMON_SETTINGS();
+ virtual ~COMMON_SETTINGS();
+ virtual int Reload();
+ virtual int ReadSettings() = 0;
+
+ virtual std::string GetStrError() const;
+
+protected:
+
+ virtual int ParseInt(const std::string & value, int * val);
+ virtual int ParseIntInRange(const std::string & value, int min, int max, int * val);
+
+ virtual int ParseDouble(const std::string & value, double * val);
+ virtual int ParseDoubleInRange(const std::string & value, double min, double max, double * val);
+
+ virtual int ParseYesNo(const std::string & value, bool * val);
+
+ mutable std::string strError;
+};
+//-----------------------------------------------------------------------------
+#endif
+
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.4 2007/05/08 14:29:19 faust Exp $
+###############################################################################
+
+LIB_NAME = conffiles
+PROG = lib$(LIB_NAME)
+
+SRCS = conffiles.cpp
+
+INCS = conffiles.h
+
+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
+ */
+
+/*
+ * Date: 27.10.2002
+ */
+
+/*
+ * Author : Boris Mikhailenko <stg34@ua.fm>
+ */
+
+ /*
+ $Revision: 1.5 $
+ $Date: 2009/10/22 11:40:22 $
+ */
+
+//---------------------------------------------------------------------------
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fstream>
+#include <algorithm>
+#include "conffiles.h"
+#include "common.h"
+
+using namespace std;
+
+//---------------------------------------------------------------------------
+bool StringCaseCmp(const string & str1, const string & str2)
+{
+return (strcasecmp(str1.c_str(), str2.c_str()) < 0);
+}
+//---------------------------------------------------------------------------
+CONFIGFILE::CONFIGFILE(const string &fn):
+param_val(StringCaseCmp)
+{
+fileName = fn;
+f = fopen(fn.c_str(), "rt");
+
+error = 0;
+param_val.clear();
+
+if (!f)
+ {
+ error = -1;
+ return;
+ }
+
+string line, parameter, value;
+
+unsigned long pos;
+bool emptyLine;
+unsigned char c;
+
+while (!feof(f))
+ {
+ line.erase(line.begin(), line.end());
+
+ c = fgetc(f);
+ while (!feof(f))
+ {
+ //printf("%c", c);
+ if (c == '\n')
+ break;
+ line.push_back(c);
+ c = fgetc(f);
+ }
+
+ pos = line.find('#');
+ if (pos != string::npos)
+ line.resize(pos);
+
+ emptyLine = true;
+ for (unsigned int i = 0; i < line.size(); i++)
+ {
+ if (line[i] != ' ' && line[i] != '\t' && line[i] != '\n' && line[i] != '\r')
+ {
+ emptyLine = false;
+ break;
+ }
+ }
+ if (emptyLine)
+ {
+ continue;
+ }
+
+ pos = line.find("=");
+ if (pos == string::npos)
+ {
+ fclose(f);
+ error = -1;
+ //printf("%s find(=) error\n", __FILE__);
+ return;
+ }
+ parameter = line.substr(0, pos);
+ //transform(parameter.begin(), parameter.end(), parameter.begin(), tolower);
+ value = line.substr(pos + 1);
+ //cout << parameter << "==" << value << endl;
+ param_val[parameter] = value;
+ //cout << parameter << "==" << param_val[parameter] << endl;
+ }
+
+fclose(f);
+}
+//---------------------------------------------------------------------------
+CONFIGFILE::~CONFIGFILE()
+{
+
+}
+//---------------------------------------------------------------------------
+const string & CONFIGFILE::GetFileName() const
+{
+return fileName;
+}
+//---------------------------------------------------------------------------
+int CONFIGFILE::Error()
+{
+int e = error;
+error = 0;
+return e;
+}
+//---------------------------------------------------------------------------
+int CONFIGFILE::FindParameter(const string ¶meter, string * value) const
+{
+it = param_val.find(parameter);
+if (it == param_val.end())
+ return -1;
+
+*value = param_val[parameter];
+return 0;
+}
+//---------------------------------------------------------------------------
+int CONFIGFILE::Flush()
+{
+fstream f(fileName.c_str(), ios::out);
+if (!f.is_open())
+ {
+ error = EIO;
+ return EIO;
+ }
+
+it = param_val.begin();
+while (it != param_val.end())
+ {
+ f << it->first << "=" << it->second << endl;
+ it++;
+ }
+
+f.close();
+
+return 0;
+}
+//---------------------------------------------------------------------------
+int CONFIGFILE::ReadString(const string & param, char * str, int * maxLen, const char * defaultVal) const
+{
+it = param_val.find(param);
+// îÁÛÌÉ ÎÕÖÎÕÀ ÐÅÒÅÍÅÎÎÕÀ
+
+if (it != param_val.end())
+ {
+ // þÔÏ-ÔÏ ÓÔÏÉÔ
+ strncpy(str, param_val[param].c_str(), *maxLen);
+ *maxLen = param_val[param].size();
+ return 0;
+ }
+
+strncpy(str, defaultVal, *maxLen);
+*maxLen = strlen(defaultVal);
+return -1;
+}
+//---------------------------------------------------------------------------
+int CONFIGFILE::ReadString(const string & param, string * val, const string & defaultVal) const
+{
+it = param_val.find(param);
+// îÁÛÌÉ ÎÕÖÎÕÀ ÐÅÒÅÍÅÎÎÕÀ
+
+if (it != param_val.end())
+ {
+ // þÔÏ-ÔÏ ÓÔÏÉÔ
+ *val = param_val[param];
+ return 0;
+ }
+
+*val = defaultVal;
+return -1;
+}
+//---------------------------------------------------------------------------
+int CONFIGFILE::WriteString(const string & param, const char * val)
+{
+WriteString(param, string(val));
+return 0;
+}
+//---------------------------------------------------------------------------
+int CONFIGFILE::WriteString(const string & param, const string &val)
+{
+param_val[param] = val;
+Flush();
+return 0;
+}
+//---------------------------------------------------------------------------
+int CONFIGFILE::ReadTime(const string & param, time_t * val, time_t defaultVal) const
+{
+it = param_val.find(param);
+
+if (it != param_val.end())
+ {
+ char *res;
+ *val = strtol(param_val[param].c_str(), &res, 10);
+ if (*res != 0)
+ {
+ *val = defaultVal; //Error!
+ return EINVAL;
+ }
+ return 0;
+ }
+
+*val = defaultVal;
+return -1;
+}
+//---------------------------------------------------------------------------
+int CONFIGFILE::ReadInt(const string & param, int * val, int defaultVal) const
+{
+it = param_val.find(param);
+// îÁÛÌÉ ÎÕÖÎÕÀ ÐÅÒÅÍÅÎÎÕÀ
+
+if (it != param_val.end())
+ {
+ // þÔÏ-ÔÏ ÓÔÏÉÔ
+ char *res;
+ *val = strtol(param_val[param].c_str(), &res, 10);
+ if (*res != 0)
+ {
+ *val = defaultVal; //Error!
+ return EINVAL;
+ }
+ return 0;
+ }
+
+*val = defaultVal;
+return -1;
+}
+//---------------------------------------------------------------------------
+int CONFIGFILE::ReadUInt(const string & param, unsigned int * val, unsigned int defaultVal) const
+{
+it = param_val.find(param);
+// îÁÛÌÉ ÎÕÖÎÕÀ ÐÅÒÅÍÅÎÎÕÀ
+
+if (it != param_val.end())
+ {
+ // þÔÏ-ÔÏ ÓÔÏÉÔ
+ char *res;
+ *val = strtoul(param_val[param].c_str(), &res, 10);
+ if (*res != 0)
+ {
+ *val = defaultVal; //Error!
+ return EINVAL;
+ }
+ return 0;
+ }
+
+*val = defaultVal;
+return -1;
+}
+//---------------------------------------------------------------------------
+int CONFIGFILE::ReadLongInt(const string & param, long int * val, long int defaultVal) const
+{
+it = param_val.find(param);
+// îÁÛÌÉ ÎÕÖÎÕÀ ÐÅÒÅÍÅÎÎÕÀ
+
+if (it != param_val.end())
+ {
+ // þÔÏ-ÔÏ ÓÔÏÉÔ
+ char *res;
+ *val = strtol(param_val[param].c_str(), &res, 10);
+ if (*res != 0)
+ {
+ *val = defaultVal; //Error!
+ return EINVAL;
+ }
+ return 0;
+ }
+
+*val = defaultVal;
+return -1;
+}
+//---------------------------------------------------------------------------
+int CONFIGFILE::ReadULongInt(const string & param, unsigned long int * val, unsigned long int defaultVal) const
+{
+it = param_val.find(param);
+// îÁÛÌÉ ÎÕÖÎÕÀ ÐÅÒÅÍÅÎÎÕÀ
+
+if (it != param_val.end())
+ {
+ // þÔÏ-ÔÏ ÓÔÏÉÔ
+ char *res;
+ *val = strtoul(param_val[param].c_str(), &res, 10);
+ if (*res != 0)
+ {
+ *val = defaultVal; //Error!
+ return EINVAL;
+ }
+ return 0;
+ }
+
+*val = defaultVal;
+return -1;
+}
+//---------------------------------------------------------------------------
+int CONFIGFILE::ReadLongLongInt(const string & param, int64_t * val, int64_t defaultVal) const
+{
+it = param_val.find(param);
+// îÁÛÌÉ ÎÕÖÎÕÀ ÐÅÒÅÍÅÎÎÕÀ
+
+if (it != param_val.end())
+ {
+ // þÔÏ-ÔÏ ÓÔÏÉÔ
+ char *res;
+ *val = strtoll(param_val[param].c_str(), &res, 10);
+ if (*res != 0)
+ {
+ *val = defaultVal; //Error!
+ return EINVAL;
+ }
+ return 0;
+ }
+
+*val = defaultVal;
+return -1;
+}
+//---------------------------------------------------------------------------
+int CONFIGFILE::ReadULongLongInt(const string & param, uint64_t * val, uint64_t defaultVal) const
+{
+it = param_val.find(param);
+// îÁÛÌÉ ÎÕÖÎÕÀ ÐÅÒÅÍÅÎÎÕÀ
+
+if (it != param_val.end())
+ {
+ // þÔÏ-ÔÏ ÓÔÏÉÔ
+ char *res;
+ *val = strtoull(param_val[param].c_str(), &res, 10);
+ if (*res != 0)
+ {
+ *val = defaultVal; //Error!
+ return EINVAL;
+ }
+ return 0;
+ }
+
+*val = defaultVal;
+return -1;
+}
+//---------------------------------------------------------------------------
+int CONFIGFILE::ReadShortInt(const string & param, short int * val, short int defaultVal) const
+{
+it = param_val.find(param);
+// îÁÛÌÉ ÎÕÖÎÕÀ ÐÅÒÅÍÅÎÎÕÀ
+
+if (it != param_val.end())
+ {
+ // þÔÏ-ÔÏ ÓÔÏÉÔ
+ char *res;
+ *val = (short)strtol(param_val[param].c_str(), &res, 10);
+ if (*res != 0)
+ {
+ *val = defaultVal; //Error!
+ return EINVAL;
+ }
+ return 0;
+ }
+
+*val = defaultVal;
+return -1;
+}
+//---------------------------------------------------------------------------
+int CONFIGFILE::ReadUShortInt(const string & param, unsigned short int * val, unsigned short int defaultVal) const
+{
+it = param_val.find(param);
+// îÁÛÌÉ ÎÕÖÎÕÀ ÐÅÒÅÍÅÎÎÕÀ
+
+if (it != param_val.end())
+ {
+ // þÔÏ-ÔÏ ÓÔÏÉÔ
+ char *res;
+ *val = (short)strtoul(param_val[param].c_str(), &res, 10);
+ if (*res != 0)
+ {
+ *val = defaultVal; //Error!
+ return EINVAL;
+ }
+ return 0;
+ }
+
+*val = defaultVal;
+return -1;
+}
+//---------------------------------------------------------------------------
+int CONFIGFILE::WriteInt(const string & param, int64_t val)
+{
+string s;
+//sprintf(s, "%lld", val);
+x2str(val, s);
+param_val[param] = s;
+Flush();
+return 0;
+}
+//---------------------------------------------------------------------------
+int CONFIGFILE::ReadDouble(const string & param, double * val, double defaultVal) const
+{
+it = param_val.find(param);
+// îÁÛÌÉ ÎÕÖÎÕÀ ÐÅÒÅÍÅÎÎÕÀ
+
+if (it != param_val.end())
+ {
+ // þÔÏ-ÔÏ ÓÔÏÉÔ
+ char *res;
+ *val = strtod(param_val[param].c_str(), &res);
+ if (*res != 0)
+ {
+ //cout << param << "=" << param_val[param] << " Error!!!\n";
+ *val = defaultVal; //Error!
+ return EINVAL;
+ }
+ return 0;
+ }
+
+//cout << "îÉÞÅÇÏ ÎÅÔ!!!\n";
+
+*val = defaultVal;
+return -1;
+}
+//---------------------------------------------------------------------------
+int CONFIGFILE::WriteDouble(const string & param, double val)
+{
+char s[30];
+sprintf(s, "%f", val);
+param_val[param] = s;
+Flush();
+return 0;
+}
+//---------------------------------------------------------------------------
+
+
--- /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@ua.fm>
+ */
+
+ /*
+ $Revision: 1.5 $
+ $Date: 2009/06/22 16:00:38 $
+ */
+
+//---------------------------------------------------------------------------
+
+#ifndef ConfFilesH
+#define ConfFilesH
+#include <sys/types.h>
+#include <stdio.h>
+#include <map>
+#include <string>
+
+#include "os_int.h"
+
+using namespace std;
+//---------------------------------------------------------------------------
+//#define CONF_STR_LEN 300
+//typedef char STRING[CONF_STR_LEN];
+
+typedef bool (*StringCaseCmp_t)(const string & str1, const string & str2);
+
+class CONFIGFILE
+{
+private:
+ mutable map<string, string, StringCaseCmp_t> param_val;
+ mutable map<string, string>::iterator it;
+
+ FILE * f;
+ int Flush();
+ //int ReadFile();
+ string fileName;
+ int error;
+
+public:
+ CONFIGFILE(const string &fn);
+ ~CONFIGFILE();
+ const string & GetFileName() const;
+
+ // 5 ÆÕÎËÃÉÉ Read* ×ÏÚ×ÒÁÝÁÀÔ 0 ÐÒÉ ÕÓÐÅÛÎÏÍ ÓÞÉÔÙ×ÁÎÉÉ
+ // É EINVAL ÐÒÉ ÏÔÓÕÔÓ×ÉÉ ÐÁÒÁÍÅÔÒÁ É ×ÙÓÔÁ×ÌÑÀÔ defaulValue
+ int ReadString(const string & param, char * val, int * maxLen, const char * defaultVal) const;
+ int ReadString(const string & param, string * val, const string & defaultVal) const;
+
+ int FindParameter(const string ¶meter, string * value) const;
+
+ int ReadTime (const string & param, time_t *, time_t) const;
+
+ int ReadShortInt (const string & param, short int *, short int) const;
+ int ReadInt (const string & param, int *, int) const;
+ int ReadLongInt (const string & param, long int *, long int) const;
+ int ReadLongLongInt(const string & param, int64_t *, int64_t) const;
+
+ int ReadUShortInt (const string & param, unsigned short int *, unsigned short int) const;
+ int ReadUInt (const string & param, unsigned int *, unsigned int) const;
+ int ReadULongInt (const string & param, unsigned long int *, unsigned long int) const;
+ int ReadULongLongInt(const string & param, uint64_t *, uint64_t) const;
+
+ int ReadDouble (const string & param, double * val, double defaultVal) const;
+
+ int WriteString(const string & param, const char * val);
+ int WriteString(const string & param, const string & val);
+ int WriteInt (const string & param, int64_t val);
+ int WriteDouble(const string & param, double val);
+
+ int Error();
+};
+//---------------------------------------------------------------------------
+#endif
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.5 2009/10/09 07:15:48 nobunaga Exp $
+###############################################################################
+
+LIB_NAME = stg_crypto
+PROG = lib$(LIB_NAME)
+
+SRCS = ag_md5.cpp \
+ blowfish.cpp
+
+INCS = ag_md5.h \
+ blowfish.h
+
+include ../Makefile.in
--- /dev/null
+
+#ifdef WIN32
+#include <process.h>
+#include <windows.h>
+#else
+#include <sys/time.h>
+#include <unistd.h>
+#endif
+
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "ag_md5.h"
+
+
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+#define MD5STEP(f, w, x, y, z, data, s) \
+ ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
+
+
+int i64c(int i)
+{
+ if (i <= 0)
+ return ('.');
+
+ if (i == 1)
+ return ('/');
+
+ if (i >= 2 && i < 12)
+ return ('0' - 2 + i);
+
+ if (i >= 12 && i < 38)
+ return ('A' - 12 + i);
+
+ if (i >= 38 && i < 63)
+ return ('a' - 38 + i);
+
+ return ('z');
+}
+
+char * l64a_(long l)
+{
+ static char buf[8];
+ int i = 0;
+
+ if (l < 0L)
+ return ((char *) 0);
+
+ do {
+ buf[i++] = i64c ((int) (l % 64));
+ buf[i] = '\0';
+ } while (l /= 64L, l > 0 && i < 6);
+
+ return (buf);
+}
+
+char * crypt_make_salt(void)
+{
+
+ static char result[40];
+ #ifdef WIN32
+ unsigned int tsec;
+ #else
+ struct timeval tv;
+ #endif
+
+ result[0] = '\0';
+ strcpy(result, "$1$"); /* magic for the new MD5 crypt() */
+
+ /*
+ * Generate 8 chars of salt, the old crypt() will use only first 2.
+ */
+ #ifdef WIN32
+ strcat(result, l64a_(GetTickCount()));
+ tsec = time(NULL);
+ strcat(result, l64a_(tsec + getpid() + clock()));
+ #else
+ gettimeofday(&tv, (struct timezone *) 0);
+ strcat(result, l64a_(tv.tv_usec));
+ strcat(result, l64a_(tv.tv_sec + getpid() + clock()));
+ #endif
+
+ if (strlen(result) > 3 + 8) /* magic+salt */
+ result[11] = '\0';
+
+ return result;
+}
+
+void byteReverse(unsigned char *buf, unsigned longs)
+{
+ uint32_t t;
+ do {
+ t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
+ ((unsigned) buf[1] << 8 | buf[0]);
+ *(uint32_t *) buf = t;
+ buf += 4;
+ } while (--longs);
+}
+
+/*
+ * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void MD5Init(struct MD5Context *ctx)
+{
+ ctx->buf[0] = 0x67452301;
+ ctx->buf[1] = 0xefcdab89;
+ ctx->buf[2] = 0x98badcfe;
+ ctx->buf[3] = 0x10325476;
+
+ ctx->bits[0] = 0;
+ ctx->bits[1] = 0;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void MD5Update(struct MD5Context *ctx, char const *buf, unsigned len)
+{
+ uint32_t t;
+
+ /* Update bitcount */
+
+ t = ctx->bits[0];
+ if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t)
+ ctx->bits[1]++; /* Carry from low to high */
+ ctx->bits[1] += len >> 29;
+
+ t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
+
+ /* Handle any leading odd-sized chunks */
+
+ if (t) {
+ unsigned char *p = (unsigned char *) ctx->in + t;
+
+ t = 64 - t;
+ if (len < t) {
+ memcpy(p, buf, len);
+ return;
+ }
+ memcpy(p, buf, t);
+ byteReverse(ctx->in, 16);
+ MD5Transform(ctx->buf, (uint32_t *) ctx->in);
+ buf += t;
+ len -= t;
+ }
+ /* Process data in 64-byte chunks */
+
+ while (len >= 64) {
+ memcpy(ctx->in, buf, 64);
+ byteReverse(ctx->in, 16);
+ MD5Transform(ctx->buf, (uint32_t *) ctx->in);
+ buf += 64;
+ len -= 64;
+ }
+
+ /* Handle any remaining bytes of data. */
+
+ memcpy(ctx->in, buf, len);
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void
+MD5Final(unsigned char digest[16], struct MD5Context *ctx)
+{
+ unsigned count;
+ unsigned char *p;
+
+ /* Compute number of bytes mod 64 */
+ count = (ctx->bits[0] >> 3) & 0x3F;
+
+ /* Set the first char of padding to 0x80. This is safe since there is
+ always at least one byte free */
+ p = ctx->in + count;
+ *p++ = 0x80;
+
+ /* Bytes of padding needed to make 64 bytes */
+ count = 64 - 1 - count;
+
+ /* Pad out to 56 mod 64 */
+ if (count < 8) {
+ /* Two lots of padding: Pad the first block to 64 bytes */
+ memset(p, 0, count);
+ byteReverse(ctx->in, 16);
+ MD5Transform(ctx->buf, (uint32_t *) ctx->in);
+
+ /* Now fill the next block with 56 bytes */
+ memset(ctx->in, 0, 56);
+ } else {
+ /* Pad block to 56 bytes */
+ memset(p, 0, count - 8);
+ }
+ byteReverse(ctx->in, 14);
+
+ /* Append length in bits and transform */
+ ((uint32_t *) ctx->in)[14] = ctx->bits[0];
+ ((uint32_t *) ctx->in)[15] = ctx->bits[1];
+
+ MD5Transform(ctx->buf, (uint32_t *) ctx->in);
+ byteReverse((unsigned char *) ctx->buf, 4);
+ memcpy(digest, ctx->buf, 16);
+ memset((char *) ctx, 0, sizeof(ctx)); /* In case it's sensitive */
+}
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data. MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+void
+MD5Transform(uint32_t buf[4], uint32_t const in[16])
+{
+ register uint32_t a, b, c, d;
+
+ a = buf[0];
+ b = buf[1];
+ c = buf[2];
+ d = buf[3];
+
+ MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+ MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+ MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+ MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+ MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+ MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+ MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+ MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+ MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+ MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+ MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+ MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+ MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+ MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+ MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+ MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+ MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+ MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+ MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+ MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+ MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+ MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+ MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+ MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+ MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+ MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+ MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+ MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+ MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+ MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+ MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+ MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+ MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+ MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+ MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+ MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+ MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+ MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+ MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+ MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+ MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+ MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+ MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+ MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+ MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+ MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+ MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+ MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+ MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+ MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+ MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+ MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+ MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+ MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+ MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+ MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+ MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+ MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+ MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+ MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+ MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+ MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+ MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+ MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
+}
+
+static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */
+ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+static void
+to64(char *s, unsigned long v, int n)
+{
+ while (--n >= 0) {
+ *s++ = itoa64[v&0x3f];
+ v >>= 6;
+ }
+}
+
+/*
+ * UNIX password
+ *
+ * Use MD5 for what it is best at...
+ */
+
+char *
+libshadow_md5_crypt(const char *pw, const char *salt)
+{
+ static const char *magic = "$1$"; /*
+ * This string is magic for
+ * this algorithm. Having
+ * it this way, we can get
+ * get better later on
+ */
+ static char passwd[120], *p;
+ static const char *sp,*ep;
+ unsigned char final[16];
+ int sl,pl,i,j;
+ MD5_CTX ctx,ctx1;
+ unsigned long l;
+
+ /* Refine the Salt first */
+ sp = salt;
+
+ /* If it starts with the magic string, then skip that */
+ if(!strncmp(sp,magic,strlen(magic)))
+ sp += strlen(magic);
+
+ /* It stops at the first '$', max 8 chars */
+ for(ep=sp;*ep && *ep != '$' && ep < (sp+8);ep++)
+ continue;
+
+ /* get the length of the true salt */
+ sl = ep - sp;
+
+ MD5Init(&ctx);
+
+ /* The password first, since that is what is most unknown */
+ MD5Update(&ctx, pw, strlen(pw));
+
+ /* Then our magic string */
+ MD5Update(&ctx, magic, strlen(magic));
+
+ /* Then the raw salt */
+ MD5Update(&ctx, sp, sl);
+
+ /* Then just as many characters of the MD5(pw,salt,pw) */
+ MD5Init(&ctx1);
+ MD5Update(&ctx1,pw,strlen(pw));
+ MD5Update(&ctx1,sp,sl);
+ MD5Update(&ctx1,pw,strlen(pw));
+ MD5Final(final,&ctx1);
+ for(pl = strlen(pw); pl > 0; pl -= 16)
+ MD5Update(&ctx, (char*)final, pl>16 ? 16 : pl);
+
+ /* Don't leave anything around in vm they could use. */
+ memset(final,0,sizeof final);
+
+ /* Then something really weird... */
+ for (j=0,i = strlen(pw); i ; i >>= 1)
+ if(i&1)
+ MD5Update(&ctx, (char*)final+j, 1);
+ else
+ MD5Update(&ctx, pw+j, 1);
+
+ /* Now make the output string */
+ strcpy(passwd,magic);
+ strncat(passwd,sp,sl);
+ strcat(passwd,"$");
+
+ MD5Final(final,&ctx);
+
+ /*
+ * and now, just to make sure things don't run too fast
+ * On a 60 Mhz Pentium this takes 34 msec, so you would
+ * need 30 seconds to build a 1000 entry dictionary...
+ */
+ /*
+ for(i=0;i<1000;i++) {
+ MD5Init(&ctx1);
+ if(i & 1)
+ MD5Update(&ctx1,pw,strlen(pw));
+ else
+ MD5Update(&ctx1,final,16);
+
+ if(i % 3)
+ MD5Update(&ctx1,sp,sl);
+
+ if(i % 7)
+ MD5Update(&ctx1,pw,strlen(pw));
+
+ if(i & 1)
+ MD5Update(&ctx1,final,16);
+ else
+ MD5Update(&ctx1,pw,strlen(pw));
+ MD5Final(final,&ctx1);
+ }*/
+
+ p = passwd + strlen(passwd);
+
+ l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p,l,4); p += 4;
+ l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p,l,4); p += 4;
+ l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p,l,4); p += 4;
+ l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p,l,4); p += 4;
+ l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p,l,4); p += 4;
+ l = final[11] ; to64(p,l,2); p += 2;
+ *p = '\0';
+
+ /* Don't leave anything around in vm they could use. */
+ memset(final,0,sizeof final);
+
+ return passwd;
+}
+
+char *pw_encrypt(const char *clear, const char *salt) {
+
+ /*
+ * If the salt string from the password file or from crypt_make_salt()
+ * begins with the magic string, use the new algorithm.
+ */
+ if (strncmp(salt, "$1$", 3) == 0)
+ return(libshadow_md5_crypt(clear, salt));
+ else return(NULL);
+
+}
+/* AG MD5 functions */
+char *make_ag_hash(time_t salt, const char *clear) {
+ char salt_str[20];
+ char *res=NULL;
+ char *p;
+
+ unsigned long slt = salt;
+ sprintf(salt_str, "$1$%08lx", slt);
+ res=libshadow_md5_crypt(clear, salt_str);
+ p=strrchr(res, '$');
+ return(++p);
+}
+
+int check_ag_hash(time_t salt, const char *clear, const char *hash) {
+ return(strcmp(hash, make_ag_hash(salt, clear)));
+}
+
--- /dev/null
+#ifndef _MD5_H
+#define _MD5_H
+
+#include <time.h>
+
+#include "os_int.h"
+
+struct MD5Context {
+ uint32_t buf[4];
+ uint32_t bits[2];
+ unsigned char in[64];
+};
+
+typedef struct MD5Context MD5_CTX;
+
+char *crypt_make_salt(void);
+void byteReverse(unsigned char*, unsigned);
+void MD5Init(struct MD5Context *ctx);
+void MD5Update(struct MD5Context*, char const*, unsigned);
+void MD5Final(unsigned char digest[16], struct MD5Context *ctx);
+void MD5Transform(uint32_t buf[4], uint32_t const in[16]);
+/* static void to64(char*, unsigned long, int); */
+char *libshadow_md5_crypt(const char*, const char*);
+char *pw_encrypt(const char*, const char*);
+
+/* AG functions */
+char *make_ag_hash(time_t salt, const char *clear);
+int check_ag_hash(time_t salt, const char *clear, const char *hash);
+
+#endif /* _MD5_H */
--- /dev/null
+/*
+ * Author : Paul Kocher
+ * E-mail : pck@netcom.com
+ * Date : 1997
+ * Description: C implementation of the Blowfish algorithm.
+ */
+
+#include <string.h>
+
+#include "blowfish.h"
+#include "stg_const.h"
+
+/*typedef struct _BCoptions
+ {
+ unsigned char remove;
+ unsigned char standardout;
+ unsigned char compression;
+ unsigned char type;
+ uint32_t origsize;
+ unsigned char securedelete;
+ } BCoptions;*/
+
+#define ENCRYPT 0
+#define DECRYPT 1
+
+#define endianBig ((unsigned char) 0x45)
+#define endianLittle ((unsigned char) 0x54)
+
+#ifdef WIN32 /* Win32 doesn't have random() or lstat */
+ #define random() rand()
+ #define initstate(x,y,z) srand(x)
+ #define lstat(x,y) stat(x,y)
+#endif
+
+#ifndef S_ISREG
+ #define S_ISREG(x) ( ((x)&S_IFMT)==S_IFREG )
+#endif
+
+
+#define N 16
+
+static uint32_t F(BLOWFISH_CTX *ctx, uint32_t x);
+static const uint32_t ORIG_P[16 + 2] = {
+0x243F6A88L, 0x85A308D3L, 0x13198A2EL, 0x03707344L,
+0xA4093822L, 0x299F31D0L, 0x082EFA98L, 0xEC4E6C89L,
+0x452821E6L, 0x38D01377L, 0xBE5466CFL, 0x34E90C6CL,
+0xC0AC29B7L, 0xC97C50DDL, 0x3F84D5B5L, 0xB5470917L,
+0x9216D5D9L, 0x8979FB1BL
+};
+
+static const uint32_t ORIG_S[4][256] = {
+{ 0xD1310BA6L, 0x98DFB5ACL, 0x2FFD72DBL, 0xD01ADFB7L,
+ 0xB8E1AFEDL, 0x6A267E96L, 0xBA7C9045L, 0xF12C7F99L,
+ 0x24A19947L, 0xB3916CF7L, 0x0801F2E2L, 0x858EFC16L,
+ 0x636920D8L, 0x71574E69L, 0xA458FEA3L, 0xF4933D7EL,
+ 0x0D95748FL, 0x728EB658L, 0x718BCD58L, 0x82154AEEL,
+ 0x7B54A41DL, 0xC25A59B5L, 0x9C30D539L, 0x2AF26013L,
+ 0xC5D1B023L, 0x286085F0L, 0xCA417918L, 0xB8DB38EFL,
+ 0x8E79DCB0L, 0x603A180EL, 0x6C9E0E8BL, 0xB01E8A3EL,
+ 0xD71577C1L, 0xBD314B27L, 0x78AF2FDAL, 0x55605C60L,
+ 0xE65525F3L, 0xAA55AB94L, 0x57489862L, 0x63E81440L,
+ 0x55CA396AL, 0x2AAB10B6L, 0xB4CC5C34L, 0x1141E8CEL,
+ 0xA15486AFL, 0x7C72E993L, 0xB3EE1411L, 0x636FBC2AL,
+ 0x2BA9C55DL, 0x741831F6L, 0xCE5C3E16L, 0x9B87931EL,
+ 0xAFD6BA33L, 0x6C24CF5CL, 0x7A325381L, 0x28958677L,
+ 0x3B8F4898L, 0x6B4BB9AFL, 0xC4BFE81BL, 0x66282193L,
+ 0x61D809CCL, 0xFB21A991L, 0x487CAC60L, 0x5DEC8032L,
+ 0xEF845D5DL, 0xE98575B1L, 0xDC262302L, 0xEB651B88L,
+ 0x23893E81L, 0xD396ACC5L, 0x0F6D6FF3L, 0x83F44239L,
+ 0x2E0B4482L, 0xA4842004L, 0x69C8F04AL, 0x9E1F9B5EL,
+ 0x21C66842L, 0xF6E96C9AL, 0x670C9C61L, 0xABD388F0L,
+ 0x6A51A0D2L, 0xD8542F68L, 0x960FA728L, 0xAB5133A3L,
+ 0x6EEF0B6CL, 0x137A3BE4L, 0xBA3BF050L, 0x7EFB2A98L,
+ 0xA1F1651DL, 0x39AF0176L, 0x66CA593EL, 0x82430E88L,
+ 0x8CEE8619L, 0x456F9FB4L, 0x7D84A5C3L, 0x3B8B5EBEL,
+ 0xE06F75D8L, 0x85C12073L, 0x401A449FL, 0x56C16AA6L,
+ 0x4ED3AA62L, 0x363F7706L, 0x1BFEDF72L, 0x429B023DL,
+ 0x37D0D724L, 0xD00A1248L, 0xDB0FEAD3L, 0x49F1C09BL,
+ 0x075372C9L, 0x80991B7BL, 0x25D479D8L, 0xF6E8DEF7L,
+ 0xE3FE501AL, 0xB6794C3BL, 0x976CE0BDL, 0x04C006BAL,
+ 0xC1A94FB6L, 0x409F60C4L, 0x5E5C9EC2L, 0x196A2463L,
+ 0x68FB6FAFL, 0x3E6C53B5L, 0x1339B2EBL, 0x3B52EC6FL,
+ 0x6DFC511FL, 0x9B30952CL, 0xCC814544L, 0xAF5EBD09L,
+ 0xBEE3D004L, 0xDE334AFDL, 0x660F2807L, 0x192E4BB3L,
+ 0xC0CBA857L, 0x45C8740FL, 0xD20B5F39L, 0xB9D3FBDBL,
+ 0x5579C0BDL, 0x1A60320AL, 0xD6A100C6L, 0x402C7279L,
+ 0x679F25FEL, 0xFB1FA3CCL, 0x8EA5E9F8L, 0xDB3222F8L,
+ 0x3C7516DFL, 0xFD616B15L, 0x2F501EC8L, 0xAD0552ABL,
+ 0x323DB5FAL, 0xFD238760L, 0x53317B48L, 0x3E00DF82L,
+ 0x9E5C57BBL, 0xCA6F8CA0L, 0x1A87562EL, 0xDF1769DBL,
+ 0xD542A8F6L, 0x287EFFC3L, 0xAC6732C6L, 0x8C4F5573L,
+ 0x695B27B0L, 0xBBCA58C8L, 0xE1FFA35DL, 0xB8F011A0L,
+ 0x10FA3D98L, 0xFD2183B8L, 0x4AFCB56CL, 0x2DD1D35BL,
+ 0x9A53E479L, 0xB6F84565L, 0xD28E49BCL, 0x4BFB9790L,
+ 0xE1DDF2DAL, 0xA4CB7E33L, 0x62FB1341L, 0xCEE4C6E8L,
+ 0xEF20CADAL, 0x36774C01L, 0xD07E9EFEL, 0x2BF11FB4L,
+ 0x95DBDA4DL, 0xAE909198L, 0xEAAD8E71L, 0x6B93D5A0L,
+ 0xD08ED1D0L, 0xAFC725E0L, 0x8E3C5B2FL, 0x8E7594B7L,
+ 0x8FF6E2FBL, 0xF2122B64L, 0x8888B812L, 0x900DF01CL,
+ 0x4FAD5EA0L, 0x688FC31CL, 0xD1CFF191L, 0xB3A8C1ADL,
+ 0x2F2F2218L, 0xBE0E1777L, 0xEA752DFEL, 0x8B021FA1L,
+ 0xE5A0CC0FL, 0xB56F74E8L, 0x18ACF3D6L, 0xCE89E299L,
+ 0xB4A84FE0L, 0xFD13E0B7L, 0x7CC43B81L, 0xD2ADA8D9L,
+ 0x165FA266L, 0x80957705L, 0x93CC7314L, 0x211A1477L,
+ 0xE6AD2065L, 0x77B5FA86L, 0xC75442F5L, 0xFB9D35CFL,
+ 0xEBCDAF0CL, 0x7B3E89A0L, 0xD6411BD3L, 0xAE1E7E49L,
+ 0x00250E2DL, 0x2071B35EL, 0x226800BBL, 0x57B8E0AFL,
+ 0x2464369BL, 0xF009B91EL, 0x5563911DL, 0x59DFA6AAL,
+ 0x78C14389L, 0xD95A537FL, 0x207D5BA2L, 0x02E5B9C5L,
+ 0x83260376L, 0x6295CFA9L, 0x11C81968L, 0x4E734A41L,
+ 0xB3472DCAL, 0x7B14A94AL, 0x1B510052L, 0x9A532915L,
+ 0xD60F573FL, 0xBC9BC6E4L, 0x2B60A476L, 0x81E67400L,
+ 0x08BA6FB5L, 0x571BE91FL, 0xF296EC6BL, 0x2A0DD915L,
+ 0xB6636521L, 0xE7B9F9B6L, 0xFF34052EL, 0xC5855664L,
+ 0x53B02D5DL, 0xA99F8FA1L, 0x08BA4799L, 0x6E85076AL},
+
+{ 0x4B7A70E9L, 0xB5B32944L, 0xDB75092EL, 0xC4192623L,
+ 0xAD6EA6B0L, 0x49A7DF7DL, 0x9CEE60B8L, 0x8FEDB266L,
+ 0xECAA8C71L, 0x699A17FFL, 0x5664526CL, 0xC2B19EE1L,
+ 0x193602A5L, 0x75094C29L, 0xA0591340L, 0xE4183A3EL,
+ 0x3F54989AL, 0x5B429D65L, 0x6B8FE4D6L, 0x99F73FD6L,
+ 0xA1D29C07L, 0xEFE830F5L, 0x4D2D38E6L, 0xF0255DC1L,
+ 0x4CDD2086L, 0x8470EB26L, 0x6382E9C6L, 0x021ECC5EL,
+ 0x09686B3FL, 0x3EBAEFC9L, 0x3C971814L, 0x6B6A70A1L,
+ 0x687F3584L, 0x52A0E286L, 0xB79C5305L, 0xAA500737L,
+ 0x3E07841CL, 0x7FDEAE5CL, 0x8E7D44ECL, 0x5716F2B8L,
+ 0xB03ADA37L, 0xF0500C0DL, 0xF01C1F04L, 0x0200B3FFL,
+ 0xAE0CF51AL, 0x3CB574B2L, 0x25837A58L, 0xDC0921BDL,
+ 0xD19113F9L, 0x7CA92FF6L, 0x94324773L, 0x22F54701L,
+ 0x3AE5E581L, 0x37C2DADCL, 0xC8B57634L, 0x9AF3DDA7L,
+ 0xA9446146L, 0x0FD0030EL, 0xECC8C73EL, 0xA4751E41L,
+ 0xE238CD99L, 0x3BEA0E2FL, 0x3280BBA1L, 0x183EB331L,
+ 0x4E548B38L, 0x4F6DB908L, 0x6F420D03L, 0xF60A04BFL,
+ 0x2CB81290L, 0x24977C79L, 0x5679B072L, 0xBCAF89AFL,
+ 0xDE9A771FL, 0xD9930810L, 0xB38BAE12L, 0xDCCF3F2EL,
+ 0x5512721FL, 0x2E6B7124L, 0x501ADDE6L, 0x9F84CD87L,
+ 0x7A584718L, 0x7408DA17L, 0xBC9F9ABCL, 0xE94B7D8CL,
+ 0xEC7AEC3AL, 0xDB851DFAL, 0x63094366L, 0xC464C3D2L,
+ 0xEF1C1847L, 0x3215D908L, 0xDD433B37L, 0x24C2BA16L,
+ 0x12A14D43L, 0x2A65C451L, 0x50940002L, 0x133AE4DDL,
+ 0x71DFF89EL, 0x10314E55L, 0x81AC77D6L, 0x5F11199BL,
+ 0x043556F1L, 0xD7A3C76BL, 0x3C11183BL, 0x5924A509L,
+ 0xF28FE6EDL, 0x97F1FBFAL, 0x9EBABF2CL, 0x1E153C6EL,
+ 0x86E34570L, 0xEAE96FB1L, 0x860E5E0AL, 0x5A3E2AB3L,
+ 0x771FE71CL, 0x4E3D06FAL, 0x2965DCB9L, 0x99E71D0FL,
+ 0x803E89D6L, 0x5266C825L, 0x2E4CC978L, 0x9C10B36AL,
+ 0xC6150EBAL, 0x94E2EA78L, 0xA5FC3C53L, 0x1E0A2DF4L,
+ 0xF2F74EA7L, 0x361D2B3DL, 0x1939260FL, 0x19C27960L,
+ 0x5223A708L, 0xF71312B6L, 0xEBADFE6EL, 0xEAC31F66L,
+ 0xE3BC4595L, 0xA67BC883L, 0xB17F37D1L, 0x018CFF28L,
+ 0xC332DDEFL, 0xBE6C5AA5L, 0x65582185L, 0x68AB9802L,
+ 0xEECEA50FL, 0xDB2F953BL, 0x2AEF7DADL, 0x5B6E2F84L,
+ 0x1521B628L, 0x29076170L, 0xECDD4775L, 0x619F1510L,
+ 0x13CCA830L, 0xEB61BD96L, 0x0334FE1EL, 0xAA0363CFL,
+ 0xB5735C90L, 0x4C70A239L, 0xD59E9E0BL, 0xCBAADE14L,
+ 0xEECC86BCL, 0x60622CA7L, 0x9CAB5CABL, 0xB2F3846EL,
+ 0x648B1EAFL, 0x19BDF0CAL, 0xA02369B9L, 0x655ABB50L,
+ 0x40685A32L, 0x3C2AB4B3L, 0x319EE9D5L, 0xC021B8F7L,
+ 0x9B540B19L, 0x875FA099L, 0x95F7997EL, 0x623D7DA8L,
+ 0xF837889AL, 0x97E32D77L, 0x11ED935FL, 0x16681281L,
+ 0x0E358829L, 0xC7E61FD6L, 0x96DEDFA1L, 0x7858BA99L,
+ 0x57F584A5L, 0x1B227263L, 0x9B83C3FFL, 0x1AC24696L,
+ 0xCDB30AEBL, 0x532E3054L, 0x8FD948E4L, 0x6DBC3128L,
+ 0x58EBF2EFL, 0x34C6FFEAL, 0xFE28ED61L, 0xEE7C3C73L,
+ 0x5D4A14D9L, 0xE864B7E3L, 0x42105D14L, 0x203E13E0L,
+ 0x45EEE2B6L, 0xA3AAABEAL, 0xDB6C4F15L, 0xFACB4FD0L,
+ 0xC742F442L, 0xEF6ABBB5L, 0x654F3B1DL, 0x41CD2105L,
+ 0xD81E799EL, 0x86854DC7L, 0xE44B476AL, 0x3D816250L,
+ 0xCF62A1F2L, 0x5B8D2646L, 0xFC8883A0L, 0xC1C7B6A3L,
+ 0x7F1524C3L, 0x69CB7492L, 0x47848A0BL, 0x5692B285L,
+ 0x095BBF00L, 0xAD19489DL, 0x1462B174L, 0x23820E00L,
+ 0x58428D2AL, 0x0C55F5EAL, 0x1DADF43EL, 0x233F7061L,
+ 0x3372F092L, 0x8D937E41L, 0xD65FECF1L, 0x6C223BDBL,
+ 0x7CDE3759L, 0xCBEE7460L, 0x4085F2A7L, 0xCE77326EL,
+ 0xA6078084L, 0x19F8509EL, 0xE8EFD855L, 0x61D99735L,
+ 0xA969A7AAL, 0xC50C06C2L, 0x5A04ABFCL, 0x800BCADCL,
+ 0x9E447A2EL, 0xC3453484L, 0xFDD56705L, 0x0E1E9EC9L,
+ 0xDB73DBD3L, 0x105588CDL, 0x675FDA79L, 0xE3674340L,
+ 0xC5C43465L, 0x713E38D8L, 0x3D28F89EL, 0xF16DFF20L,
+ 0x153E21E7L, 0x8FB03D4AL, 0xE6E39F2BL, 0xDB83ADF7L},
+
+{ 0xE93D5A68L, 0x948140F7L, 0xF64C261CL, 0x94692934L,
+ 0x411520F7L, 0x7602D4F7L, 0xBCF46B2EL, 0xD4A20068L,
+ 0xD4082471L, 0x3320F46AL, 0x43B7D4B7L, 0x500061AFL,
+ 0x1E39F62EL, 0x97244546L, 0x14214F74L, 0xBF8B8840L,
+ 0x4D95FC1DL, 0x96B591AFL, 0x70F4DDD3L, 0x66A02F45L,
+ 0xBFBC09ECL, 0x03BD9785L, 0x7FAC6DD0L, 0x31CB8504L,
+ 0x96EB27B3L, 0x55FD3941L, 0xDA2547E6L, 0xABCA0A9AL,
+ 0x28507825L, 0x530429F4L, 0x0A2C86DAL, 0xE9B66DFBL,
+ 0x68DC1462L, 0xD7486900L, 0x680EC0A4L, 0x27A18DEEL,
+ 0x4F3FFEA2L, 0xE887AD8CL, 0xB58CE006L, 0x7AF4D6B6L,
+ 0xAACE1E7CL, 0xD3375FECL, 0xCE78A399L, 0x406B2A42L,
+ 0x20FE9E35L, 0xD9F385B9L, 0xEE39D7ABL, 0x3B124E8BL,
+ 0x1DC9FAF7L, 0x4B6D1856L, 0x26A36631L, 0xEAE397B2L,
+ 0x3A6EFA74L, 0xDD5B4332L, 0x6841E7F7L, 0xCA7820FBL,
+ 0xFB0AF54EL, 0xD8FEB397L, 0x454056ACL, 0xBA489527L,
+ 0x55533A3AL, 0x20838D87L, 0xFE6BA9B7L, 0xD096954BL,
+ 0x55A867BCL, 0xA1159A58L, 0xCCA92963L, 0x99E1DB33L,
+ 0xA62A4A56L, 0x3F3125F9L, 0x5EF47E1CL, 0x9029317CL,
+ 0xFDF8E802L, 0x04272F70L, 0x80BB155CL, 0x05282CE3L,
+ 0x95C11548L, 0xE4C66D22L, 0x48C1133FL, 0xC70F86DCL,
+ 0x07F9C9EEL, 0x41041F0FL, 0x404779A4L, 0x5D886E17L,
+ 0x325F51EBL, 0xD59BC0D1L, 0xF2BCC18FL, 0x41113564L,
+ 0x257B7834L, 0x602A9C60L, 0xDFF8E8A3L, 0x1F636C1BL,
+ 0x0E12B4C2L, 0x02E1329EL, 0xAF664FD1L, 0xCAD18115L,
+ 0x6B2395E0L, 0x333E92E1L, 0x3B240B62L, 0xEEBEB922L,
+ 0x85B2A20EL, 0xE6BA0D99L, 0xDE720C8CL, 0x2DA2F728L,
+ 0xD0127845L, 0x95B794FDL, 0x647D0862L, 0xE7CCF5F0L,
+ 0x5449A36FL, 0x877D48FAL, 0xC39DFD27L, 0xF33E8D1EL,
+ 0x0A476341L, 0x992EFF74L, 0x3A6F6EABL, 0xF4F8FD37L,
+ 0xA812DC60L, 0xA1EBDDF8L, 0x991BE14CL, 0xDB6E6B0DL,
+ 0xC67B5510L, 0x6D672C37L, 0x2765D43BL, 0xDCD0E804L,
+ 0xF1290DC7L, 0xCC00FFA3L, 0xB5390F92L, 0x690FED0BL,
+ 0x667B9FFBL, 0xCEDB7D9CL, 0xA091CF0BL, 0xD9155EA3L,
+ 0xBB132F88L, 0x515BAD24L, 0x7B9479BFL, 0x763BD6EBL,
+ 0x37392EB3L, 0xCC115979L, 0x8026E297L, 0xF42E312DL,
+ 0x6842ADA7L, 0xC66A2B3BL, 0x12754CCCL, 0x782EF11CL,
+ 0x6A124237L, 0xB79251E7L, 0x06A1BBE6L, 0x4BFB6350L,
+ 0x1A6B1018L, 0x11CAEDFAL, 0x3D25BDD8L, 0xE2E1C3C9L,
+ 0x44421659L, 0x0A121386L, 0xD90CEC6EL, 0xD5ABEA2AL,
+ 0x64AF674EL, 0xDA86A85FL, 0xBEBFE988L, 0x64E4C3FEL,
+ 0x9DBC8057L, 0xF0F7C086L, 0x60787BF8L, 0x6003604DL,
+ 0xD1FD8346L, 0xF6381FB0L, 0x7745AE04L, 0xD736FCCCL,
+ 0x83426B33L, 0xF01EAB71L, 0xB0804187L, 0x3C005E5FL,
+ 0x77A057BEL, 0xBDE8AE24L, 0x55464299L, 0xBF582E61L,
+ 0x4E58F48FL, 0xF2DDFDA2L, 0xF474EF38L, 0x8789BDC2L,
+ 0x5366F9C3L, 0xC8B38E74L, 0xB475F255L, 0x46FCD9B9L,
+ 0x7AEB2661L, 0x8B1DDF84L, 0x846A0E79L, 0x915F95E2L,
+ 0x466E598EL, 0x20B45770L, 0x8CD55591L, 0xC902DE4CL,
+ 0xB90BACE1L, 0xBB8205D0L, 0x11A86248L, 0x7574A99EL,
+ 0xB77F19B6L, 0xE0A9DC09L, 0x662D09A1L, 0xC4324633L,
+ 0xE85A1F02L, 0x09F0BE8CL, 0x4A99A025L, 0x1D6EFE10L,
+ 0x1AB93D1DL, 0x0BA5A4DFL, 0xA186F20FL, 0x2868F169L,
+ 0xDCB7DA83L, 0x573906FEL, 0xA1E2CE9BL, 0x4FCD7F52L,
+ 0x50115E01L, 0xA70683FAL, 0xA002B5C4L, 0x0DE6D027L,
+ 0x9AF88C27L, 0x773F8641L, 0xC3604C06L, 0x61A806B5L,
+ 0xF0177A28L, 0xC0F586E0L, 0x006058AAL, 0x30DC7D62L,
+ 0x11E69ED7L, 0x2338EA63L, 0x53C2DD94L, 0xC2C21634L,
+ 0xBBCBEE56L, 0x90BCB6DEL, 0xEBFC7DA1L, 0xCE591D76L,
+ 0x6F05E409L, 0x4B7C0188L, 0x39720A3DL, 0x7C927C24L,
+ 0x86E3725FL, 0x724D9DB9L, 0x1AC15BB4L, 0xD39EB8FCL,
+ 0xED545578L, 0x08FCA5B5L, 0xD83D7CD3L, 0x4DAD0FC4L,
+ 0x1E50EF5EL, 0xB161E6F8L, 0xA28514D9L, 0x6C51133CL,
+ 0x6FD5C7E7L, 0x56E14EC4L, 0x362ABFCEL, 0xDDC6C837L,
+ 0xD79A3234L, 0x92638212L, 0x670EFA8EL, 0x406000E0L},
+
+{ 0x3A39CE37L, 0xD3FAF5CFL, 0xABC27737L, 0x5AC52D1BL,
+ 0x5CB0679EL, 0x4FA33742L, 0xD3822740L, 0x99BC9BBEL,
+ 0xD5118E9DL, 0xBF0F7315L, 0xD62D1C7EL, 0xC700C47BL,
+ 0xB78C1B6BL, 0x21A19045L, 0xB26EB1BEL, 0x6A366EB4L,
+ 0x5748AB2FL, 0xBC946E79L, 0xC6A376D2L, 0x6549C2C8L,
+ 0x530FF8EEL, 0x468DDE7DL, 0xD5730A1DL, 0x4CD04DC6L,
+ 0x2939BBDBL, 0xA9BA4650L, 0xAC9526E8L, 0xBE5EE304L,
+ 0xA1FAD5F0L, 0x6A2D519AL, 0x63EF8CE2L, 0x9A86EE22L,
+ 0xC089C2B8L, 0x43242EF6L, 0xA51E03AAL, 0x9CF2D0A4L,
+ 0x83C061BAL, 0x9BE96A4DL, 0x8FE51550L, 0xBA645BD6L,
+ 0x2826A2F9L, 0xA73A3AE1L, 0x4BA99586L, 0xEF5562E9L,
+ 0xC72FEFD3L, 0xF752F7DAL, 0x3F046F69L, 0x77FA0A59L,
+ 0x80E4A915L, 0x87B08601L, 0x9B09E6ADL, 0x3B3EE593L,
+ 0xE990FD5AL, 0x9E34D797L, 0x2CF0B7D9L, 0x022B8B51L,
+ 0x96D5AC3AL, 0x017DA67DL, 0xD1CF3ED6L, 0x7C7D2D28L,
+ 0x1F9F25CFL, 0xADF2B89BL, 0x5AD6B472L, 0x5A88F54CL,
+ 0xE029AC71L, 0xE019A5E6L, 0x47B0ACFDL, 0xED93FA9BL,
+ 0xE8D3C48DL, 0x283B57CCL, 0xF8D56629L, 0x79132E28L,
+ 0x785F0191L, 0xED756055L, 0xF7960E44L, 0xE3D35E8CL,
+ 0x15056DD4L, 0x88F46DBAL, 0x03A16125L, 0x0564F0BDL,
+ 0xC3EB9E15L, 0x3C9057A2L, 0x97271AECL, 0xA93A072AL,
+ 0x1B3F6D9BL, 0x1E6321F5L, 0xF59C66FBL, 0x26DCF319L,
+ 0x7533D928L, 0xB155FDF5L, 0x03563482L, 0x8ABA3CBBL,
+ 0x28517711L, 0xC20AD9F8L, 0xABCC5167L, 0xCCAD925FL,
+ 0x4DE81751L, 0x3830DC8EL, 0x379D5862L, 0x9320F991L,
+ 0xEA7A90C2L, 0xFB3E7BCEL, 0x5121CE64L, 0x774FBE32L,
+ 0xA8B6E37EL, 0xC3293D46L, 0x48DE5369L, 0x6413E680L,
+ 0xA2AE0810L, 0xDD6DB224L, 0x69852DFDL, 0x09072166L,
+ 0xB39A460AL, 0x6445C0DDL, 0x586CDECFL, 0x1C20C8AEL,
+ 0x5BBEF7DDL, 0x1B588D40L, 0xCCD2017FL, 0x6BB4E3BBL,
+ 0xDDA26A7EL, 0x3A59FF45L, 0x3E350A44L, 0xBCB4CDD5L,
+ 0x72EACEA8L, 0xFA6484BBL, 0x8D6612AEL, 0xBF3C6F47L,
+ 0xD29BE463L, 0x542F5D9EL, 0xAEC2771BL, 0xF64E6370L,
+ 0x740E0D8DL, 0xE75B1357L, 0xF8721671L, 0xAF537D5DL,
+ 0x4040CB08L, 0x4EB4E2CCL, 0x34D2466AL, 0x0115AF84L,
+ 0xE1B00428L, 0x95983A1DL, 0x06B89FB4L, 0xCE6EA048L,
+ 0x6F3F3B82L, 0x3520AB82L, 0x011A1D4BL, 0x277227F8L,
+ 0x611560B1L, 0xE7933FDCL, 0xBB3A792BL, 0x344525BDL,
+ 0xA08839E1L, 0x51CE794BL, 0x2F32C9B7L, 0xA01FBAC9L,
+ 0xE01CC87EL, 0xBCC7D1F6L, 0xCF0111C3L, 0xA1E8AAC7L,
+ 0x1A908749L, 0xD44FBD9AL, 0xD0DADECBL, 0xD50ADA38L,
+ 0x0339C32AL, 0xC6913667L, 0x8DF9317CL, 0xE0B12B4FL,
+ 0xF79E59B7L, 0x43F5BB3AL, 0xF2D519FFL, 0x27D9459CL,
+ 0xBF97222CL, 0x15E6FC2AL, 0x0F91FC71L, 0x9B941525L,
+ 0xFAE59361L, 0xCEB69CEBL, 0xC2A86459L, 0x12BAA8D1L,
+ 0xB6C1075EL, 0xE3056A0CL, 0x10D25065L, 0xCB03A442L,
+ 0xE0EC6E0EL, 0x1698DB3BL, 0x4C98A0BEL, 0x3278E964L,
+ 0x9F1F9532L, 0xE0D392DFL, 0xD3A0342BL, 0x8971F21EL,
+ 0x1B0A7441L, 0x4BA3348CL, 0xC5BE7120L, 0xC37632D8L,
+ 0xDF359F8DL, 0x9B992F2EL, 0xE60B6F47L, 0x0FE3F11DL,
+ 0xE54CDA54L, 0x1EDAD891L, 0xCE6279CFL, 0xCD3E7E6FL,
+ 0x1618B166L, 0xFD2C1D05L, 0x848FD2C5L, 0xF6FB2299L,
+ 0xF523F357L, 0xA6327623L, 0x93A83531L, 0x56CCCD02L,
+ 0xACF08162L, 0x5A75EBB5L, 0x6E163697L, 0x88D273CCL,
+ 0xDE966292L, 0x81B949D0L, 0x4C50901BL, 0x71C65614L,
+ 0xE6C6C7BDL, 0x327A140AL, 0x45E1D006L, 0xC3F27B9AL,
+ 0xC9AA53FDL, 0x62A80F00L, 0xBB25BFE2L, 0x35BDD2F6L,
+ 0x71126905L, 0xB2040222L, 0xB6CBCF7CL, 0xCD769C2BL,
+ 0x53113EC0L, 0x1640E3D3L, 0x38ABBD60L, 0x2547ADF0L,
+ 0xBA38209CL, 0xF746CE76L, 0x77AFA1C5L, 0x20756060L,
+ 0x85CBFE4EL, 0x8AE88DD8L, 0x7AAAF9B0L, 0x4CF9AA7EL,
+ 0x1948C25CL, 0x02FB8A8CL, 0x01C36AE4L, 0xD6EBE1F9L,
+ 0x90D4F869L, 0xA65CDEA0L, 0x3F09252DL, 0xC208E69FL,
+ 0xB74E6132L, 0xCE77E25BL, 0x578FDFE3L, 0x3AC372E6L}
+};
+//-----------------------------------------------------------------------------
+uint32_t F(BLOWFISH_CTX *ctx, uint32_t x)
+{
+unsigned short a, b, c, d;
+uint32_t y = 0;
+//uint32_t y1, y2;
+
+d = x & 0x00FF;
+x >>= 8;
+c = x & 0x00FF;
+x >>= 8;
+b = x & 0x00FF;
+x >>= 8;
+a = x & 0x00FF;
+
+/*y1 = ctx->S[0][a];
+y2 = ctx->S[1][b];
+y = y1+y2;*/
+
+y = ctx->S[0][a] + ctx->S[1][b];
+y = y ^ ctx->S[2][c];
+y = y + ctx->S[3][d];
+return y;
+}
+//-----------------------------------------------------------------------------
+void Blowfish_Encrypt(BLOWFISH_CTX *ctx, uint32_t *xl, uint32_t *xr)
+{
+uint32_t Xl;
+uint32_t Xr;
+uint32_t temp;
+short i;
+
+Xl = *xl;
+Xr = *xr;
+
+for (i = 0; i < N; ++i)
+ {
+ Xl = Xl ^ ctx->P[i];
+ Xr = F(ctx, Xl) ^ Xr;
+ temp = Xl;
+ Xl = Xr;
+ Xr = temp;
+ }
+
+temp = Xl;
+Xl = Xr;
+Xr = temp;
+Xr = Xr ^ ctx->P[N];
+Xl = Xl ^ ctx->P[N + 1];
+*xl = Xl;
+*xr = Xr;
+}
+//-----------------------------------------------------------------------------
+void Blowfish_Decrypt(BLOWFISH_CTX *ctx, uint32_t *xl, uint32_t *xr)
+{
+uint32_t Xl;
+uint32_t Xr;
+uint32_t temp;
+short i;
+
+Xl = *xl;
+Xr = *xr;
+
+for (i = N + 1; i > 1; --i)
+ {
+ Xl = Xl ^ ctx->P[i];
+ Xr = F(ctx, Xl) ^ Xr;
+ /* Exchange Xl and Xr */
+ temp = Xl;
+ Xl = Xr;
+ Xr = temp;
+ }
+
+/* Exchange Xl and Xr */
+temp = Xl;
+Xl = Xr;
+Xr = temp;
+Xr = Xr ^ ctx->P[1];
+Xl = Xl ^ ctx->P[0];
+*xl = Xl;
+*xr = Xr;
+}
+//-----------------------------------------------------------------------------
+void Blowfish_Init(BLOWFISH_CTX *ctx, unsigned char *key, int keyLen)
+{
+int i, j, k;
+uint32_t data, datal, datar;
+
+memset(ctx->S, 0, sizeof(ctx->S));
+
+for (i = 0; i < 4; i++)
+ {
+
+ for (j = 0; j < 256; j++)
+ ctx->S[i][j] = ORIG_S[i][j];
+ }
+
+j = 0;
+
+for (i = 0; i < N + 2; ++i)
+ {
+ data = 0x00000000;
+
+ for (k = 0; k < 4; ++k)
+ {
+ data = (data << 8) | key[j];
+ j = j + 1;
+ if (j >= keyLen)
+ j = 0;
+ }
+
+ ctx->P[i] = ORIG_P[i] ^ data;
+ }
+
+datal = 0x00000000;
+datar = 0x00000000;
+
+for (i = 0; i < N + 2; i += 2)
+ {
+ Blowfish_Encrypt(ctx, &datal, &datar);
+ ctx->P[i] = datal;
+ ctx->P[i + 1] = datar;
+ }
+
+for (i = 0; i < 4; ++i)
+ {
+
+ for (j = 0; j < 256; j += 2)
+ {
+ Blowfish_Encrypt(ctx, &datal, &datar);
+ ctx->S[i][j] = datal;
+ ctx->S[i][j + 1] = datar;
+ }
+ }
+}
+//-----------------------------------------------------------------------------
+void EnDecodeInit(const char * passwd, int, BLOWFISH_CTX *ctx)
+{
+unsigned char * keyL = NULL;//[PASSWD_LEN]; // ðÁÒÏÌØ ÄÌÑ ÛÉÆÒÏ×ËÉ
+
+keyL = new unsigned char[PASSWD_LEN];
+
+memset(keyL, 0, PASSWD_LEN);
+
+strncpy((char *)keyL, passwd, PASSWD_LEN);
+
+Blowfish_Init(ctx, keyL, PASSWD_LEN);
+
+delete[] keyL;
+}
+//-----------------------------------------------------------------------------
+// Note: swap bytes order for compatibility with OpenSSL
+uint32_t bytes2block(const char * c)
+{
+ uint32_t t = static_cast<unsigned char>(*c++);
+ t += static_cast<unsigned char>(*c++) << 8;
+ t += static_cast<unsigned char>(*c++) << 16;
+ t += static_cast<unsigned char>(*c) << 24;
+ return t;
+}
+//-----------------------------------------------------------------------------
+// Note: swap bytes order for compatibility with OpenSSL
+void block2bytes(uint32_t t, char * c)
+{
+ *c++ = t & 0x000000FF;
+ *c++ = t >> 8 & 0x000000FF;
+ *c++ = t >> 16 & 0x000000FF;
+ *c = t >> 24 & 0x000000FF;
+}
+//-----------------------------------------------------------------------------
+void DecodeString(char * d, const char * s, BLOWFISH_CTX *ctx)
+{
+uint32_t a = bytes2block(s);
+uint32_t b = bytes2block(s + 4);
+
+Blowfish_Decrypt(ctx, &a, &b);
+
+block2bytes(a, d);
+block2bytes(b, d + 4);
+}
+//-----------------------------------------------------------------------------
+void EncodeString(char * d, const char * s, BLOWFISH_CTX *ctx)
+{
+uint32_t a = bytes2block(s);
+uint32_t b = bytes2block(s + 4);
+
+Blowfish_Encrypt(ctx, &a, &b);
+
+block2bytes(a, d);
+block2bytes(b, d + 4);
+}
+//-----------------------------------------------------------------------------
--- /dev/null
+/*
+ * Author : Paul Kocher
+ * E-mail : pck@netcom.com
+ * Date : 1997
+ * Description: C implementation of the Blowfish algorithm.
+ */
+
+#ifndef BLOWFISH_H
+#define BLOWFISH_H
+
+#include "os_int.h"
+
+#define MAXKEYBYTES 56 /* 448 bits */
+
+typedef struct {
+ uint32_t P[16 + 2];
+ uint32_t S[4][256];
+} BLOWFISH_CTX;
+
+void Blowfish_Init(BLOWFISH_CTX *ctx, unsigned char *key, int keyLen);
+void Blowfish_Encrypt(BLOWFISH_CTX *ctx, uint32_t *xl, uint32_t *xr);
+void Blowfish_Decrypt(BLOWFISH_CTX *ctx, uint32_t *xl, uint32_t *xr);
+
+void EnDecodeInit(const char * key, int passwdLen, BLOWFISH_CTX *ctx);
+void DecodeString(char * d, const char * s, BLOWFISH_CTX *ctx);
+void EncodeString(char * d, const char * s, BLOWFISH_CTX *ctx);
+
+#endif
+
--- /dev/null
+//---------------------------------------------------------------------------\r
+\r
+#include <vcl.h>\r
+#pragma hdrstop\r
+#define Library\r
+\r
+// To add a file to the library use the Project menu 'Add to Project'.\r
+\r
+
\ No newline at end of file
--- /dev/null
+<?xml version='1.0' encoding='utf-8' ?>\r
+<!-- C++Builder XML Project -->\r
+<PROJECT>\r
+ <MACROS>\r
+ <VERSION value="BCB.06.00"/>\r
+ <PROJECT value="..\..\lib\crypto.lib"/>\r
+ <OBJFILES value="obj\ag_md5.obj obj\blowfish.obj"/>\r
+ <RESFILES value=""/>\r
+ <IDLFILES value=""/>\r
+ <IDLGENFILES value=""/>\r
+ <DEFFILE value=""/>\r
+ <RESDEPEN value="$(RESFILES)"/>\r
+ <LIBFILES value=""/>\r
+ <LIBRARIES value=""/>\r
+ <PACKAGES value=""/>\r
+ <PATHCPP value=".;"/>\r
+ <PATHPAS value=".;"/>\r
+ <PATHRC value=".;"/>\r
+ <PATHASM value=".;"/>\r
+ <LINKER value="TLib"/>\r
+ <USERDEFINES value="_DEBUG;WIN32"/>\r
+ <SYSDEFINES value="_RTLDLL;NO_STRICT"/>\r
+ <MAINSOURCE value="crypto.bpf"/>\r
+ <INCLUDEPATH value="$(BCB)\include;$(BCB)\include\vcl;..\..\include"/>\r
+ <LIBPATH value="$(BCB)\lib\obj;$(BCB)\lib"/>\r
+ <WARNINGS value="-w-par"/>\r
+ <LISTFILE value=""/>\r
+ <OTHERFILES value=""/>\r
+ </MACROS>\r
+ <OPTIONS>\r
+ <IDLCFLAGS value="-I$(BCB)\include -I$(BCB)\include\vcl -I..\..\include -src_suffix cpp \r
+ -D_DEBUG -DWIN32 -boa"/>\r
+ <CFLAG1 value="-Od -H=$(BCB)\lib\vcl60.csm -Hc -Vx -Ve -X- -r- -a8 -b- -k -y -v -vi- -c \r
+ -tW -tWM"/>\r
+ <PFLAGS value="-N2obj -N0obj -$YD -$W -$O- -$A8 -v -JPHNE -M"/>\r
+ <AFLAGS value="/mx /w2 /zd"/>\r
+ <LFLAGS value=""/>\r
+ <OTHERFILES value=""/>\r
+ </OPTIONS>\r
+ <LINKER>\r
+ <ALLOBJ value="$(OBJFILES)"/>\r
+ <ALLLIB value=""/>\r
+ <OTHERFILES value=""/>\r
+ </LINKER>\r
+ <FILELIST>\r
+ <FILE FILENAME="crypto.bpf" FORMNAME="" UNITNAME="crypto" CONTAINERID="BPF" DESIGNCLASS="" LOCALCOMMAND=""/>\r
+ <FILE FILENAME="blowfish.h" FORMNAME="" UNITNAME="blowfish.h" CONTAINERID="" DESIGNCLASS="" LOCALCOMMAND=""/>\r
+ <FILE FILENAME="ag_md5.c" FORMNAME="" UNITNAME="ag_md5.c" CONTAINERID="CCompiler" DESIGNCLASS="" LOCALCOMMAND=""/>\r
+ <FILE FILENAME="ag_md5.h" FORMNAME="" UNITNAME="ag_md5.h" CONTAINERID="" DESIGNCLASS="" LOCALCOMMAND=""/>\r
+ <FILE FILENAME="blowfish.cpp" FORMNAME="" UNITNAME="blowfish.cpp" CONTAINERID="CCompiler" DESIGNCLASS="" LOCALCOMMAND=""/>\r
+ </FILELIST>\r
+ <BUILDTOOLS>\r
+ </BUILDTOOLS>\r
+\r
+ <IDEOPTIONS>\r
+[Version Info]\r
+IncludeVerInfo=0\r
+AutoIncBuild=0\r
+MajorVer=1\r
+MinorVer=0\r
+Release=0\r
+Build=0\r
+Debug=0\r
+PreRelease=0\r
+Special=0\r
+Private=0\r
+DLL=0\r
+Locale=1058\r
+CodePage=1251\r
+\r
+[Version Info Keys]\r
+CompanyName=\r
+FileDescription=\r
+FileVersion=1.0.0.0\r
+InternalName=\r
+LegalCopyright=\r
+LegalTrademarks=\r
+OriginalFilename=\r
+ProductName=\r
+ProductVersion=1.0.0.0\r
+Comments=\r
+\r
+[HistoryLists\hlIncludePath]\r
+Count=2\r
+Item0=$(BCB)\include;$(BCB)\include\vcl;..\..\include\r
+Item1=$(BCB)\include;$(BCB)\include\vcl\r
+\r
+[HistoryLists\hlLibraryPath]\r
+Count=1\r
+Item0=$(BCB)\lib\obj;$(BCB)\lib\r
+\r
+[HistoryLists\hlDebugSourcePath]\r
+Count=1\r
+Item0=$(BCB)\source\vcl\r
+\r
+[HistoryLists\hlConditionals]\r
+Count=2\r
+Item0=_DEBUG;WIN32\r
+Item1=_DEBUG\r
+\r
+[HistoryLists\hlIntOutputDir]\r
+Count=1\r
+Item0=obj\r
+\r
+[HistoryLists\hlFinalOutputDir]\r
+Count=2\r
+Item0=..\..\lib\\r
+Item1=..\..\lib\r
+\r
+[HistoryLists\hlTlibPageSize]\r
+Count=1\r
+Item0=0x0010\r
+\r
+[Debugging]\r
+DebugSourceDirs=$(BCB)\source\vcl\r
+\r
+[Parameters]\r
+RunParams=\r
+Launcher=\r
+UseLauncher=0\r
+DebugCWD=\r
+HostApplication=\r
+RemoteHost=\r
+RemotePath=\r
+RemoteLauncher=\r
+RemoteCWD=\r
+RemoteDebug=0\r
+\r
+[Compiler]\r
+ShowInfoMsgs=0\r
+LinkDebugVcl=0\r
+LinkCGLIB=0\r
+\r
+[CORBA]\r
+AddServerUnit=1\r
+AddClientUnit=1\r
+PrecompiledHeaders=1\r
+\r
+[Language]\r
+ActiveLang=\r
+ProjectLang=\r
+RootDir=\r
+ </IDEOPTIONS>\r
+</PROJECT>
\ No newline at end of file
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.3 2007/05/08 14:29:19 faust Exp $
+###############################################################################
+
+LIB_NAME = dotconfpp
+PROG = lib$(LIB_NAME)
+
+SRCS = dotconfpp.cpp \
+ mempool.cpp
+
+INCS = dotconfpp.h \
+ mempool.h
+
+include ../Makefile.in
--- /dev/null
+/* Copyright (C) 2003 Aleksey Krivoshey <krivoshey@users.sourceforge.net>
+*
+* 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
+*/
+
+#include <libgen.h> // dirname
+#include <glob.h> // glob
+#include <string>
+
+#include "dotconfpp.h"
+
+DOTCONFDocumentNode::DOTCONFDocumentNode():previousNode(NULL), nextNode(NULL), parentNode(NULL), childNode(NULL),
+ values(NULL), valuesCount(0),
+ name(NULL), lineNum(0), fileName(NULL), closed(true)
+{
+}
+
+DOTCONFDocumentNode::~DOTCONFDocumentNode()
+{
+ free(name);
+ if(values != NULL){
+ for(int i = 0 ; i < valuesCount; i++){
+ free(values[i]);
+ }
+ free(values);
+ }
+}
+
+void DOTCONFDocumentNode::pushValue(char * _value)
+{
+ valuesCount++;
+ values = (char**)realloc(values, valuesCount*sizeof(char*));
+ values[valuesCount-1] = strdup(_value);
+}
+
+const char* DOTCONFDocumentNode::getValue(int index) const
+{
+ if(index >= valuesCount){
+ return NULL;
+ }
+ return values[index];
+}
+
+DOTCONFDocument::DOTCONFDocument(DOTCONFDocument::CaseSensitive caseSensitivity):
+ mempool(NULL),
+ curParent(NULL), curPrev(NULL), errorCallback(NULL), errorCallbackData(NULL),
+ curLine(0), file(NULL), fileName(NULL)
+{
+ if(caseSensitivity == CASESENSITIVE){
+ cmp_func = strcmp;
+ } else {
+ cmp_func = strcasecmp;
+ }
+
+ mempool = new AsyncDNSMemPool(1024);
+ mempool->initialize();
+}
+
+DOTCONFDocument::~DOTCONFDocument()
+{
+ for(std::list<DOTCONFDocumentNode*>::iterator i = nodeTree.begin(); i != nodeTree.end(); i++){
+ delete(*i);
+ }
+ for(std::list<char*>::iterator i = requiredOptions.begin(); i != requiredOptions.end(); i++){
+ free(*i);
+ }
+ for(std::list<char*>::iterator i = processedFiles.begin(); i != processedFiles.end(); i++){
+ free(*i);
+ }
+ free(fileName);
+ delete mempool;
+}
+
+int DOTCONFDocument::cleanupLine(char * line)
+{
+ char * start = line;
+ char * bg = line;
+ bool multiline = false;
+ bool concat = false;
+ char * word = NULL;
+
+ if(!words.empty() && quoted)
+ concat = true;
+
+ while(*line){
+ if((*line == '#' || *line == ';') && !quoted){
+ *bg = 0;
+ if(strlen(start)){
+ //printf("2start='%s'\n", start);
+ if(concat){
+ word = (char*)mempool->alloc(strlen(words.back())+strlen(start)+1);
+ strcpy(word, words.back());
+ strcat(word, start);
+ words.pop_back();
+ concat = false;
+ } else {
+ word = mempool->strdup(start);
+ }
+ words.push_back(word);
+ }
+ break;
+ }
+ if(*line == '=' && !quoted){ // 'parameter = value' is the same as 'parameter value' but do not replace with ' ' when used in quoted value
+ *line = ' ';continue;
+ }
+ if(*line == '\\' && (*(line+1) == '"' || *(line+1) == '\'')){
+ *bg++ = *(line+1);
+ line+=2; continue;
+ }
+ if(*line == '\\' && *(line+1) == 'n'){
+ *bg++ = '\n';
+ line+=2; continue;
+ }
+ if(*line == '\\' && *(line+1) == 'r'){
+ *bg++ = '\r';
+ line+=2; continue;
+ }
+ if(*line == '\\' && (*(line+1) == '\n' || *(line+1) == '\r')){ //multiline
+ *bg = 0;
+ if(strlen(start)){
+ //printf("3start='%s'\n", start);
+ if(concat){
+ word = (char*)mempool->alloc(strlen(words.back())+strlen(start)+1);
+ strcpy(word, words.back());
+ strcat(word, start);
+ words.pop_back();
+ concat = false;
+ } else {
+ word = mempool->strdup(start);
+ }
+ words.push_back(word);
+ }
+ multiline = true;
+ break;
+ }
+ if(*line == '"' || *line == '\''){ //need to handle quotes because of spaces or = that may be between
+ quoted = !quoted;
+ line++; continue;
+ }
+ if(isspace(*line) && !quoted){
+ *bg++ = 0;
+ if(strlen(start)){
+ //printf("start='%s'\n", start);
+ if(concat){
+ word = (char*)mempool->alloc(strlen(words.back())+strlen(start)+1);
+ strcpy(word, words.back());
+ strcat(word, start);
+ words.pop_back();
+ concat = false;
+ } else {
+ word = mempool->strdup(start);
+ }
+ words.push_back(word);
+ }
+ start = bg;
+ while(isspace(*++line)) {};
+ continue;
+ }
+ *bg++ = *line++;
+ }
+
+ if(quoted && !multiline){
+ error(curLine, fileName, "unterminated quote");
+ return -1;
+ }
+
+ return multiline?1:0;
+}
+
+int DOTCONFDocument::parseLine()
+{
+ char * word = NULL;
+ char * nodeName = NULL;
+ char * nodeValue = NULL;
+ DOTCONFDocumentNode * tagNode = NULL;
+ bool newNode = false;
+
+ for(std::list<char*>::iterator i = words.begin(); i != words.end(); i++) {
+ word = *i;
+
+ if(*word == '<'){
+ newNode = true;
+ }
+
+ if(newNode){
+ nodeValue = NULL;
+ nodeName = NULL;
+ newNode = false;
+ }
+
+ size_t wordLen = strlen(word);
+ if(word[wordLen-1] == '>'){
+ word[wordLen-1] = 0;
+ newNode = true;
+ }
+
+ if(nodeName == NULL){
+ nodeName = word;
+ bool closed = true; //if this not <> node then it is closed by default
+ if(*nodeName == '<'){
+ if(*(nodeName+1) != '/'){ //opening tag
+ nodeName++;
+ closed = false;
+ } else { //closing tag
+ nodeName+=2;
+ std::list<DOTCONFDocumentNode*>::reverse_iterator i=nodeTree.rbegin();
+ for(; i!=nodeTree.rend(); i++){
+ if(!cmp_func(nodeName, (*i)->name) && !(*i)->closed){
+ (*i)->closed = true;
+ curParent = (*i)->parentNode;
+ curPrev = *i;
+ break;
+ }
+ }
+ if(i==nodeTree.rend()){
+ error(curLine, fileName, "not matched closing tag </%s>", nodeName);
+ return -1;
+ }
+ continue;
+ }
+ }
+ tagNode = new DOTCONFDocumentNode;
+ tagNode->name = strdup(nodeName);
+ tagNode->document = this;
+ tagNode->fileName = processedFiles.back();
+ tagNode->lineNum = curLine;
+ tagNode->closed = closed;
+ if(!nodeTree.empty()){
+ DOTCONFDocumentNode * prev = nodeTree.back();
+ if(prev->closed){
+
+ curPrev->nextNode = tagNode;
+ tagNode->previousNode = curPrev;
+ tagNode->parentNode = curParent;
+
+ } else {
+ prev->childNode = tagNode;
+ tagNode->parentNode = prev;
+ curParent = prev;
+ }
+ }
+ nodeTree.push_back(tagNode);
+ curPrev = tagNode;
+ } else {
+ nodeValue = word;
+ tagNode->pushValue(nodeValue);
+ }
+ }
+
+ return 0;
+}
+int DOTCONFDocument::parseFile(DOTCONFDocumentNode * _parent)
+{
+ char str[512];
+ int ret = 0;
+ curLine = 0;
+ curParent = _parent;
+
+ quoted = false;
+ size_t slen = 0;
+
+ while(fgets(str, 511, file)){
+ curLine++;
+ slen = strlen(str);
+ if( slen >= 510 ){
+ error(curLine, fileName, "warning: line too long");
+ }
+ if(str[slen-1] != '\n'){
+ str[slen] = '\n';
+ str[slen+1] = 0;
+ }
+ if((ret = cleanupLine(str)) == -1){
+ break;
+ }
+ if(ret == 0){
+ if(!words.empty()){
+ ret = parseLine();
+ mempool->free();
+ words.clear();
+ if(ret == -1){
+ break;
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+int DOTCONFDocument::checkConfig(const std::list<DOTCONFDocumentNode*>::iterator & from)
+{
+ int ret = 0;
+
+ DOTCONFDocumentNode * tagNode = NULL;
+ int vi = 0;
+ for(std::list<DOTCONFDocumentNode*>::iterator i = from; i != nodeTree.end(); i++){
+ tagNode = *i;
+ if(!tagNode->closed){
+ error(tagNode->lineNum, tagNode->fileName, "unclosed tag %s", tagNode->name);
+ ret = -1;
+ break;
+ }
+ vi = 0;
+ while( vi < tagNode->valuesCount ){
+ //if((tagNode->values[vi])[0] == '$' && (tagNode->values[vi])[1] == '{' && strchr(tagNode->values[vi], '}') ){
+ if(strstr(tagNode->values[vi], "${") && strchr(tagNode->values[vi], '}') ){
+ ret = macroSubstitute(tagNode, vi );
+ mempool->free();
+ if(ret == -1){
+ break;
+ }
+ }
+ vi++;
+ }
+ if(ret == -1){
+ break;
+ }
+ }
+
+ return ret;
+}
+
+int DOTCONFDocument::setContent(const char * _fileName)
+{
+ int ret = 0;
+ char realpathBuf[PATH_MAX];
+
+ if(realpath(_fileName, realpathBuf) == NULL){
+ error(0, NULL, "realpath(%s) failed: %s", _fileName, strerror(errno));
+ return -1;
+ }
+
+ fileName = strdup(realpathBuf);
+
+ char * forPathName = strdup(realpathBuf);
+
+ if (forPathName == NULL) {
+ error(0, NULL, "Not enought memory to duplicate realpath");
+ return -1;
+ }
+
+ char * _pathName = dirname(forPathName);
+
+ std::string pathName(_pathName);
+
+ free(forPathName); // From strdup
+
+ processedFiles.push_back(strdup(realpathBuf));
+
+ if(( file = fopen(fileName, "r")) == NULL){
+ error(0, NULL, "failed to open file '%s': %s", fileName, strerror(errno));
+ return -1;
+ }
+
+ ret = parseFile();
+
+ (void) fclose(file);
+
+ if(!ret){
+
+ if( (ret = checkConfig(nodeTree.begin())) == -1){
+ return -1;
+ }
+
+ std::list<DOTCONFDocumentNode*>::iterator from;
+ DOTCONFDocumentNode * tagNode = NULL;
+ int vi = 0;
+ for(std::list<DOTCONFDocumentNode*>::iterator i = nodeTree.begin(); i!=nodeTree.end(); i++){
+ tagNode = *i;
+ if(!cmp_func("IncludeFile", tagNode->name)){
+ vi = 0;
+ while( vi < tagNode->valuesCount ){
+ glob_t globBuf;
+ std::string nodeFilePath;
+ if (*tagNode->values[vi] != '/') {
+ // Relative path
+ nodeFilePath = pathName + "/" + tagNode->values[vi];
+ } else {
+ // Absolute path
+ nodeFilePath = tagNode->values[vi];
+ }
+ int res = glob(nodeFilePath.c_str(), 0, NULL, &globBuf);
+ if (res) {
+ switch (res) {
+ case GLOB_NOSPACE:
+ error(tagNode->lineNum, tagNode->fileName, "glob call failed for '%s': no free space", nodeFilePath.c_str());
+ return -1;
+ case GLOB_ABORTED:
+ // printf("Read error\n");
+ // Ignore that error
+ break;
+ case GLOB_NOMATCH:
+ // printf("No match\n");
+ // Ignore that error
+ break;
+ default:
+ error(tagNode->lineNum, tagNode->fileName, "glob call failed for '%s': unknown error", nodeFilePath.c_str());
+ return -1;
+ }
+ }
+ if (!res) {
+ for (size_t i = 0; i < globBuf.gl_pathc; ++i) {
+ std::string nodeFilePath(globBuf.gl_pathv[i]);
+ if(access(nodeFilePath.c_str(), R_OK) == -1){
+ error(tagNode->lineNum, tagNode->fileName, "%s: %s", nodeFilePath.c_str(), strerror(errno));
+ continue;
+ }
+ if(realpath(nodeFilePath.c_str(), realpathBuf) == NULL){
+ error(tagNode->lineNum, tagNode->fileName, "realpath(%s) failed: %s", nodeFilePath.c_str(), strerror(errno));
+ continue;
+ }
+
+ bool processed = false;
+ for(std::list<char*>::const_iterator itInode = processedFiles.begin(); itInode != processedFiles.end(); itInode++){
+ if(!strcmp(*itInode, realpathBuf)){
+ processed = true;
+ break;
+ }
+ }
+ if(processed){
+ break;
+ }
+
+ processedFiles.push_back(strdup(realpathBuf));
+
+ file = fopen(nodeFilePath.c_str(), "r");
+ if(file == NULL){
+ error(tagNode->lineNum, fileName, "failed to open file '%s': %s", nodeFilePath.c_str(), strerror(errno));
+ continue;
+ }
+ //free(fileName);
+ fileName = strdup(realpathBuf);
+ from = nodeTree.end(); from--;
+
+ if(tagNode->parentNode){
+ DOTCONFDocumentNode * nd = tagNode->parentNode->childNode;
+ while(nd){
+ if(!nd->nextNode)
+ break;
+ nd = nd->nextNode;
+ }
+
+ curPrev = nd;
+ }
+ ret = parseFile(tagNode->parentNode);
+
+ //ret = parseFile(tagNode->parentNode);
+ (void) fclose(file);
+ if(ret == -1)
+ continue;
+ if(checkConfig(++from) == -1){
+ continue;
+ }
+ }
+ }
+ globfree(&globBuf);
+ vi++;
+ }
+ }
+ }
+ /*
+ if( (ret = checkConfig(nodeTree.begin())) == -1){
+ return -1;
+ }
+ */
+
+ if(!requiredOptions.empty())
+ ret = checkRequiredOptions();
+ }
+
+ return ret;
+}
+
+int DOTCONFDocument::checkRequiredOptions()
+{
+ for(std::list<char*>::const_iterator ci = requiredOptions.begin(); ci != requiredOptions.end(); ci++){
+ bool matched = false;
+ for(std::list<DOTCONFDocumentNode*>::iterator i = nodeTree.begin(); i!=nodeTree.end(); i++){
+ if(!cmp_func((*i)->name, *ci)){
+ matched = true;
+ break;
+ }
+ }
+ if(!matched){
+ error(0, NULL, "required option '%s' not specified", *ci);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+void DOTCONFDocument::error(int lineNum, const char * fileName, const char * fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+
+ size_t len = (lineNum!=0?strlen(fileName):0) + strlen(fmt) + 50;
+ char * buf = (char*)mempool->alloc(len);
+
+ if(lineNum)
+ (void) snprintf(buf, len, "DOTCONF++: file '%s', line %d: %s\n", fileName, lineNum, fmt);
+ else
+ (void) snprintf(buf, len, "DOTCONF++: %s\n", fmt);
+
+ if (errorCallback) {
+ errorCallback(errorCallbackData, buf);
+ } else {
+ (void) vfprintf(stderr, buf, args);
+ }
+
+ va_end(args);
+}
+
+char * DOTCONFDocument::getSubstitution(char * macro, int lineNum)
+{
+ char * buf = NULL;
+ char * variable = macro+2;
+
+ char * endBr = strchr(macro, '}');
+
+ if(!endBr){
+ error(lineNum, fileName, "unterminated '{'");
+ return NULL;
+ }
+ *endBr = 0;
+
+ char * defaultValue = strchr(variable, ':');
+
+ if(defaultValue){
+ *defaultValue++ = 0;
+ if(*defaultValue != '-'){
+ error(lineNum, fileName, "incorrect macro substitution syntax");
+ return NULL;
+ }
+ defaultValue++;
+ if(*defaultValue == '"' || *defaultValue == '\''){
+ defaultValue++;
+ defaultValue[strlen(defaultValue)-1] = 0;
+ }
+ } else {
+ defaultValue = NULL;
+ }
+
+ char * subs = getenv(variable);
+ if( subs ){
+ buf = mempool->strdup(subs);
+ } else {
+ std::list<DOTCONFDocumentNode*>::iterator i = nodeTree.begin();
+ DOTCONFDocumentNode * tagNode = NULL;
+ for(; i!=nodeTree.end(); i++){
+ tagNode = *i;
+ if(!cmp_func(tagNode->name, variable)){
+ if(tagNode->valuesCount != 0){
+ buf = mempool->strdup(tagNode->values[0]);
+ break;
+ }
+ }
+ }
+ if( i == nodeTree.end() ){
+ if( defaultValue ){
+ buf = mempool->strdup(defaultValue);
+ } else {
+ error(lineNum, fileName, "substitution not found and default value not given");
+ return NULL;
+ }
+ }
+ }
+ return buf;
+}
+
+int DOTCONFDocument::macroSubstitute(DOTCONFDocumentNode * tagNode, int valueIndex)
+{
+ int ret = 0;
+ char * macro = tagNode->values[valueIndex];
+ size_t valueLen = strlen(tagNode->values[valueIndex])+1;
+ char * value = (char*)mempool->alloc(valueLen);
+ char * v = value;
+ char * subs = NULL;
+
+ while(*macro){
+ if(*macro == '$' && *(macro+1) == '{'){
+ char * m = strchr(macro, '}');
+ subs = getSubstitution(macro, tagNode->lineNum);
+ if(subs == NULL){
+ ret = -1;
+ break;
+ }
+ macro = m + 1;
+ *v = 0;
+ v = (char*)mempool->alloc(strlen(value)+strlen(subs)+valueLen);
+ strcpy(v, value);
+ value = strcat(v, subs);
+ v = value + strlen(value);
+ continue;
+ }
+ *v++ = *macro++;
+ }
+ *v = 0;
+
+ free(tagNode->values[valueIndex]);
+ tagNode->values[valueIndex] = strdup(value);
+ return ret;
+}
+
+const DOTCONFDocumentNode * DOTCONFDocument::getFirstNode() const
+{
+ if ( !nodeTree.empty() ) {
+ return *nodeTree.begin();
+ } else {
+ return NULL;
+ }
+}
+
+const DOTCONFDocumentNode * DOTCONFDocument::findNode(const char * nodeName, const DOTCONFDocumentNode * parentNode, const DOTCONFDocumentNode * startNode) const
+{
+ //printf("nodeName=%s, cont=%s, start=%s\n", nodeName, containingNode!=NULL?containingNode->name:"NULL", startNode!=NULL?startNode->name:"NULL");
+
+ std::list<DOTCONFDocumentNode*>::const_iterator i = nodeTree.begin();
+
+ if(startNode == NULL)
+ startNode = parentNode;
+
+ if(startNode != NULL){
+ while( i != nodeTree.end() && (*i) != startNode ){
+ i++;
+ }
+ if( i != nodeTree.end() ) i++;
+ }
+
+ for(; i!=nodeTree.end(); i++){
+ //if(parentNode != NULL && (*i)->parentNode != parentNode){
+ if((*i)->parentNode != parentNode){
+ continue;
+ }
+ if(!cmp_func(nodeName, (*i)->name)){
+ return *i;
+ }
+ }
+ return NULL;
+}
+
+void DOTCONFDocument::setRequiredOptionNames(const char ** requiredOptionNames)
+{
+ while(*requiredOptionNames){
+ requiredOptions.push_back(strdup( *requiredOptionNames ));
+ requiredOptionNames++;
+ }
+}
+
--- /dev/null
+/* Copyright (C) 2003 Aleksey Krivoshey <voodoo@foss.kharkov.ua>
+*
+* 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
+*/
+
+
+#ifndef DOTCONFPP_H
+#define DOTCONFPP_H
+
+#include <list>
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <limits.h>
+
+#include "os_int.h"
+#include "mempool.h"
+
+typedef void (* DOTCONFCallback) (void * data, const char * buf);
+
+class DOTCONFDocument;
+
+class DOTCONFDocumentNode
+{
+friend class DOTCONFDocument;
+private:
+ DOTCONFDocumentNode * previousNode;
+ DOTCONFDocumentNode * nextNode;
+ DOTCONFDocumentNode * parentNode;
+ DOTCONFDocumentNode * childNode;
+ char ** values;
+ int valuesCount;
+ char * name;
+ const DOTCONFDocument * document;
+ int lineNum;
+ char * fileName;
+ bool closed;
+
+ void pushValue(char * _value);
+
+public:
+ DOTCONFDocumentNode();
+ ~DOTCONFDocumentNode();
+
+ const char * getConfigurationFileName() const { return fileName; }
+ int getConfigurationLineNumber() const { return lineNum; }
+
+ const DOTCONFDocumentNode * getNextNode() const { return nextNode; }
+ const DOTCONFDocumentNode * getPreviuosNode() const { return previousNode; }
+ const DOTCONFDocumentNode * getParentNode() const { return parentNode; }
+ const DOTCONFDocumentNode * getChildNode() const { return childNode; }
+ const char * getValue(int index = 0) const;
+ const char * getName() const { return name; }
+ const DOTCONFDocument * getDocument() const { return document; }
+};
+
+class DOTCONFDocument
+{
+public:
+ enum CaseSensitive { CASESENSITIVE, CASEINSENSITIVE };
+protected:
+ AsyncDNSMemPool * mempool;
+private:
+ DOTCONFDocumentNode * curParent;
+ DOTCONFDocumentNode * curPrev;
+ DOTCONFCallback errorCallback;
+ void * errorCallbackData;
+ int curLine;
+ bool quoted;
+ std::list<DOTCONFDocumentNode *> nodeTree;
+ std::list<char *> requiredOptions;
+ std::list<char *> processedFiles;
+ FILE * file;
+ char * fileName;
+ std::list<char *> words;
+ int (* cmp_func)(const char *, const char *);
+
+ int checkRequiredOptions();
+ int parseLine();
+ int parseFile(DOTCONFDocumentNode * _parent = NULL);
+ int checkConfig(const std::list<DOTCONFDocumentNode *>::iterator & from);
+ int cleanupLine(char * line);
+ char * getSubstitution(char * macro, int lineNum);
+ int macroSubstitute(DOTCONFDocumentNode * tagNode, int valueIndex);
+
+protected:
+ virtual void error(int lineNum, const char * fileName, const char * fmt, ...);
+
+public:
+ DOTCONFDocument(CaseSensitive caseSensitivity = CASESENSITIVE);
+ virtual ~DOTCONFDocument();
+
+ void setErrorCallback(DOTCONFCallback _callback, void * _data) { errorCallback = _callback; errorCallbackData = _data; };
+
+ int setContent(const char * _fileName);
+
+ void setRequiredOptionNames(const char ** requiredOptionNames); // !TERMINATE ARRAY WITH NULL
+ const DOTCONFDocumentNode * getFirstNode() const;
+ const DOTCONFDocumentNode * findNode(const char * nodeName, const DOTCONFDocumentNode * parentNode = NULL, const DOTCONFDocumentNode * startNode = NULL) const;
+};
+
+#endif
--- /dev/null
+/* Copyright (C) 2003 Aleksey Krivoshey <voodoo@foss.kharkov.ua>
+*
+* 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
+*/
+
+
+#include "mempool.h"
+
+AsyncDNSMemPool::PoolChunk::PoolChunk(size_t _size):
+ pool(NULL), pos(0), size(_size)
+{
+ pool = ::malloc(size);
+}
+
+AsyncDNSMemPool::PoolChunk::~PoolChunk()
+{
+ ::free(pool);
+}
+
+AsyncDNSMemPool::AsyncDNSMemPool(size_t _defaultSize):
+ chunks(NULL), chunksCount(0), defaultSize(_defaultSize),
+ poolUsage(0), poolUsageCounter(0)
+{
+}
+
+AsyncDNSMemPool::~AsyncDNSMemPool()
+{
+ for(size_t i = 0; i<chunksCount; i++){
+ delete chunks[i];
+ }
+ ::free(chunks);
+}
+
+int AsyncDNSMemPool::initialize()
+{
+ chunksCount = 1;
+ chunks = (PoolChunk**)::malloc(sizeof(PoolChunk*));
+ if(chunks == NULL)
+ return -1;
+
+ chunks[chunksCount-1] = new PoolChunk(defaultSize);
+
+ return 0;
+}
+
+void AsyncDNSMemPool::addNewChunk(size_t size)
+{
+ chunksCount++;
+ chunks = (PoolChunk**)::realloc(chunks, chunksCount*sizeof(PoolChunk*));
+ if(size <= defaultSize)
+ chunks[chunksCount-1] = new PoolChunk(defaultSize);
+ else
+ chunks[chunksCount-1] = new PoolChunk(size);
+}
+
+void * AsyncDNSMemPool::alloc(size_t size)
+{
+ PoolChunk * chunk = NULL;
+ for(size_t i = 0; i<chunksCount; i++){
+ chunk = chunks[i];
+ if((chunk->size - chunk->pos) >= size){
+ chunk->pos += size;
+ return ((u_int8_t*)chunk->pool) + chunk->pos - size;
+ }
+ }
+ addNewChunk(size);
+ chunks[chunksCount-1]->pos = size;
+ return chunks[chunksCount-1]->pool;
+}
+
+void AsyncDNSMemPool::free()
+{
+ size_t pu = 0;
+ size_t psz = 0;
+ poolUsageCounter++;
+
+ for(size_t i = 0; i<chunksCount; i++){
+ pu += chunks[i]->pos;
+ psz += chunks[i]->size;
+ chunks[i]->pos = 0;
+ }
+ poolUsage=(poolUsage>pu)?poolUsage:pu;
+
+ if(poolUsageCounter >= 10 && chunksCount > 1){
+ psz -= chunks[chunksCount-1]->size;
+ if(poolUsage < psz){
+ chunksCount--;
+ delete chunks[chunksCount];
+ }
+ poolUsage = 0;
+ poolUsageCounter = 0;
+ }
+}
+
+void * AsyncDNSMemPool::calloc(size_t size)
+{
+ return ::memset(this->alloc(size), 0, size);
+}
+
+char * AsyncDNSMemPool::strdup(const char *str)
+{
+ return ::strcpy((char*)this->alloc(strlen(str)+1), str);
+}
+
--- /dev/null
+/* Copyright (C) 2003 Aleksey Krivoshey <voodoo@foss.kharkov.ua>
+*
+* 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
+*/
+
+
+#ifndef ASYNC_DNS_MEMPOOL_H
+#define ASYNC_DNS_MEMPOOL_H
+
+#include "os_int.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+class AsyncDNSMemPool
+{
+private:
+ struct PoolChunk {
+ void * pool;
+ size_t pos;
+ size_t size;
+
+ PoolChunk(size_t _size);
+ ~PoolChunk();
+ };
+ PoolChunk ** chunks;
+ size_t chunksCount;
+ size_t defaultSize;
+
+ size_t poolUsage;
+ size_t poolUsageCounter;
+
+ void addNewChunk(size_t size);
+
+public:
+ AsyncDNSMemPool(size_t _defaultSize = 4096);
+ virtual ~AsyncDNSMemPool();
+
+ int initialize();
+ void free();
+ void * alloc(size_t size);
+ void * calloc(size_t size);
+ char * strdup(const char *str);
+};
+
+#endif
+
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.3 2007/05/08 14:29:20 faust Exp $
+###############################################################################
+
+LIB_NAME = hostallow
+PROG = lib$(LIB_NAME)
+
+SRCS = hostallow.cpp
+
+INCS = hostallow.h
+
+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
+ */
+
+/*
+ * Date: 27.10.2002
+ */
+
+/*
+ * Author : Boris Mikhailenko <stg34@ua.fm>
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <algorithm>
+#include <functional>
+
+#include "hostallow.h"
+//-----------------------------------------------------------------------------
+HOSTALLOW::HOSTALLOW()
+{
+
+}
+//-----------------------------------------------------------------------------
+int HOSTALLOW::ParseHosts(const char * str, int hostsType)
+{
+/*
+ðÒÏÉÚ×ÏÄÉÍ ÒÁÚÂÏÒ ÓÔÒÏËÉ ×ÉÄÁ host host host ...
+ÇÄÅ host ÍÏÖÅÔ ÉÍÅÔØ ×ÉÄ a.b.c.d ÉÌÉ a.b.c.d/e
+ÉÌÉ all.
+ÐÒÉÞÅÍ × ÓÌÕÞÁÅ ÓÅÔÉ ÍÁÓËÁ É ÁÄÒÅÓ ÄÏÌÖÎÙ ÂÙÔØ
+ÓÏÏÔ×ÅÔÓÔ×ÕÀÝÉÍÉ ÄÒÕÇ ÄÒÕÇÕ.
+
+òÅÚÕÌØÔÁÔÙ ÚÁÎÏÓÉÍ × ÓÏÏÔ×ÅÔÓÔ×ÕÀÝÉÊ ÓÐÉÓÏË
+ * */
+
+int len;
+char *s;
+char * tok;
+uint32_t ip;
+uint32_t mask;
+//INETADDR inetAddr;
+
+if (strcasecmp(str, "all") == 0)
+ {
+ if (hostsType == hostsAllow)
+ hostAllowList.push_back(INETADDR());
+ else
+ hostDenyList.push_back(INETADDR());
+ return 0;
+ }
+else
+ {
+ len = strlen(str);
+
+ s = new char[len + 1];
+
+ strcpy(s, str);
+
+ tok = strtok(s, " ");
+
+ while (tok)
+ {
+ if (ParseIPMask(tok, &ip, &mask) != 0)
+ {
+ return -1;
+ delete[] s;
+ }
+ //printfd(__FILE__, "ParseHosts tok %s\n", tok);
+ tok = strtok(NULL, " ");
+ if (hostsType == hostsAllow)
+ {
+ //printfd(__FILE__, "ParseHosts APPEND allow %X %X\n", ip, mask);
+ hostAllowList.push_back(INETADDR(ip, mask));
+ }
+ else
+ {
+ //printfd(__FILE__, "ParseHosts APPEND deny %X %X\n", ip, mask);
+ hostDenyList.push_back(INETADDR(ip, mask));
+ }
+ }
+ }
+
+delete[] s;
+return 0;
+}
+//-----------------------------------------------------------------------------
+int HOSTALLOW::ParseIPMask(const char * s, uint32_t * ip, uint32_t * mask)
+{
+/*
+òÁÚÂÏÒ ÓÔÒÏËÉ ×ÉÄÁ a.b.c.d/e ÉÌÉ a.b.c.d
+
+123.123.123.123/30
+ * */
+int len;
+char * host;
+
+int i = 0, msk;
+
+len = strlen(s);
+host = new char[len + 1];
+
+while (s[i] != 0 && s[i] != '/')
+ {
+ host[i] = s[i];
+ i++;
+ }
+
+host[i] = 0;
+
+if (inet_addr(host) == INADDR_NONE)
+ {
+ delete[] host;
+ sprintf(errMsg, "Icorrect IP address %s", host);
+ return -1;
+ }
+
+*ip = inet_addr(host);
+
+char *res;
+
+if (s[i] == '/')
+ {
+ msk = strtol(&s[i+1], &res, 10);
+ if (*res != 0)
+ {
+ sprintf(errMsg, "Icorrect mask %s", &s[i+1]);
+ delete[] host;
+ return -1;
+ }
+
+ if (msk < 0 || msk > 32)
+ {
+ sprintf(errMsg, "Icorrect mask %s", &s[i+1]);
+ delete[] host;
+ *mask = 0;
+ return 0;
+ }
+
+ uint32_t m = 0;
+ m = htonl(0xFFffFFff<<(32 - msk));
+
+ *mask = m;
+ }
+else
+ {
+ *mask = 0xFFffFFff;
+ }
+
+if ((*ip & *mask) != *ip)
+ {
+ sprintf(errMsg, "Address does'n match mask.\n");
+ delete[] host;
+ return -1;
+ }
+
+delete[] host;
+return 0;
+}
+//-----------------------------------------------------------------------------
+int HOSTALLOW::ParseOrder(const char * str)
+{
+/*
+ÐÒÏÉÚ×ÏÄÉÍ ÒÁÚÂÏÒ ÓÔÒÏËÉ ×ÉÄÁ allow deny ÉÌÉ deny allow
+ */
+
+if (strcasecmp(str, "allow,deny") == 0)
+ {
+ order = orderAllow;
+ return 0;
+ }
+
+if (strcasecmp(str, "deny,allow") == 0)
+ {
+ order = orderDeny;
+ return 0;
+ }
+
+sprintf(errMsg, "Parameter \'order\' must be \'allow,deny\' or \'deny,allow\'");
+return -1;
+}
+//-----------------------------------------------------------------------------
+int HOSTALLOW::GetError()
+{
+/*
+÷ÏÚ×ÒÁÝÁÅÍ ËÏÄ ÏÛÉÂËÉ É ÓÂÒÁÓÙ×ÁÅÍ ÅÅ.
+ * */
+return 0;
+}
+//-----------------------------------------------------------------------------
+bool HOSTALLOW::HostAllowed(uint32_t ip)
+{
+/*
+ðÒÏ×ÅÒÑÅÍ Ñ×ÌÑÅÔÓÑ ÌÉ éð ÒÁÚÒÅÛÅÎÎÙÍ ÉÌÉ ÎÅÔ
+ * */
+
+if (order == orderDeny)
+ {
+ if (IsHostInDeniedList(ip))
+ {
+ return false;
+ }
+
+ if (IsHostInAllowedList(ip))
+ {
+ return true;
+ }
+ }
+else
+ {
+ if (IsHostInAllowedList(ip))
+ {
+ return true;
+ }
+
+ if (IsHostInDeniedList(ip))
+ {
+ return false;
+ }
+ }
+
+return false;
+}
+//-----------------------------------------------------------------------------
+int HOSTALLOW::IsIPInSubnet(uint32_t checkedIP, INETADDR &ia)
+{
+//uint32_t checkedIP;
+if ((ia.mask & checkedIP) == (ia.ip))
+ return true;
+return false;
+}
+//-----------------------------------------------------------------------------
+bool HOSTALLOW::IsHostInAllowedList(uint32_t ip)
+{
+/*
+îÁÈÏÄÉÔÓÑ ÌÉ éð × ÓÐÉÓËÅ ÒÁÚÒÅÛÅÎÎÙÈ
+ * */
+list<INETADDR>::iterator li;
+
+li = hostAllowList.begin();
+
+while(li != hostAllowList.end())
+ {
+ if (IsIPInSubnet(ip, *li))
+ return true;
+ }
+
+return false;
+}
+//-----------------------------------------------------------------------------
+bool HOSTALLOW::IsHostInDeniedList(uint32_t ip)
+{
+/*
+îÁÈÏÄÉÔÓÑ ÌÉ éð × ÓÐÉÓËÅ ÚÁÐÒÅÝÅÎÎÙÈ
+ * */
+list<INETADDR>::iterator li;
+
+li = hostDenyList.begin();
+
+while(li != hostDenyList.end())
+ {
+ if (IsIPInSubnet(ip, *li))
+ return true;
+ }
+
+return false;
+}
+//-----------------------------------------------------------------------------
+const char * HOSTALLOW::GetStrError()
+{
+/*
+÷ÏÚ×ÒÁÝÁÅÍ ÔÅËÓÔÏ×ÏÅ ÏÐÉÓÁÎÉÅ ÏÛÉÂËÉ.
+ * */
+return errMsg;
+}
+//-----------------------------------------------------------------------------
+
--- /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@ua.fm>
+ */
+
+
+#ifndef HOSTALLOW_H
+#define HOSTALLOW_H
+
+#include "os_int.h"
+
+#include <list>
+
+using namespace std;
+
+#define HA_ERR_MSG_LEN (255)
+//-----------------------------------------------------------------------------
+enum ORDER
+{
+ orderAllow = 0,
+ orderDeny
+};
+//-----------------------------------------------------------------------------
+enum
+{
+ hostsAllow = 0,
+ hostsDeny
+};
+//-----------------------------------------------------------------------------
+struct INETADDR
+{
+ INETADDR(uint32_t i, uint8_t m) {ip = i; mask = m;};
+ INETADDR() {ip = 0; mask = 0;};
+ uint32_t ip;
+ uint8_t mask;
+};
+//-----------------------------------------------------------------------------
+class HOSTALLOW
+{
+public:
+ HOSTALLOW();
+ int ParseHosts(const char *, int hostsType);
+ int ParseOrder(const char *);
+ int GetError();
+ bool HostAllowed(uint32_t ip);
+ const char * GetStrError();
+
+private:
+ int ParseIPMask(const char * s, uint32_t * ip, uint32_t * mask);
+ bool IsHostInDeniedList(uint32_t ip);
+ bool IsHostInAllowedList(uint32_t ip);
+ //int IsIPInSubnet(INETADDR &ia);
+ int IsIPInSubnet(uint32_t checkedIP, INETADDR &ia);
+ list<INETADDR> hostAllowList;
+ list<INETADDR> hostDenyList;
+ char errMsg[HA_ERR_MSG_LEN];
+ int order;
+ char src[16 + 1];
+ char dst[16 + 1];
+
+};
+//-----------------------------------------------------------------------------
+
+#endif
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.11 2010/08/18 07:47:03 faust Exp $
+###############################################################################
+
+LIB_NAME = ia_auth_c
+PROG = lib$(LIB_NAME)
+
+SRCS = ia_auth_c.cpp
+
+INCS = ia_auth_c.h
+
+STGLIBS = -lstg_common \
+ -lstg_crypto
+LIBS = $(LIB_THREAD)
+
+include ../Makefile.in
--- /dev/null
+//---------------------------------------------------------------------------
+
+#include <vcl.h>
+#pragma hdrstop
+#define Library
+
+// To add a file to the library use the Project menu 'Add to Project'.
+
+
\ No newline at end of file
--- /dev/null
+<?xml version='1.0' encoding='utf-8' ?>
+<!-- C++Builder XML Project -->
+<PROJECT>
+ <MACROS>
+ <VERSION value="BCB.06.00"/>
+ <PROJECT value="..\..\lib\ia_auth_c.lib"/>
+ <OBJFILES value="ia_auth_c.obj"/>
+ <RESFILES value=""/>
+ <IDLFILES value=""/>
+ <IDLGENFILES value=""/>
+ <DEFFILE value=""/>
+ <RESDEPEN value="$(RESFILES)"/>
+ <LIBFILES value=""/>
+ <LIBRARIES value=""/>
+ <PACKAGES value=""/>
+ <PATHCPP value=".;"/>
+ <PATHPAS value=".;"/>
+ <PATHRC value=".;"/>
+ <PATHASM value=".;"/>
+ <LINKER value="TLib"/>
+ <USERDEFINES value="_DEBUG;WIN32"/>
+ <SYSDEFINES value="_RTLDLL;NO_STRICT"/>
+ <MAINSOURCE value="ia_auth_c.bpf"/>
+ <INCLUDEPATH value="$(BCB)\include;$(BCB)\include\vcl;..\..\include"/>
+ <LIBPATH value="$(BCB)\lib\obj;$(BCB)\lib"/>
+ <WARNINGS value="-w-par"/>
+ <LISTFILE value=""/>
+ <OTHERFILES value=""/>
+ </MACROS>
+ <OPTIONS>
+ <IDLCFLAGS value="-I$(BCB)\include -I$(BCB)\include\vcl -I..\..\include -src_suffix cpp
+ -D_DEBUG -DWIN32 -boa"/>
+ <CFLAG1 value="-Od -H=$(BCB)\lib\vcl60.csm -Hc -Vx -Ve -X- -r- -a8 -b- -k -y -v -vi- -c
+ -tW -tWM"/>
+ <PFLAGS value="-$YD -$W -$O- -$A8 -v -JPHNE -M"/>
+ <AFLAGS value="/mx /w2 /zd"/>
+ <LFLAGS value=""/>
+ <OTHERFILES value=""/>
+ </OPTIONS>
+ <LINKER>
+ <ALLOBJ value="$(OBJFILES)"/>
+ <ALLLIB value=""/>
+ <OTHERFILES value=""/>
+ </LINKER>
+ <FILELIST>
+ <FILE FILENAME="ia_auth_c.bpf" FORMNAME="" UNITNAME="ia_auth_c" CONTAINERID="BPF" DESIGNCLASS="" LOCALCOMMAND=""/>
+ <FILE FILENAME="packet.h" FORMNAME="" UNITNAME="packet.h" CONTAINERID="" DESIGNCLASS="" LOCALCOMMAND=""/>
+ <FILE FILENAME="ia_auth_c.h" FORMNAME="" UNITNAME="ia_auth_c.h" CONTAINERID="" DESIGNCLASS="" LOCALCOMMAND=""/>
+ <FILE FILENAME="ia_auth_c.cpp" FORMNAME="" UNITNAME="ia_auth_c.cpp" CONTAINERID="CCompiler" DESIGNCLASS="" LOCALCOMMAND=""/>
+ </FILELIST>
+ <BUILDTOOLS>
+ </BUILDTOOLS>
+
+ <IDEOPTIONS>
+[Version Info]
+IncludeVerInfo=0
+AutoIncBuild=0
+MajorVer=1
+MinorVer=0
+Release=0
+Build=0
+Debug=0
+PreRelease=0
+Special=0
+Private=0
+DLL=0
+Locale=1049
+CodePage=1251
+
+[Version Info Keys]
+CompanyName=
+FileDescription=
+FileVersion=1.0.0.0
+InternalName=
+LegalCopyright=
+LegalTrademarks=
+OriginalFilename=
+ProductName=
+ProductVersion=1.0.0.0
+Comments=
+
+[HistoryLists\hlIncludePath]
+Count=2
+Item0=$(BCB)\include;$(BCB)\include\vcl;..\..\include
+Item1=$(BCB)\include;$(BCB)\include\vcl
+
+[HistoryLists\hlLibraryPath]
+Count=1
+Item0=$(BCB)\lib\obj;$(BCB)\lib
+
+[HistoryLists\hlDebugSourcePath]
+Count=1
+Item0=$(BCB)\source\vcl
+
+[HistoryLists\hlConditionals]
+Count=2
+Item0=_DEBUG;WIN32
+Item1=_DEBUG
+
+[HistoryLists\hlFinalOutputDir]
+Count=1
+Item0=..\..\lib
+
+[Debugging]
+DebugSourceDirs=$(BCB)\source\vcl
+
+[Parameters]
+RunParams=
+Launcher=
+UseLauncher=0
+DebugCWD=
+HostApplication=
+RemoteHost=
+RemotePath=
+RemoteLauncher=
+RemoteCWD=
+RemoteDebug=0
+
+[Compiler]
+ShowInfoMsgs=0
+LinkDebugVcl=0
+LinkCGLIB=0
+
+[CORBA]
+AddServerUnit=1
+AddClientUnit=1
+PrecompiledHeaders=1
+ </IDEOPTIONS>
+</PROJECT>
\ No newline at end of file
--- /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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+ $Author: faust $
+ $Revision: 1.15 $
+ $Date: 2010/04/16 11:28:03 $
+*/
+
+/*
+* Author :
+* Boris Mikhailenko <stg34@stargazer.dp.ua>
+* Andrey Rakhmanov <andrey_rakhmanov@yahoo.com> - èñïðàâëåíèå äâóõ áàãîâ.
+*/
+
+//---------------------------------------------------------------------------
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <string.h>
+
+#ifdef WIN32
+ #include <winsock2.h>
+ #include <windows.h>
+ #include <winbase.h>
+ #include <winnt.h>
+#else
+ #include <fcntl.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netdb.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+ #include <unistd.h>
+#endif
+
+#include "common.h"
+#include "ia_auth_c.h"
+
+#define IA_NONE (0)
+#define IA_CONNECT (1)
+#define IA_DISCONNECT (2)
+
+#define IA_DEBUGPROTO 1
+
+#define IA_ID "00100"
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+#ifndef WIN32
+#include <sys/time.h>
+void * RunL(void * data)
+{
+
+IA_CLIENT_PROT * c = (IA_CLIENT_PROT *)data;
+static int a = 0;
+
+if (a == 0)
+ {
+ usleep(50000);
+ a = 1;
+ }
+
+while (c->GetNonstop())
+ {
+ c->Run();
+ }
+return NULL;
+}
+//---------------------------------------------------------------------------
+void Sleep(int ms)
+{
+usleep(ms * 1000);
+}
+//---------------------------------------------------------------------------
+long GetTickCount()
+{
+struct timeval tv;
+gettimeofday(&tv, NULL);
+return tv.tv_sec*1000 + tv.tv_usec/1000;
+}
+#else
+//---------------------------------------------------------------------------
+unsigned long WINAPI RunW(void * data)
+{
+IA_CLIENT_PROT * c = (IA_CLIENT_PROT *)data;
+while (c->GetNonstop())
+ c->Run();
+return 0;
+}
+//---------------------------------------------------------------------------
+#endif
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+IA_CLIENT_PROT::IA_CLIENT_PROT(const string & sn, unsigned short p, uint16_t localPort)
+ : stat(),
+ action(IA_NONE),
+ phase(1),
+ phaseTime(0),
+ messageText(),
+ infoText(),
+ strError(),
+ codeError(0),
+ nonstop(true),
+ isNetPrepared(false),
+ proxyMode(false),
+ password(),
+ login(),
+ serverName(sn),
+ port(p),
+ ip(0),
+ localPort(localPort),
+ firstConnect(true),
+ reconnect(0),
+ sockr(0),
+ protNum(0),
+ userTimeout(60),
+ aliveTimeout(5),
+ rnd(0),
+ pStatusChangedCb(NULL),
+ pStatChangedCb(NULL),
+ pInfoCb(NULL),
+ pErrorCb(NULL),
+ pDirNameCb(NULL),
+ statusChangedCbData(NULL),
+ statChangedCbData(NULL),
+ infoCbData(NULL),
+ errorCbData(NULL),
+ dirNameCbData(NULL),
+ packetTypes(),
+ connSyn8(NULL),
+ connSynAck8(NULL),
+ connAck8(NULL),
+ aliveSyn8(NULL),
+ aliveAck8(NULL),
+ disconnSyn8(NULL),
+ disconnSynAck8(NULL),
+ disconnAck8(NULL),
+ err(),
+ info(NULL)
+{
+memset(&stat, 0, sizeof(stat));
+
+#ifdef WIN32
+WSAStartup(MAKEWORD(2, 0), &wsaData);
+#endif
+
+packetTypes["CONN_SYN"] = CONN_SYN_N;
+packetTypes["CONN_SYN_ACK"] = CONN_SYN_ACK_N;
+packetTypes["CONN_ACK"] = CONN_ACK_N;
+packetTypes["ALIVE_SYN"] = ALIVE_SYN_N;
+packetTypes["ALIVE_ACK"] = ALIVE_ACK_N;
+packetTypes["DISCONN_SYN"] = DISCONN_SYN_N;
+packetTypes["DISCONN_SYN_ACK"] = DISCONN_SYN_ACK_N;
+packetTypes["DISCONN_ACK"] = DISCONN_ACK_N;
+packetTypes["FIN"] = FIN_N;
+packetTypes["ERR"] = ERROR_N;
+packetTypes["INFO"] = INFO_N;
+packetTypes["INFO_7"] = INFO_7_N;
+packetTypes["INFO_8"] = INFO_8_N;
+
+unsigned char key[IA_PASSWD_LEN];
+memset(key, 0, IA_LOGIN_LEN);
+strncpy((char *)key, "pr7Hhen", 8);
+Blowfish_Init(&ctxHdr, key, IA_PASSWD_LEN);
+}
+//---------------------------------------------------------------------------
+void IA_CLIENT_PROT::PrepareNet()
+{
+struct hostent * phe;
+unsigned long ip;
+
+ip = inet_addr(serverName.c_str());
+if (ip == INADDR_NONE)
+ {
+ phe = gethostbyname(serverName.c_str());
+ if (phe)
+ {
+ ip = *((unsigned long*)phe->h_addr_list[0]);
+ }
+ else
+ {
+ strError = string("Unknown host ") + "\'" + serverName + "\'";
+ codeError = IA_GETHOSTBYNAME_ERROR;
+ if (pErrorCb != NULL)
+ pErrorCb(messageText, IA_GETHOSTBYNAME_ERROR, errorCbData);
+ }
+ }
+
+#ifndef WIN32
+close(sockr);
+#else
+closesocket(sockr);
+#endif
+
+sockr = socket(AF_INET, SOCK_DGRAM, 0); // Cîêåò ÷åðåç êîòîðûé øëåì è ïðèíèìàåì
+
+localAddrS.sin_family = AF_INET;
+localAddrS.sin_port = htons(port);
+localAddrS.sin_addr.s_addr = inet_addr("0.0.0.0");
+
+localAddrR.sin_family = AF_INET;
+
+if (localPort)
+ localAddrR.sin_port = htons(localPort);
+else
+ localAddrR.sin_port = htons(port);
+localAddrR.sin_addr.s_addr = inet_addr("0.0.0.0");
+
+servAddr.sin_family = AF_INET;
+servAddr.sin_port = htons(port);
+servAddr.sin_addr.s_addr = ip;
+
+int res = bind(sockr, (struct sockaddr*)&localAddrR, sizeof(localAddrR));
+if (res == -1)
+ {
+ strError = "bind error";
+ codeError = IA_BIND_ERROR;
+ if (pErrorCb != NULL)
+ pErrorCb(messageText, IA_BIND_ERROR, errorCbData);
+ return;
+ }
+
+#ifdef WIN32
+unsigned long arg = 1;
+res = ioctlsocket(sockr, FIONBIO, &arg);
+#else
+if (0 != fcntl(sockr, F_SETFL, O_NONBLOCK))
+ {
+ strError = "fcntl error";
+ codeError = IA_FCNTL_ERROR;
+ if (pErrorCb != NULL)
+ pErrorCb(messageText, IA_FCNTL_ERROR, errorCbData);
+ }
+#endif
+
+}
+//---------------------------------------------------------------------------
+IA_CLIENT_PROT::~IA_CLIENT_PROT()
+{
+#ifndef WIN32
+close(sockr);
+#else
+closesocket(sockr);
+WSACleanup();
+#endif
+}
+//---------------------------------------------------------------------------
+int IA_CLIENT_PROT::DeterminatePacketType(const char * buffer)
+{
+map<string, int>::iterator pi;
+pi = packetTypes.find(buffer);
+if (pi == packetTypes.end())
+ {
+ return -1;
+ }
+else
+ {
+ return pi->second;
+ }
+}
+//---------------------------------------------------------------------------
+void IA_CLIENT_PROT::FillHdr8(char * buffer, unsigned long)
+{
+strncpy(buffer, IA_ID, 6);
+buffer[IA_MAGIC_LEN] = 0;
+buffer[IA_MAGIC_LEN + 1] = IA_PROTO_VER;
+strncpy(buffer + sizeof(HDR_8), login.c_str(), IA_LOGIN_LEN);
+}
+//---------------------------------------------------------------------------
+int IA_CLIENT_PROT::Send(char * buffer, int len)
+{
+if (!isNetPrepared)
+ {
+ PrepareNet();
+ isNetPrepared = true;
+ }
+
+// Øèôðóåì LoginS
+int db = sizeof(HDR_8);
+for (int i = 0; i < IA_LOGIN_LEN/8; i++)
+ {
+ Blowfish_Encrypt(&ctxHdr, (uint32_t*)(buffer + db + i*8), (uint32_t*)(buffer + db + i*8 + 4));
+ }
+
+// Øèôðóåì âñ¸ îñòàëüíîå
+db += IA_LOGIN_LEN;
+int encLen = (len - sizeof(HDR_8) - IA_LOGIN_LEN)/8;
+for (int i = 0; i < encLen; i++)
+ {
+ Blowfish_Encrypt(&ctxPass, (uint32_t*)(buffer + db), (uint32_t*)(buffer + db + 4));
+ db += 8;
+ }
+
+return sendto(sockr, buffer, len, 0, (struct sockaddr*)&servAddr, sizeof(servAddr));
+}
+//---------------------------------------------------------------------------
+int IA_CLIENT_PROT::Recv(char * buffer, int len)
+{
+#ifdef WIN32
+int fromLen;
+#else
+socklen_t fromLen;
+#endif
+
+struct sockaddr_in addr;
+fromLen = sizeof(addr);
+int res = recvfrom(sockr, buffer, len, 0, (struct sockaddr*)&addr, &fromLen);
+
+if (res == -1)
+ return res;
+
+if (strcmp(buffer + 4 + sizeof(HDR_8), "ERR"))
+ {
+ for (int i = 0; i < len/8; i++)
+ Blowfish_Decrypt(&ctxPass, (uint32_t*)(buffer + i*8), (uint32_t*)(buffer + i*8 + 4));
+ }
+
+return 0;
+}
+//---------------------------------------------------------------------------
+int IA_CLIENT_PROT::NetSend(int n)
+{
+char buffer[2048];
+int msgLen;
+
+memset(buffer, 0, 2048);
+
+switch (n)
+ {
+ case CONN_SYN_N:
+ msgLen = Prepare_CONN_SYN_8(buffer);
+ break;
+
+ case CONN_ACK_N:
+ msgLen = Prepare_CONN_ACK_8(buffer);
+ break;
+
+ case ALIVE_ACK_N:
+ msgLen = Prepare_ALIVE_ACK_8(buffer);
+ break;
+
+ case DISCONN_SYN_N:
+ msgLen = Prepare_DISCONN_SYN_8(buffer);
+ break;
+
+ case DISCONN_ACK_N:
+ msgLen = Prepare_DISCONN_ACK_8(buffer);
+ break;
+
+ default:
+ return -1;
+ }
+
+FillHdr8(buffer, 0);
+Send(buffer, msgLen);
+
+return 0;
+}
+//---------------------------------------------------------------------------
+int IA_CLIENT_PROT::NetRecv()
+{
+char buffer[2048];
+
+if (Recv(buffer, sizeof(buffer)) < 0)
+ return -1;
+
+char packetName[20];
+strncpy(packetName, buffer + 12, sizeof(packetName));
+packetName[sizeof(packetName) - 1] = 0;
+int pn = DeterminatePacketType(buffer + 12);
+
+int ret;
+switch (pn)
+ {
+ case CONN_SYN_ACK_N:
+ ret = Process_CONN_SYN_ACK_8(buffer);
+ break;
+
+ case ALIVE_SYN_N:
+ ret = Process_ALIVE_SYN_8(buffer);
+ break;
+
+ case DISCONN_SYN_ACK_N:
+ ret = Process_DISCONN_SYN_ACK_8(buffer);
+ break;
+
+ case FIN_N:
+ ret = Process_FIN_8(buffer);
+ break;
+
+ case INFO_8_N:
+ ret = Process_INFO_8(buffer);
+ break;
+
+ case ERROR_N:
+ ret = Process_ERROR(buffer);
+ break;
+
+ default:
+ ret = -1;
+ }
+return ret;
+}
+//---------------------------------------------------------------------------
+void IA_CLIENT_PROT::Start()
+{
+#ifdef WIN32
+unsigned long pt;
+CreateThread(NULL, 16384, RunW, this, 0, &pt);
+#else
+pthread_create(&thread, NULL, RunL, this);
+#endif
+}
+//---------------------------------------------------------------------------
+void IA_CLIENT_PROT::Stop()
+{
+nonstop = false;
+}
+//---------------------------------------------------------------------------
+void IA_CLIENT_PROT::Run()
+{
+NetRecv();
+
+switch (phase)
+ {
+ case 1:
+ if (action == IA_CONNECT)
+ {
+ action = IA_NONE;
+ NetSend(CONN_SYN_N);
+ phase = 2;
+ phaseTime = GetTickCount();
+ }
+ if (reconnect && !firstConnect)
+ {
+ action = IA_CONNECT;
+ }
+ break;
+
+ case 2:
+ if ((int)(GetTickCount() - phaseTime)/1000 > aliveTimeout)
+ {
+ phase = 1;
+ phaseTime = GetTickCount();
+ if (pStatusChangedCb != NULL)
+ pStatusChangedCb(0, statusChangedCbData);
+ }
+
+ if (action == IA_DISCONNECT)
+ {
+ action = IA_NONE;
+ NetSend(DISCONN_SYN_N);
+ phase = 4;
+ phaseTime = GetTickCount();
+ }
+
+ break;
+
+ case 3:
+ if ((int)(GetTickCount() - phaseTime)/1000 > userTimeout)
+ {
+ phase = 1;
+ phaseTime = GetTickCount();
+ if (pStatusChangedCb != NULL)
+ pStatusChangedCb(0, statusChangedCbData);
+ firstConnect = false;
+ }
+
+ if (action == IA_DISCONNECT)
+ {
+ action = IA_NONE;
+ NetSend(DISCONN_SYN_N);
+ phase = 4;
+ phaseTime = GetTickCount();
+ }
+
+ break;
+
+ case 4:
+ if ((int)(GetTickCount() - phaseTime)/1000 > aliveTimeout)
+ {
+ phase=1;
+ phaseTime = GetTickCount();
+ if (pStatusChangedCb != NULL)
+ pStatusChangedCb(0, statusChangedCbData);
+ }
+
+ if (action == IA_CONNECT)
+ {
+ action = IA_NONE;
+ NetSend(CONN_SYN_N);
+ phase = 2;
+ phaseTime = GetTickCount();
+ }
+
+ break;
+
+ case 5:
+ if ((int)(GetTickCount() - phaseTime)/1000 > aliveTimeout)
+ {
+ phase = 1;
+ phaseTime = GetTickCount();
+ if (pStatusChangedCb != NULL)
+ pStatusChangedCb(0, statusChangedCbData);
+ }
+
+ if (action == IA_CONNECT)
+ {
+ action = IA_NONE;
+ NetSend(CONN_SYN_N);
+ phase = 2;
+ phaseTime = GetTickCount();
+ }
+
+ break;
+ }
+Sleep(20);
+return;
+}
+//---------------------------------------------------------------------------
+void IA_CLIENT_PROT::GetStat(LOADSTAT * ls)
+{
+memcpy(ls, &stat, sizeof(stat));
+}
+//---------------------------------------------------------------------------
+void IA_CLIENT_PROT::SetServer(const string & sn, unsigned short p)
+{
+serverName = sn;
+port = p;
+PrepareNet();
+}
+//---------------------------------------------------------------------------
+void IA_CLIENT_PROT::SetLogin(const string & l)
+{
+login = l;
+}
+//---------------------------------------------------------------------------
+void IA_CLIENT_PROT::SetPassword(const string & p)
+{
+password = p;
+
+unsigned char keyL[IA_PASSWD_LEN];
+memset(keyL, 0, IA_PASSWD_LEN);
+strncpy((char *)keyL, password.c_str(), IA_PASSWD_LEN);
+Blowfish_Init(&ctxPass, keyL, IA_PASSWD_LEN);
+}
+//---------------------------------------------------------------------------
+void IA_CLIENT_PROT::SetEnabledDirs(const bool * selectedDirs)
+{
+memcpy(IA_CLIENT_PROT::selectedDirs, selectedDirs, sizeof(bool) * DIR_NUM);
+}
+//---------------------------------------------------------------------------
+int IA_CLIENT_PROT::Connect()
+{
+action = IA_CONNECT;
+return 0;
+}
+//---------------------------------------------------------------------------
+int IA_CLIENT_PROT::Disconnect()
+{
+firstConnect = true;
+action = IA_DISCONNECT;
+return 0;
+}
+//---------------------------------------------------------------------------
+int IA_CLIENT_PROT::GetStrError(string * error) const
+{
+int ret = codeError;
+*error = strError;
+strError = "";
+codeError = 0;
+return ret;
+}
+//---------------------------------------------------------------------------
+int IA_CLIENT_PROT::Process_CONN_SYN_ACK_8(const char * buffer)
+{
+vector<string> dirNames;
+connSynAck8 = (CONN_SYN_ACK_8*)buffer;
+
+#ifdef ARCH_BE
+SwapBytes(connSynAck8->len);
+SwapBytes(connSynAck8->rnd);
+SwapBytes(connSynAck8->userTimeOut);
+SwapBytes(connSynAck8->aliveDelay);
+#endif
+
+rnd = connSynAck8->rnd;
+userTimeout = connSynAck8->userTimeOut;
+aliveTimeout = connSynAck8->aliveDelay;
+
+for (int i = 0; i < DIR_NUM; i++)
+ {
+ dirNames.push_back((const char*)connSynAck8->dirName[i]);
+ }
+
+if (pDirNameCb != NULL)
+ pDirNameCb(dirNames, dirNameCbData);
+
+NetSend(CONN_ACK_N);
+phase = 3;
+phaseTime = GetTickCount();
+
+return CONN_SYN_ACK_N;
+}
+//---------------------------------------------------------------------------
+int IA_CLIENT_PROT::Process_ALIVE_SYN_8(const char * buffer)
+{
+aliveSyn8 = (ALIVE_SYN_8*)buffer;
+
+#ifdef ARCH_BE
+SwapBytes(aliveSyn8->len);
+SwapBytes(aliveSyn8->rnd);
+SwapBytes(aliveSyn8->cash);
+SwapBytes(aliveSyn8->status);
+for (int i = 0; i < DIR_NUM; ++i)
+ {
+ SwapBytes(aliveSyn8->mu[i]);
+ SwapBytes(aliveSyn8->md[i]);
+ SwapBytes(aliveSyn8->su[i]);
+ SwapBytes(aliveSyn8->sd[i]);
+ }
+#endif
+
+rnd = aliveSyn8->rnd;
+memcpy(&stat, (char*)aliveSyn8->mu, sizeof(stat));
+
+if (pStatChangedCb != NULL)
+ pStatChangedCb(stat, statChangedCbData);
+
+if (pStatusChangedCb != NULL)
+ pStatusChangedCb(1, statusChangedCbData);
+NetSend(ALIVE_ACK_N);
+phaseTime = GetTickCount();
+
+return ALIVE_SYN_N;
+}
+//---------------------------------------------------------------------------
+int IA_CLIENT_PROT::Process_DISCONN_SYN_ACK_8(const char * buffer)
+{
+disconnSynAck8 = (DISCONN_SYN_ACK_8*)buffer;
+
+#ifdef ARCH_BE
+SwapBytes(disconnSynAck8->len);
+SwapBytes(disconnSynAck8->rnd);
+#endif
+
+rnd = disconnSynAck8->rnd;
+
+NetSend(DISCONN_ACK_N);
+phase = 5;
+phaseTime = GetTickCount();
+
+return DISCONN_SYN_ACK_N;
+}
+//---------------------------------------------------------------------------
+int IA_CLIENT_PROT::Process_FIN_8(const char *)
+{
+phase = 1;
+phaseTime = GetTickCount();
+if (pStatusChangedCb != NULL)
+ pStatusChangedCb(0, statusChangedCbData);
+
+return FIN_N;
+}
+//---------------------------------------------------------------------------
+int IA_CLIENT_PROT::Process_INFO_8(const char * buffer)
+{
+info = (INFO_8*)buffer;
+
+#ifdef ARCH_BE
+SwapBytes(info->len);
+SwapBytes(info->sendTime);
+#endif
+
+if (pInfoCb != NULL)
+ pInfoCb((char*)info->text, info->infoType, info->showTime, info->sendTime, infoCbData);
+return INFO_8_N;
+}
+//---------------------------------------------------------------------------
+int IA_CLIENT_PROT::Process_ERROR(const char * buffer)
+{
+memcpy(&err, buffer, sizeof(err));
+
+#ifdef ARCH_BE
+SwapBytes(err.len);
+#endif
+
+KOIToWin((const char*)err.text, &messageText);
+if (pErrorCb != NULL)
+ pErrorCb(messageText, IA_SERVER_ERROR, errorCbData);
+phase = 1;
+phaseTime = GetTickCount();
+codeError = IA_SERVER_ERROR;
+
+return ERROR_N;
+}
+//---------------------------------------------------------------------------
+int IA_CLIENT_PROT::Prepare_CONN_SYN_8(char * buffer)
+{
+connSyn8 = (CONN_SYN_8*)buffer;
+
+#ifdef ARCH_BE
+SwapBytes(connSyn8->len);
+#endif
+
+connSyn8->len = sizeof(CONN_SYN_8);
+#ifdef IA_DEBUGPROTO
+if (sizeof(CONN_SYN_8) != Min8(sizeof(CONN_SYN_8)))
+ {
+ int * a = NULL;
+ *a = 0;
+ }
+#endif
+
+strncpy((char*)connSyn8->type, "CONN_SYN", IA_MAX_TYPE_LEN);
+strncpy((char*)connSyn8->login, login.c_str(), IA_LOGIN_LEN);
+connSyn8->dirs = 0;
+for (int i = 0; i < DIR_NUM; i++)
+ {
+ connSyn8->dirs |= (selectedDirs[i] << i);
+ }
+return connSyn8->len;
+}
+//---------------------------------------------------------------------------
+int IA_CLIENT_PROT::Prepare_CONN_ACK_8(char * buffer)
+{
+connAck8 = (CONN_ACK_8*)buffer;
+
+#ifdef ARCH_BE
+SwapBytes(connAck8->len);
+SwapBytes(connAck8->rnd);
+#endif
+
+#ifdef IA_DEBUGPROTO
+if (sizeof(CONN_ACK_8) != Min8(sizeof(CONN_ACK_8)))
+ {
+ int * a = NULL;
+ *a = 0;
+ }
+#endif
+
+connAck8->len = sizeof(CONN_ACK_8);
+strncpy((char*)connAck8->loginS, login.c_str(), IA_LOGIN_LEN);
+strncpy((char*)connAck8->type, "CONN_ACK", IA_MAX_TYPE_LEN);
+rnd++;
+connAck8->rnd = rnd;
+
+return connAck8->len;
+}
+//---------------------------------------------------------------------------
+int IA_CLIENT_PROT::Prepare_ALIVE_ACK_8(char * buffer)
+{
+aliveAck8 = (ALIVE_ACK_8*)buffer;
+
+#ifdef ARCH_BE
+SwapBytes(aliveAck8->len);
+SwapBytes(aliveAck8->rnd);
+#endif
+
+#ifdef IA_DEBUGPROTO
+if (Min8(sizeof(ALIVE_ACK_8)) != sizeof(ALIVE_ACK_8))
+ {
+ int * a = NULL;
+ *a = 0;
+ }
+#endif
+
+aliveAck8 = (ALIVE_ACK_8*)buffer;
+aliveAck8->len = sizeof(ALIVE_ACK_8);
+strncpy((char*)aliveAck8->loginS, login.c_str(), IA_LOGIN_LEN);
+strncpy((char*)aliveAck8->type, "ALIVE_ACK", IA_MAX_TYPE_LEN);
+aliveAck8->rnd = ++rnd;
+return aliveAck8->len;
+}
+//---------------------------------------------------------------------------
+int IA_CLIENT_PROT::Prepare_DISCONN_SYN_8(char * buffer)
+{
+disconnSyn8 = (DISCONN_SYN_8*)buffer;
+
+#ifdef ARCH_BE
+SwapBytes(disconnSyn8->len);
+#endif
+
+#ifdef IA_DEBUGPROTO
+if (Min8(sizeof(DISCONN_SYN_8)) != sizeof(DISCONN_SYN_8))
+ {
+ int * a = NULL;
+ *a = 0;
+ }
+#endif
+
+disconnSyn8->len = sizeof(DISCONN_SYN_8);
+strncpy((char*)disconnSyn8->loginS, login.c_str(), IA_LOGIN_LEN);
+strncpy((char*)disconnSyn8->type, "DISCONN_SYN", IA_MAX_TYPE_LEN);
+strncpy((char*)disconnSyn8->login, login.c_str(), IA_LOGIN_LEN);
+return disconnSyn8->len;
+}
+//---------------------------------------------------------------------------
+int IA_CLIENT_PROT::Prepare_DISCONN_ACK_8(char * buffer)
+{
+disconnAck8 = (DISCONN_ACK_8*)buffer;
+
+#ifdef ARCH_BE
+SwapBytes(disconnAck8->len);
+SwapBytes(disconnAck8->rnd);
+#endif
+
+#ifdef IA_DEBUGPROTO
+if (Min8(sizeof(DISCONN_ACK_8)) != sizeof(DISCONN_ACK_8))
+ {
+ int * a = NULL;
+ *a = 0;
+ }
+#endif
+
+disconnAck8->len = Min8(sizeof(DISCONN_ACK_8));
+disconnAck8->rnd = rnd + 1;
+strncpy((char*)disconnAck8->loginS, login.c_str(), IA_LOGIN_LEN);
+strncpy((char*)disconnAck8->type, "DISCONN_ACK", IA_MAX_TYPE_LEN);
+return disconnAck8->len;
+}
+//---------------------------------------------------------------------------
+void IA_CLIENT_PROT::SetStatusChangedCb(tpStatusChangedCb p, void * data)
+{
+pStatusChangedCb = p;
+statusChangedCbData = data;
+}
+//---------------------------------------------------------------------------
+void IA_CLIENT_PROT::SetStatChangedCb(tpStatChangedCb p, void * data)
+{
+pStatChangedCb = p;
+statChangedCbData = data;
+}
+//---------------------------------------------------------------------------
+void IA_CLIENT_PROT::SetInfoCb(tpCallBackInfoFn p, void * data)
+{
+pInfoCb = p;
+infoCbData = data;
+}
+//---------------------------------------------------------------------------
+void IA_CLIENT_PROT::SetDirNameCb(tpCallBackDirNameFn p, void * data)
+{
+pDirNameCb = p;
+dirNameCbData = data;
+}
+//---------------------------------------------------------------------------
+void IA_CLIENT_PROT::SetErrorCb(tpCallBackErrorFn p, void * data)
+{
+pErrorCb = p;
+errorCbData = data;
+}
+//---------------------------------------------------------------------------
--- /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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+ $Author: faust $
+ $Revision: 1.10 $
+ $Date: 2010/03/15 12:57:24 $
+*/
+
+/*
+* Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+*/
+//---------------------------------------------------------------------------
+#ifndef IA_AUTH_C_H
+#define IA_AUTH_C_H
+
+#ifndef WIN32
+#include <netinet/in.h>
+#include <pthread.h>
+#else
+#include <winsock2.h>
+#endif
+
+#include <string>
+#include <vector>
+#include <map>
+
+#include "blowfish.h"
+#include "ia_packets.h"
+
+#define IA_BIND_ERROR (1)
+#define IA_SERVER_ERROR (2)
+#define IA_FCNTL_ERROR (3)
+#define IA_GETHOSTBYNAME_ERROR (4)
+
+#define IA_PROTO_VER (8)
+#define IA_PROTO_PROXY_VER (101)
+
+using namespace std;
+
+typedef void (*tpStatusChangedCb)(int status, void * data);
+typedef void (*tpStatChangedCb)(const LOADSTAT & stat, void * data);
+typedef void (*tpCallBackInfoFn)(const string & message, int infoType, int showTime, int sendTime, void * data);
+typedef void (*tpCallBackErrorFn)(const string & message, int netError, void * data);
+typedef void (*tpCallBackDirNameFn)(const vector<string> & dirName, void * data);
+
+//---------------------------------------------------------------------------
+class IA_CLIENT_PROT
+{
+#ifdef WIN32
+friend unsigned long WINAPI RunW(void * data);
+#else
+friend void * RunL(void * data);
+#endif
+
+public:
+ IA_CLIENT_PROT(const string & sn, uint16_t p, uint16_t localPort = 0);
+ ~IA_CLIENT_PROT();
+
+ void Start();
+ void Stop();
+ void GetStat(LOADSTAT * ls);
+
+ void SetServer(const string & sn, unsigned short port);
+ void SetLogin(const string & login);
+ void SetPassword(const string & password);
+ void SetEnabledDirs(const bool * selectedDirs);
+
+ void SetStatusChangedCb(tpStatusChangedCb p, void * data);
+ void SetStatChangedCb(tpStatChangedCb p, void * data);
+ void SetInfoCb(tpCallBackInfoFn p, void * data);
+ void SetErrorCb(tpCallBackErrorFn p, void * data);
+ void SetDirNameCb(tpCallBackDirNameFn p, void * data);
+
+ int Connect();
+ int Disconnect();
+ int GetAuthorized() const { return phase == 3 || phase == 4; }; // Ìû ïîäêëþ÷åíû èëè íåò?
+ int GetPhase() const { return phase; };
+ int GetStatus() const;
+ int GetReconnect() const { return reconnect; };
+ void SetReconnect(int r) { reconnect = r; };
+ char GetProtoVer() const { return proxyMode ? IA_PROTO_PROXY_VER : IA_PROTO_VER; };
+ void GetMessageText(string * text) const { *text = messageText; };
+ void GetInfoText(string * text) const { *text = infoText; };
+ int GetStrError(string * error) const;
+
+ void SetProxyMode(bool on) { proxyMode = on; };
+ bool GetProxyMode() const { return proxyMode; };
+
+ void SetIP(uint32_t ip) { IA_CLIENT_PROT::ip = ip; };
+ uint32_t GetIP() const { return ip; };
+
+private:
+ void Run();
+ int NetRecv();
+ int NetSend(int n);
+ bool GetNonstop() const { return nonstop; };
+ void PrepareNet();
+ int DeterminatePacketType(const char * buffer);
+
+ int Process_CONN_SYN_ACK_8(const char * buffer);
+ int Process_ALIVE_SYN_8(const char * buffer);
+ int Process_DISCONN_SYN_ACK_8(const char * buffer);
+ int Process_FIN_8(const char * buffer);
+ int Process_INFO_8(const char * buffer);
+ int Process_ERROR(const char * buffer);
+
+ int Prepare_CONN_SYN_8(char * buffer);
+ int Prepare_CONN_ACK_8(char * buffer);
+ int Prepare_ALIVE_ACK_8(char * buffer);
+ int Prepare_DISCONN_SYN_8(char * buffer);
+ int Prepare_DISCONN_ACK_8(char * buffer);
+
+ void FillHdr8(char * buffer, unsigned long ip);
+ int Send(char * buffer, int len);
+ int Recv(char * buffer, int len);
+
+ LOADSTAT stat;
+ int action;
+ int phase;
+ int phaseTime; // Âðåìÿ âõîäà â ôàçó
+ string messageText; // Ñîîáùåíèå îá îøèáêå
+ string infoText;
+ mutable string strError;
+ mutable int codeError;
+ bool nonstop;
+ bool isNetPrepared;
+ bool proxyMode;
+
+ BLOWFISH_CTX ctxPass;
+ BLOWFISH_CTX ctxHdr;
+
+ bool selectedDirs[DIR_NUM];
+
+ string password;
+ string login;
+
+ #ifdef WIN32
+ WSADATA wsaData;
+ #else
+ pthread_t thread;
+ #endif
+
+ string serverName; // Èìÿ ñåðâåðà
+ uint16_t port; // Ïîðò ñåðâåðà
+ uint32_t ip; // Proxy IP
+ uint32_t localPort;
+
+ struct sockaddr_in localAddrS; // Íàø àäðåñ
+ struct sockaddr_in localAddrR; // Íàø àäðåñ
+ struct sockaddr_in servAddr; // àäðåñ ñåðâåðà
+
+ bool firstConnect;
+ int reconnect;
+ int sockr;
+ int protNum; // ×èñëî, êîòîðîå ó÷àñòâóåò â îáìåíå ñîîáùåíèÿìèa
+ int userTimeout;
+ int aliveTimeout;
+ unsigned int rnd;
+
+ tpStatusChangedCb pStatusChangedCb;
+ tpStatChangedCb pStatChangedCb;
+ tpCallBackInfoFn pInfoCb;
+ tpCallBackErrorFn pErrorCb;
+ tpCallBackDirNameFn pDirNameCb;
+
+ void * statusChangedCbData;
+ void * statChangedCbData;
+ void * infoCbData;
+ void * errorCbData;
+ void * dirNameCbData;
+
+ map<string, int> packetTypes;
+
+ CONN_SYN_8 * connSyn8;
+ CONN_SYN_ACK_8 * connSynAck8;
+ CONN_ACK_8 * connAck8;
+ ALIVE_SYN_8 * aliveSyn8;
+ ALIVE_ACK_8 * aliveAck8;
+ DISCONN_SYN_8 * disconnSyn8;
+ DISCONN_SYN_ACK_8 * disconnSynAck8;
+ DISCONN_ACK_8 * disconnAck8;
+ ERR_8 err;
+ INFO_8 * info;
+};
+//---------------------------------------------------------------------------
+#ifdef WIN32
+unsigned long WINAPI RunW(void *);
+#else
+void * RunW(void *);
+#endif
+
+//---------------------------------------------------------------------------
+#endif //IA_AUTH_C_H
+
+
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.6 2009/03/03 15:50:15 faust Exp $
+###############################################################################
+
+LIB_NAME = ibpp
+PROG = lib$(LIB_NAME)
+
+SRCS = array.cpp \
+ blob.cpp \
+ database.cpp \
+ date.cpp \
+ dbkey.cpp \
+ _dpb.cpp \
+ events.cpp \
+ exception.cpp \
+ _ibpp.cpp \
+ _ibs.cpp \
+ _rb.cpp \
+ row.cpp \
+ service.cpp \
+ _spb.cpp \
+ statement.cpp \
+ time.cpp \
+ _tpb.cpp \
+ transaction.cpp \
+ user.cpp
+
+INCS = ibpp.h
+
+ADD_CXXFLAGS_1 = -DIBPP_LINUX
+
+LIBS = -lfbclient
+
+include ../Makefile.in
+
+
+
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: _dpb.cpp,v 1.2 2009/03/19 20:00:27 faust Exp $\r
+// Subject : IBPP, internal DPB class implementation\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * DPB == Database Parameter Block/Buffer, see Interbase 6.0 C-API\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning(disable: 4786 4996)\r
+#ifndef _DEBUG\r
+#pragma warning(disable: 4702)\r
+#endif\r
+#endif\r
+\r
+#include "_ibpp.h"\r
+\r
+#ifdef HAS_HDRSTOP\r
+#pragma hdrstop\r
+#endif\r
+\r
+#include <cstring>\r
+\r
+using namespace ibpp_internals;\r
+\r
+const int DPB::BUFFERINCR = 128;\r
+\r
+void DPB::Grow(int needed)\r
+{\r
+ if (mBuffer == 0) ++needed; // Initial alloc will require one more byte\r
+ if ((mSize + needed) > mAlloc)\r
+ {\r
+ // We need to grow the buffer. We use increments of BUFFERINCR bytes.\r
+ needed = (needed / BUFFERINCR + 1) * BUFFERINCR;\r
+ char* newbuffer = new char[mAlloc + needed];\r
+ if (mBuffer == 0)\r
+ {\r
+ // Initial allocation, initialize the version tag\r
+ newbuffer[0] = isc_dpb_version1;\r
+ mSize = 1;\r
+ }\r
+ else\r
+ {\r
+ // Move the old buffer content to the new one\r
+ memcpy(newbuffer, mBuffer, mSize);\r
+ delete [] mBuffer;\r
+ }\r
+ mBuffer = newbuffer;\r
+ mAlloc += needed;\r
+ }\r
+}\r
+\r
+void DPB::Insert(char type, const char* data)\r
+{\r
+ int len = (int)strlen(data);\r
+ Grow(len + 2);\r
+ mBuffer[mSize++] = type;\r
+ mBuffer[mSize++] = char(len);\r
+ strncpy(&mBuffer[mSize], data, len);\r
+ mSize += len;\r
+}\r
+\r
+void DPB::Insert(char type, int16_t data)\r
+{\r
+ Grow(2 + 2);\r
+ mBuffer[mSize++] = type;\r
+ mBuffer[mSize++] = char(2);\r
+ *(int16_t*)&mBuffer[mSize] = int16_t((*gds.Call()->m_vax_integer)((char*)&data, 2));\r
+ mSize += 2;\r
+}\r
+\r
+void DPB::Insert(char type, bool data)\r
+{\r
+ Grow(2 + 1);\r
+ mBuffer[mSize++] = type;\r
+ mBuffer[mSize++] = char(1);\r
+ mBuffer[mSize++] = char(data ? 1 : 0);\r
+}\r
+\r
+void DPB::Insert(char type, char data)\r
+{\r
+ Grow(2 + 1);\r
+ mBuffer[mSize++] = type;\r
+ mBuffer[mSize++] = char(1);\r
+ mBuffer[mSize++] = data;\r
+}\r
+\r
+void DPB::Reset()\r
+{\r
+ if (mAlloc != 0)\r
+ {\r
+ delete [] mBuffer;\r
+ mBuffer = 0;\r
+ mSize = 0;\r
+ mAlloc = 0;\r
+ }\r
+}\r
+\r
+//\r
+// EOF\r
+//\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: _ibpp.cpp,v 1.3 2009/03/19 20:00:27 faust Exp $\r
+// Subject : IBPP, Initialization of the library\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning(disable: 4786 4996)\r
+#ifndef _DEBUG\r
+#pragma warning(disable: 4702)\r
+#endif\r
+#endif\r
+\r
+#include "_ibpp.h"\r
+\r
+#ifdef HAS_HDRSTOP\r
+#pragma hdrstop\r
+#endif\r
+\r
+#include <limits>\r
+\r
+#ifdef IBPP_WINDOWS\r
+// New (optional) Registry Keys introduced by Firebird Server 1.5\r
+#define REG_KEY_ROOT_INSTANCES "SOFTWARE\\Firebird Project\\Firebird Server\\Instances"\r
+#define FB_DEFAULT_INSTANCE "DefaultInstance"\r
+#endif\r
+\r
+namespace ibpp_internals\r
+{\r
+ const double consts::dscales[19] = {\r
+ 1, 1E1, 1E2, 1E3, 1E4, 1E5, 1E6, 1E7, 1E8,\r
+ 1E9, 1E10, 1E11, 1E12, 1E13, 1E14, 1E15,\r
+ 1E16, 1E17, 1E18 };\r
+\r
+ const int consts::Dec31_1899 = 693595;\r
+\r
+// Many compilers confuses those following min/max with macros min and max !\r
+#undef min\r
+#undef max\r
+\r
+#ifdef __DMC__ // Needs to break-down the declaration else compiler crash (!)\r
+ const std::numeric_limits<int16_t> i16_limits;\r
+ const std::numeric_limits<int32_t> i32_limits;\r
+ const int16_t consts::min16 = i16_limits.min();\r
+ const int16_t consts::max16 = i16_limits.max();\r
+ const int32_t consts::min32 = i32_limits.min();\r
+ const int32_t consts::max32 = i32_limits.max();\r
+#else\r
+ const int16_t consts::min16 = std::numeric_limits<int16_t>::min();\r
+ const int16_t consts::max16 = std::numeric_limits<int16_t>::max();\r
+ const int32_t consts::min32 = std::numeric_limits<int32_t>::min();\r
+ const int32_t consts::max32 = std::numeric_limits<int32_t>::max();\r
+#endif\r
+\r
+ GDS gds; // Global unique GDS instance\r
+\r
+#ifdef IBPP_WINDOWS\r
+ std::string AppPath; // Used by GDS::Call() below\r
+#endif\r
+\r
+#ifdef _DEBUG\r
+ std::ostream& operator<< (std::ostream& a, flush_debug_stream_type)\r
+ {\r
+ if (std::stringstream* p = dynamic_cast<std::stringstream*>(&a))\r
+ {\r
+#ifdef IBPP_WINDOWS\r
+ ::OutputDebugString(("IBPP: " + p->str() + "\n").c_str());\r
+#endif\r
+ p->str("");\r
+ }\r
+ return a;\r
+ }\r
+#endif // _DEBUG\r
+\r
+}\r
+\r
+using namespace ibpp_internals;\r
+\r
+GDS* GDS::Call()\r
+{\r
+ // Let's load the CLIENT library, if it is not already loaded.\r
+ // The load is guaranteed to be done only once per application.\r
+\r
+ if (! mReady)\r
+ {\r
+#ifdef IBPP_WINDOWS\r
+\r
+ // Let's load the FBCLIENT.DLL or GDS32.DLL, we will never release it.\r
+ // Windows will do that for us when the executable will terminate.\r
+\r
+ char fbdll[MAX_PATH];\r
+ HKEY hkey_instances;\r
+\r
+ // Try to load FBCLIENT.DLL from each of the additional optional paths\r
+ // that may have been specified through ClientLibSearchPaths().\r
+ // We also want to actually update the environment PATH so that it references\r
+ // the specific path from where we attempt the load. This is useful because\r
+ // it directs the system to attempt finding dependencies (like the C/C++\r
+ // runtime libraries) from the same location where FBCLIENT is found.\r
+\r
+ mHandle = 0;\r
+\r
+ std::string SysPath(getenv("PATH"));\r
+ std::string::size_type pos = 0;\r
+ while (pos < mSearchPaths.size())\r
+ {\r
+ std::string::size_type newpos = mSearchPaths.find(';', pos);\r
+\r
+ std::string path;\r
+ if (newpos == std::string::npos) path = mSearchPaths.substr(pos);\r
+ else path = mSearchPaths.substr(pos, newpos-pos);\r
+\r
+ if (path.size() >= 1)\r
+ {\r
+ if (path[path.size()-1] != '\\') path += '\\';\r
+\r
+ AppPath.assign("PATH=");\r
+ AppPath.append(path).append(";").append(SysPath);\r
+ putenv(AppPath.c_str());\r
+\r
+ path.append("fbclient.dll");\r
+ mHandle = LoadLibrary(path.c_str());\r
+ if (mHandle != 0 || newpos == std::string::npos) break;\r
+ }\r
+ pos = newpos + 1;\r
+ }\r
+\r
+ if (mHandle == 0)\r
+ {\r
+ // Try to load FBCLIENT.DLL from the current application location. This\r
+ // is a usefull step for applications using the embedded version of FB\r
+ // or a local copy (for whatever reasons) of the dll.\r
+\r
+ if (! AppPath.empty())\r
+ {\r
+ // Restores the original system path\r
+ AppPath.assign("PATH=");\r
+ AppPath.append(SysPath);\r
+ putenv(AppPath.c_str());\r
+ }\r
+\r
+ int len = GetModuleFileName(NULL, fbdll, sizeof(fbdll));\r
+ if (len != 0)\r
+ {\r
+ // Get to the last '\' (this one precedes the filename part).\r
+ // There is always one after a success call to GetModuleFileName().\r
+ char* p = fbdll + len;\r
+ do {--p;} while (*p != '\\');\r
+ *p = '\0';\r
+ lstrcat(fbdll, "\\fbembed.dll");// Local copy could be named fbembed.dll\r
+ mHandle = LoadLibrary(fbdll);\r
+ if (mHandle == 0)\r
+ {\r
+ *p = '\0';\r
+ lstrcat(fbdll, "\\fbclient.dll"); // Or possibly renamed fbclient.dll\r
+ mHandle = LoadLibrary(fbdll);\r
+ }\r
+ }\r
+ }\r
+\r
+ if (mHandle == 0)\r
+ {\r
+ // Try to locate FBCLIENT.DLL through the optional FB registry key.\r
+\r
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_KEY_ROOT_INSTANCES, 0,\r
+ KEY_READ, &hkey_instances) == ERROR_SUCCESS)\r
+ {\r
+ DWORD keytype;\r
+ DWORD buflen = sizeof(fbdll);\r
+ if (RegQueryValueEx(hkey_instances, FB_DEFAULT_INSTANCE, 0,\r
+ &keytype, reinterpret_cast<UCHAR*>(fbdll),\r
+ &buflen) == ERROR_SUCCESS && keytype == REG_SZ)\r
+ {\r
+ lstrcat(fbdll, "bin\\fbclient.dll");\r
+ mHandle = LoadLibrary(fbdll);\r
+ }\r
+ RegCloseKey(hkey_instances);\r
+ }\r
+ }\r
+\r
+ if (mHandle == 0)\r
+ {\r
+ // Let's try from the PATH and System directories\r
+ mHandle = LoadLibrary("fbclient.dll");\r
+ if (mHandle == 0)\r
+ {\r
+ // Not found. Last try : attemps loading gds32.dll from PATH and\r
+ // System directories\r
+ mHandle = LoadLibrary("gds32.dll");\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("GDS::Call()",\r
+ _("Can't find or load FBCLIENT.DLL or GDS32.DLL"));\r
+ }\r
+ }\r
+#endif\r
+\r
+ mGDSVersion = 60;\r
+\r
+ // Get the entry points that we need\r
+\r
+#ifdef IBPP_WINDOWS\r
+#define IB_ENTRYPOINT(X) \\r
+ if ((m_##X = (proto_##X*)GetProcAddress(mHandle, "isc_"#X)) == 0) \\r
+ throw LogicExceptionImpl("GDS:gds()", _("Entry-point isc_"#X" not found"))\r
+#endif\r
+#ifdef IBPP_UNIX\r
+/* TODO : perform a late-bind on unix --- not so important, well I think (OM) */\r
+#define IB_ENTRYPOINT(X) m_##X = (proto_##X*)isc_##X\r
+#endif\r
+\r
+ IB_ENTRYPOINT(create_database);\r
+ IB_ENTRYPOINT(attach_database);\r
+ IB_ENTRYPOINT(detach_database);\r
+ IB_ENTRYPOINT(drop_database);\r
+ IB_ENTRYPOINT(database_info);\r
+ IB_ENTRYPOINT(open_blob2);\r
+ IB_ENTRYPOINT(create_blob2);\r
+ IB_ENTRYPOINT(close_blob);\r
+ IB_ENTRYPOINT(cancel_blob);\r
+ IB_ENTRYPOINT(get_segment);\r
+ IB_ENTRYPOINT(put_segment);\r
+ IB_ENTRYPOINT(blob_info);\r
+ IB_ENTRYPOINT(array_lookup_bounds);\r
+ IB_ENTRYPOINT(array_get_slice);\r
+ IB_ENTRYPOINT(array_put_slice);\r
+ IB_ENTRYPOINT(vax_integer);\r
+ IB_ENTRYPOINT(sqlcode);\r
+ IB_ENTRYPOINT(sql_interprete);\r
+ IB_ENTRYPOINT(interprete);\r
+ IB_ENTRYPOINT(que_events);\r
+ IB_ENTRYPOINT(cancel_events);\r
+ IB_ENTRYPOINT(start_multiple);\r
+ IB_ENTRYPOINT(commit_transaction);\r
+ IB_ENTRYPOINT(commit_retaining);\r
+ IB_ENTRYPOINT(rollback_transaction);\r
+ IB_ENTRYPOINT(rollback_retaining);\r
+ IB_ENTRYPOINT(dsql_execute_immediate);\r
+ IB_ENTRYPOINT(dsql_allocate_statement);\r
+ IB_ENTRYPOINT(dsql_describe);\r
+ IB_ENTRYPOINT(dsql_describe_bind);\r
+ IB_ENTRYPOINT(dsql_prepare);\r
+ IB_ENTRYPOINT(dsql_execute);\r
+ IB_ENTRYPOINT(dsql_execute2);\r
+ IB_ENTRYPOINT(dsql_fetch);\r
+ IB_ENTRYPOINT(dsql_free_statement);\r
+ IB_ENTRYPOINT(dsql_set_cursor_name);\r
+ IB_ENTRYPOINT(dsql_sql_info);\r
+\r
+ IB_ENTRYPOINT(service_attach);\r
+ IB_ENTRYPOINT(service_detach);\r
+ IB_ENTRYPOINT(service_start);\r
+ IB_ENTRYPOINT(service_query);\r
+\r
+ mReady = true;\r
+ }\r
+\r
+ return this;\r
+}\r
+\r
+namespace IBPP\r
+{\r
+\r
+ bool CheckVersion(uint32_t AppVersion)\r
+ {\r
+ //(void)gds.Call(); // Just call it to trigger the initialization\r
+ return (AppVersion & 0xFFFFFF00) ==\r
+ (IBPP::Version & 0xFFFFFF00) ? true : false;\r
+ }\r
+\r
+ int GDSVersion()\r
+ {\r
+ return gds.Call()->mGDSVersion;\r
+ }\r
+\r
+#ifdef IBPP_WINDOWS\r
+ void ClientLibSearchPaths(const std::string& paths)\r
+ {\r
+ gds.mSearchPaths.assign(paths);\r
+ }\r
+#else\r
+ void ClientLibSearchPaths(const std::string&)\r
+ {\r
+ }\r
+#endif\r
+\r
+ // Factories for our Interface objects\r
+\r
+ Service ServiceFactory(const std::string& ServerName,\r
+ const std::string& UserName, const std::string& UserPassword)\r
+ {\r
+ (void)gds.Call(); // Triggers the initialization, if needed\r
+ return new ServiceImpl(ServerName, UserName, UserPassword);\r
+ }\r
+\r
+ Database DatabaseFactory(const std::string& ServerName,\r
+ const std::string& DatabaseName, const std::string& UserName,\r
+ const std::string& UserPassword, const std::string& RoleName,\r
+ const std::string& CharSet, const std::string& CreateParams)\r
+ {\r
+ (void)gds.Call(); // Triggers the initialization, if needed\r
+ return new DatabaseImpl(ServerName, DatabaseName, UserName,\r
+ UserPassword, RoleName, CharSet, CreateParams);\r
+ }\r
+\r
+ Transaction TransactionFactory(Database db, TAM am,\r
+ TIL il, TLR lr, TFF flags)\r
+ {\r
+ (void)gds.Call(); // Triggers the initialization, if needed\r
+ return new TransactionImpl( dynamic_cast<DatabaseImpl*>(db.intf()),\r
+ am, il, lr, flags);\r
+ }\r
+\r
+ Statement StatementFactory(Database db, Transaction tr,\r
+ const std::string& sql)\r
+ {\r
+ (void)gds.Call(); // Triggers the initialization, if needed\r
+ return new StatementImpl( dynamic_cast<DatabaseImpl*>(db.intf()),\r
+ dynamic_cast<TransactionImpl*>(tr.intf()),\r
+ sql);\r
+ }\r
+\r
+ Blob BlobFactory(Database db, Transaction tr)\r
+ {\r
+ (void)gds.Call(); // Triggers the initialization, if needed\r
+ return new BlobImpl(dynamic_cast<DatabaseImpl*>(db.intf()),\r
+ dynamic_cast<TransactionImpl*>(tr.intf()));\r
+ }\r
+\r
+ Array ArrayFactory(Database db, Transaction tr)\r
+ {\r
+ (void)gds.Call(); // Triggers the initialization, if needed\r
+ return new ArrayImpl(dynamic_cast<DatabaseImpl*>(db.intf()),\r
+ dynamic_cast<TransactionImpl*>(tr.intf()));\r
+ }\r
+\r
+ Events EventsFactory(Database db)\r
+ {\r
+ (void)gds.Call(); // Triggers the initialization, if needed\r
+ return new EventsImpl(dynamic_cast<DatabaseImpl*>(db.intf()));\r
+ }\r
+\r
+}\r
+\r
+//\r
+// EOF\r
+//\r
+\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: _ibpp.h,v 1.2 2007/05/17 08:37:05 faust Exp $\r
+// Subject : IBPP internal declarations\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+//\r
+// * 'Internal declarations' means everything used to implement ibpp. This\r
+// file and its contents is NOT needed by users of the library. All those\r
+// declarations are wrapped in a namespace : 'ibpp_internals'.\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifndef __INTERNAL_IBPP_H__\r
+#define __INTERNAL_IBPP_H__\r
+\r
+#include "ibpp.h"\r
+\r
+#if defined(__BCPLUSPLUS__) || defined(_MSC_VER) || defined(__DMC__)\r
+#define HAS_HDRSTOP\r
+#endif\r
+\r
+#if (defined(__GNUC__) && defined(IBPP_WINDOWS))\r
+// Setting flags for ibase.h -- using GCC/Cygwin/MinGW on Win32\r
+#ifndef _MSC_VER\r
+#define _MSC_VER 1299\r
+#endif\r
+#ifndef _WIN32\r
+#define _WIN32 1\r
+#endif\r
+#endif\r
+\r
+#include "ibase.h" // From Firebird 1.x or InterBase 6.x installation\r
+\r
+#if (defined(__GNUC__) && defined(IBPP_WINDOWS))\r
+// UNSETTING flags used above for ibase.h -- Huge conflicts with libstdc++ !\r
+#undef _MSC_VER\r
+#undef _WIN32\r
+#endif\r
+\r
+#ifdef IBPP_WINDOWS\r
+#include <windows.h>\r
+#endif\r
+\r
+//#include <limits>\r
+#include <string>\r
+#include <vector>\r
+#include <sstream>\r
+#include <cstdarg>\r
+\r
+#ifdef _DEBUG\r
+#define ASSERTION(x) {if (!(x)) {throw LogicExceptionImpl("ASSERTION", \\r
+ "'"#x"' is not verified at %s, line %d", \\r
+ __FILE__, __LINE__);}}\r
+#else\r
+#define ASSERTION(x) /* x */\r
+#endif\r
+\r
+// Fix to famous MSVC 6 variable scope bug\r
+#if defined(_MSC_VER) && (_MSC_VER < 1300) // MSVC 6 should be < 1300\r
+#define for if(true)for\r
+#endif\r
+\r
+namespace ibpp_internals\r
+{\r
+\r
+enum flush_debug_stream_type {fds};\r
+\r
+#ifdef _DEBUG\r
+\r
+struct DebugStream : public std::stringstream\r
+{\r
+ // next two operators fix some g++ and vc++ related problems\r
+ std::ostream& operator<< (const char* p)\r
+ { static_cast<std::stringstream&>(*this)<< p; return *this; }\r
+\r
+ std::ostream& operator<< (const std::string& p)\r
+ { static_cast<std::stringstream&>(*this)<< p; return *this; }\r
+\r
+ DebugStream& operator=(const DebugStream&) {return *this;}\r
+ DebugStream(const DebugStream&) {}\r
+ DebugStream() {}\r
+};\r
+std::ostream& operator<< (std::ostream& a, flush_debug_stream_type);\r
+\r
+#else\r
+\r
+struct DebugStream\r
+{\r
+ template<class T> DebugStream& operator<< (const T&) { return *this; }\r
+ // for manipulators\r
+ DebugStream& operator<< (std::ostream&(*)(std::ostream&)) { return *this; }\r
+};\r
+\r
+#endif // _DEBUG\r
+\r
+class DatabaseImpl;\r
+class TransactionImpl;\r
+class StatementImpl;\r
+class BlobImpl;\r
+class ArrayImpl;\r
+class EventsImpl;\r
+\r
+// Native data types\r
+typedef enum {ivArray, ivBlob, ivDate, ivTime, ivTimestamp, ivString,\r
+ ivInt16, ivInt32, ivInt64, ivFloat, ivDouble,\r
+ ivBool, ivDBKey, ivByte} IITYPE;\r
+\r
+//\r
+// Those are the Interbase C API prototypes that we use\r
+// Taken 'asis' from IBASE.H, prefix 'isc_' replaced with 'proto_',\r
+// and 'typedef' preprended...\r
+//\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_create_database (ISC_STATUS *,\r
+ short,\r
+ char *,\r
+ isc_db_handle *,\r
+ short,\r
+ char *,\r
+ short);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_attach_database (ISC_STATUS *,\r
+ short,\r
+ char *,\r
+ isc_db_handle *,\r
+ short,\r
+ char *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_detach_database (ISC_STATUS *,\r
+ isc_db_handle *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_drop_database (ISC_STATUS *,\r
+ isc_db_handle *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_database_info (ISC_STATUS *,\r
+ isc_db_handle *,\r
+ short,\r
+ char *,\r
+ short,\r
+ char *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_dsql_execute_immediate (ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_open_blob2 (ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ isc_blob_handle *,\r
+ ISC_QUAD *,\r
+ short,\r
+ char *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_create_blob2 (ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ isc_blob_handle *,\r
+ ISC_QUAD *,\r
+ short,\r
+ char *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_close_blob (ISC_STATUS *,\r
+ isc_blob_handle *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_cancel_blob (ISC_STATUS *,\r
+ isc_blob_handle *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_get_segment (ISC_STATUS *,\r
+ isc_blob_handle *,\r
+ unsigned short *,\r
+ unsigned short,\r
+ char *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_put_segment (ISC_STATUS *,\r
+ isc_blob_handle *,\r
+ unsigned short,\r
+ char *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_blob_info (ISC_STATUS *,\r
+ isc_blob_handle *,\r
+ short,\r
+ char *,\r
+ short,\r
+ char *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_array_lookup_bounds (ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ char *,\r
+ char *,\r
+ ISC_ARRAY_DESC *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_array_get_slice (ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ ISC_QUAD *,\r
+ ISC_ARRAY_DESC *,\r
+ void *,\r
+ ISC_LONG *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_array_put_slice (ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ ISC_QUAD *,\r
+ ISC_ARRAY_DESC *,\r
+ void *,\r
+ ISC_LONG *);\r
+\r
+typedef ISC_LONG ISC_EXPORT proto_vax_integer (char *,\r
+ short);\r
+\r
+typedef ISC_LONG ISC_EXPORT proto_sqlcode (ISC_STATUS *);\r
+\r
+typedef void ISC_EXPORT proto_sql_interprete (short,\r
+ char *,\r
+ short);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_interprete (char *,\r
+ ISC_STATUS * *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_que_events (ISC_STATUS *,\r
+ isc_db_handle *,\r
+ ISC_LONG *,\r
+ short,\r
+ char *,\r
+ isc_callback,\r
+ void *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_cancel_events (ISC_STATUS *,\r
+ isc_db_handle *,\r
+ ISC_LONG *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_start_multiple (ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ short,\r
+ void *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_commit_transaction (ISC_STATUS *,\r
+ isc_tr_handle *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_commit_retaining (ISC_STATUS *,\r
+ isc_tr_handle *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_rollback_transaction (ISC_STATUS *,\r
+ isc_tr_handle *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_rollback_retaining (ISC_STATUS *,\r
+ isc_tr_handle *);\r
+\r
+///////////\r
+typedef ISC_STATUS ISC_EXPORT proto_dsql_allocate_statement (ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_stmt_handle *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_dsql_describe (ISC_STATUS *,\r
+ isc_stmt_handle *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_dsql_describe_bind (ISC_STATUS *,\r
+ isc_stmt_handle *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_dsql_execute (ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ isc_stmt_handle *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_dsql_execute2 (ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ isc_stmt_handle *,\r
+ unsigned short,\r
+ XSQLDA *,\r
+ XSQLDA *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_dsql_fetch (ISC_STATUS *,\r
+ isc_stmt_handle *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_dsql_free_statement (ISC_STATUS *,\r
+ isc_stmt_handle *,\r
+ unsigned short);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_dsql_prepare (ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ isc_stmt_handle *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_dsql_set_cursor_name (ISC_STATUS *,\r
+ isc_stmt_handle *,\r
+ char *,\r
+ unsigned short);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_dsql_sql_info (ISC_STATUS *,\r
+ isc_stmt_handle *,\r
+ short,\r
+ char *,\r
+ short,\r
+ char *);\r
+\r
+typedef void ISC_EXPORT proto_decode_date (ISC_QUAD *,\r
+ void *);\r
+\r
+typedef void ISC_EXPORT proto_encode_date (void *,\r
+ ISC_QUAD *);\r
+\r
+typedef int ISC_EXPORT proto_add_user (ISC_STATUS *, USER_SEC_DATA *);\r
+typedef int ISC_EXPORT proto_delete_user (ISC_STATUS *, USER_SEC_DATA *);\r
+typedef int ISC_EXPORT proto_modify_user (ISC_STATUS *, USER_SEC_DATA *);\r
+\r
+//\r
+// Those API are only available in versions 6.x of the GDS32.DLL\r
+//\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_service_attach (ISC_STATUS *,\r
+ unsigned short,\r
+ char *,\r
+ isc_svc_handle *,\r
+ unsigned short,\r
+ char *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_service_detach (ISC_STATUS *,\r
+ isc_svc_handle *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_service_query (ISC_STATUS *,\r
+ isc_svc_handle *,\r
+ isc_resv_handle *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ char *);\r
+\r
+typedef ISC_STATUS ISC_EXPORT proto_service_start (ISC_STATUS *,\r
+ isc_svc_handle *,\r
+ isc_resv_handle *,\r
+ unsigned short,\r
+ char*);\r
+\r
+typedef void ISC_EXPORT proto_decode_sql_date (ISC_DATE *,\r
+ void *);\r
+\r
+typedef void ISC_EXPORT proto_decode_sql_time (ISC_TIME *,\r
+ void *);\r
+\r
+typedef void ISC_EXPORT proto_decode_timestamp (ISC_TIMESTAMP *,\r
+ void *);\r
+\r
+typedef void ISC_EXPORT proto_encode_sql_date (void *,\r
+ ISC_DATE *);\r
+\r
+typedef void ISC_EXPORT proto_encode_sql_time (void *,\r
+ ISC_TIME *);\r
+\r
+typedef void ISC_EXPORT proto_encode_timestamp (void *,\r
+ ISC_TIMESTAMP *);\r
+\r
+//\r
+// Internal binding structure to the GDS32 DLL\r
+//\r
+\r
+struct GDS\r
+{\r
+ // Attributes\r
+ bool mReady;\r
+ int mGDSVersion; // Version of the GDS32.DLL (50 for 5.0, 60 for 6.0)\r
+\r
+#ifdef IBPP_WINDOWS\r
+ HMODULE mHandle; // The GDS32.DLL HMODULE\r
+ std::string mSearchPaths; // Optional additional search paths\r
+#endif\r
+\r
+ GDS* Call();\r
+\r
+ // GDS32 Entry Points\r
+ proto_create_database* m_create_database;\r
+ proto_attach_database* m_attach_database;\r
+ proto_detach_database* m_detach_database;\r
+ proto_drop_database* m_drop_database;\r
+ proto_database_info* m_database_info;\r
+ proto_dsql_execute_immediate* m_dsql_execute_immediate;\r
+ proto_open_blob2* m_open_blob2;\r
+ proto_create_blob2* m_create_blob2;\r
+ proto_close_blob* m_close_blob;\r
+ proto_cancel_blob* m_cancel_blob;\r
+ proto_get_segment* m_get_segment;\r
+ proto_put_segment* m_put_segment;\r
+ proto_blob_info* m_blob_info;\r
+ proto_array_lookup_bounds* m_array_lookup_bounds;\r
+ proto_array_get_slice* m_array_get_slice;\r
+ proto_array_put_slice* m_array_put_slice;\r
+\r
+ proto_vax_integer* m_vax_integer;\r
+ proto_sqlcode* m_sqlcode;\r
+ proto_sql_interprete* m_sql_interprete;\r
+ proto_interprete* m_interprete;\r
+ proto_que_events* m_que_events;\r
+ proto_cancel_events* m_cancel_events;\r
+ proto_start_multiple* m_start_multiple;\r
+ proto_commit_transaction* m_commit_transaction;\r
+ proto_commit_retaining* m_commit_retaining;\r
+ proto_rollback_transaction* m_rollback_transaction;\r
+ proto_rollback_retaining* m_rollback_retaining;\r
+ proto_dsql_allocate_statement* m_dsql_allocate_statement;\r
+ proto_dsql_describe* m_dsql_describe;\r
+ proto_dsql_describe_bind* m_dsql_describe_bind;\r
+ proto_dsql_prepare* m_dsql_prepare;\r
+ proto_dsql_execute* m_dsql_execute;\r
+ proto_dsql_execute2* m_dsql_execute2;\r
+ proto_dsql_fetch* m_dsql_fetch;\r
+ proto_dsql_free_statement* m_dsql_free_statement;\r
+ proto_dsql_set_cursor_name* m_dsql_set_cursor_name;\r
+ proto_dsql_sql_info* m_dsql_sql_info;\r
+ //proto_decode_date* m_decode_date;\r
+ //proto_encode_date* m_encode_date;\r
+ //proto_add_user* m_add_user;\r
+ //proto_delete_user* m_delete_user;\r
+ //proto_modify_user* m_modify_user;\r
+\r
+ proto_service_attach* m_service_attach;\r
+ proto_service_detach* m_service_detach;\r
+ proto_service_start* m_service_start;\r
+ proto_service_query* m_service_query;\r
+ //proto_decode_sql_date* m_decode_sql_date;\r
+ //proto_decode_sql_time* m_decode_sql_time;\r
+ //proto_decode_timestamp* m_decode_timestamp;\r
+ //proto_encode_sql_date* m_encode_sql_date;\r
+ //proto_encode_sql_time* m_encode_sql_time;\r
+ //proto_encode_timestamp* m_encode_timestamp;\r
+\r
+ // Constructor (No need for a specific destructor)\r
+ GDS()\r
+ {\r
+ mReady = false;\r
+ mGDSVersion = 0;\r
+#ifdef IBPP_WINDOWS\r
+ mHandle = 0;\r
+#endif\r
+ };\r
+};\r
+\r
+extern GDS gds;\r
+\r
+//\r
+// Service Parameter Block (used to define a service)\r
+//\r
+\r
+class SPB\r
+{\r
+ static const int BUFFERINCR;\r
+\r
+ char* mBuffer; // Dynamically allocated SPB structure\r
+ int mSize; // Its used size in bytes\r
+ int mAlloc; // Its allocated size in bytes\r
+\r
+ void Grow(int needed); // Alloc or grow the mBuffer\r
+\r
+public:\r
+ void Insert(char); // Insert a single byte code\r
+ void InsertString(char, int, const char*); // Insert a string, len can be defined as 1 or 2 bytes\r
+ void InsertByte(char type, char data);\r
+ void InsertQuad(char type, int32_t data);\r
+ void Reset(); // Clears the SPB\r
+ char* Self() { return mBuffer; }\r
+ short Size() { return (short)mSize; }\r
+\r
+ SPB() : mBuffer(0), mSize(0), mAlloc(0) { }\r
+ ~SPB() { Reset(); }\r
+};\r
+\r
+//\r
+// Database Parameter Block (used to define a database)\r
+//\r
+\r
+class DPB\r
+{\r
+ static const int BUFFERINCR;\r
+\r
+ char* mBuffer; // Dynamically allocated DPB structure\r
+ int mSize; // Its used size in bytes\r
+ int mAlloc; // Its allocated size in bytes\r
+\r
+ void Grow(int needed); // Allocate or grow the mBuffer, so that\r
+ // 'needed' bytes can be written (at least)\r
+\r
+public:\r
+ void Insert(char, const char*); // Insert a new char* 'cluster'\r
+ void Insert(char, int16_t); // Insert a new int16_t 'cluster'\r
+ void Insert(char, bool); // Insert a new bool 'cluster'\r
+ void Insert(char, char); // Insert a new byte 'cluster'\r
+ void Reset(); // Clears the DPB\r
+ char* Self() { return mBuffer; }\r
+ short Size() { return (short)mSize; }\r
+\r
+ DPB() : mBuffer(0), mSize(0), mAlloc(0) { }\r
+ ~DPB() { Reset(); }\r
+};\r
+\r
+//\r
+// Transaction Parameter Block (used to define a transaction)\r
+//\r
+\r
+class TPB\r
+{\r
+ static const int BUFFERINCR;\r
+\r
+ char* mBuffer; // Dynamically allocated TPB structure\r
+ int mSize; // Its used size in bytes\r
+ int mAlloc; // Its allocated size\r
+\r
+ void Grow(int needed); // Alloc or re-alloc the mBuffer\r
+\r
+public:\r
+ void Insert(char); // Insert a flag item\r
+ void Insert(const std::string& data); // Insert a string (typically table name)\r
+ void Reset(); // Clears the TPB\r
+ char* Self() { return mBuffer; }\r
+ int Size() { return mSize; }\r
+\r
+ TPB() : mBuffer(0), mSize(0), mAlloc(0) { }\r
+ ~TPB() { Reset(); }\r
+};\r
+\r
+//\r
+// Used to receive (and process) a results buffer in various API calls\r
+//\r
+\r
+class RB\r
+{\r
+ char* mBuffer;\r
+ int mSize;\r
+\r
+ char* FindToken(char token);\r
+ char* FindToken(char token, char subtoken);\r
+\r
+public:\r
+ void Reset();\r
+ int GetValue(char token);\r
+ int GetCountValue(char token);\r
+ int GetValue(char token, char subtoken);\r
+ bool GetBool(char token);\r
+ int GetString(char token, std::string& data);\r
+\r
+ char* Self() { return mBuffer; }\r
+ short Size() { return (short)mSize; }\r
+\r
+ RB();\r
+ RB(int Size);\r
+ ~RB();\r
+};\r
+\r
+//\r
+// Used to receive status info from API calls\r
+//\r
+\r
+class IBS\r
+{\r
+ mutable ISC_STATUS mVector[20];\r
+ mutable std::string mMessage;\r
+\r
+public:\r
+ ISC_STATUS* Self() { return mVector; }\r
+ bool Errors() { return (mVector[0] == 1 && mVector[1] > 0) ? true : false; }\r
+ const char* ErrorMessage() const;\r
+ int SqlCode() const;\r
+ int EngineCode() const { return (mVector[0] == 1) ? (int)mVector[1] : 0; }\r
+ void Reset();\r
+\r
+ IBS();\r
+ IBS(IBS&); // Copy Constructor\r
+ ~IBS();\r
+};\r
+\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Implementation of the "hidden" classes associated with their public\r
+// counterparts. Their private data and methods can freely change without\r
+// breaking the compatibility of the DLL. If they receive new public methods,\r
+// and those methods are reflected in the public class, then the compatibility\r
+// is broken.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+//\r
+// Hidden implementation of Exception classes.\r
+//\r
+\r
+/*\r
+ std::exception\r
+ |\r
+ IBPP::Exception\r
+ / \\r
+ / \\r
+ IBPP::LogicException ExceptionBase IBPP::SQLException\r
+ | \ / | \ /\r
+ | LogicExceptionImpl | SQLExceptionImpl\r
+ | |\r
+ IBPP::WrongType |\r
+ \ |\r
+ IBPP::WrongTypeImpl\r
+*/\r
+\r
+class ExceptionBase\r
+{\r
+ // (((((((( OBJECT INTERNALS ))))))))\r
+\r
+protected:\r
+ std::string mContext; // Exception context ("IDatabase::Drop")\r
+ std::string mWhat; // Full formatted message\r
+\r
+ void buildErrorMessage(const char* message);\r
+ void raise(const std::string& context, const char* message, va_list argptr);\r
+\r
+public:\r
+ // The following constructors are small and could be inlined, but for object\r
+ // code compacity of the library it is much better to have them non-inlined.\r
+ // The amount of code generated by compilers for a throw is well-enough.\r
+\r
+ ExceptionBase() throw();\r
+ ExceptionBase(const ExceptionBase& copied) throw();\r
+ ExceptionBase& operator=(const ExceptionBase& copied) throw();\r
+ ExceptionBase(const std::string& context, const char* message = 0, ...) throw();\r
+\r
+ virtual ~ExceptionBase() throw();\r
+\r
+ // (((((((( OBJECT INTERFACE ))))))))\r
+\r
+ virtual const char* Origin() const throw();\r
+ virtual const char* ErrorMessage() const throw();\r
+ virtual const char* what() const throw();\r
+};\r
+\r
+class LogicExceptionImpl : public IBPP::LogicException, public ExceptionBase\r
+{\r
+ // (((((((( OBJECT INTERNALS ))))))))\r
+\r
+public:\r
+ // The following constructors are small and could be inlined, but for object\r
+ // code compacity of the library it is much better to have them non-inlined.\r
+ // The amount of code generated by compilers for a throw is well-enough.\r
+\r
+ LogicExceptionImpl() throw();\r
+ LogicExceptionImpl(const LogicExceptionImpl& copied) throw();\r
+ LogicExceptionImpl& operator=(const LogicExceptionImpl& copied) throw();\r
+ LogicExceptionImpl(const std::string& context, const char* message = 0, ...) throw();\r
+\r
+ virtual ~LogicExceptionImpl() throw ();\r
+\r
+ // (((((((( OBJECT INTERFACE ))))))))\r
+ //\r
+ // The object public interface is partly implemented by inheriting from\r
+ // the ExceptionBase class.\r
+\r
+public:\r
+ virtual const char* Origin() const throw();\r
+ virtual const char* ErrorMessage() const throw();\r
+ virtual const char* what() const throw();\r
+};\r
+\r
+class SQLExceptionImpl : public IBPP::SQLException, public ExceptionBase\r
+{\r
+ // (((((((( OBJECT INTERNALS ))))))))\r
+\r
+private:\r
+ int mSqlCode;\r
+ int mEngineCode;\r
+\r
+public:\r
+ // The following constructors are small and could be inlined, but for object\r
+ // code compacity of the library it is much better to have them non-inlined.\r
+ // The amount of code generated by compilers for a throw is well-enough.\r
+\r
+ SQLExceptionImpl() throw();\r
+ SQLExceptionImpl(const SQLExceptionImpl& copied) throw();\r
+ SQLExceptionImpl& operator=(const SQLExceptionImpl& copied) throw();\r
+ SQLExceptionImpl(const IBS& status, const std::string& context,\r
+ const char* message = 0, ...) throw();\r
+\r
+ virtual ~SQLExceptionImpl() throw ();\r
+\r
+ // (((((((( OBJECT INTERFACE ))))))))\r
+ //\r
+ // The object public interface is partly implemented by inheriting from\r
+ // the ExceptionBase class.\r
+\r
+public:\r
+ virtual const char* Origin() const throw();\r
+ virtual const char* ErrorMessage() const throw();\r
+ virtual const char* what() const throw();\r
+ virtual int SqlCode() const throw();\r
+ virtual int EngineCode() const throw();\r
+};\r
+\r
+class WrongTypeImpl : public IBPP::WrongType, public ExceptionBase\r
+{\r
+ // (((((((( OBJECT INTERNALS ))))))))\r
+\r
+public:\r
+ // The following constructors are small and could be inlined, but for object\r
+ // code compacity of the library it is much better to have them non-inlined.\r
+ // The amount of code generated by compilers for a throw is well-enough.\r
+\r
+ WrongTypeImpl() throw();\r
+ WrongTypeImpl(const WrongTypeImpl& copied) throw();\r
+ WrongTypeImpl& operator=(const WrongTypeImpl& copied) throw();\r
+ WrongTypeImpl(const std::string& context, int sqlType, IITYPE varType,\r
+ const char* message = 0, ...) throw();\r
+\r
+ virtual ~WrongTypeImpl() throw ();\r
+\r
+ // (((((((( OBJECT INTERFACE ))))))))\r
+ //\r
+ // The object public interface is partly implemented by inheriting from\r
+ // the ExceptionBase class.\r
+\r
+public:\r
+ virtual const char* Origin() const throw();\r
+ virtual const char* ErrorMessage() const throw();\r
+ virtual const char* what() const throw();\r
+};\r
+\r
+class ServiceImpl : public IBPP::IService\r
+{\r
+ // (((((((( OBJECT INTERNALS ))))))))\r
+\r
+private:\r
+ int mRefCount; // Reference counter\r
+ isc_svc_handle mHandle; // InterBase API Service Handle\r
+ std::string mServerName; // Nom du serveur\r
+ std::string mUserName; // Nom de l'utilisateur\r
+ std::string mUserPassword; // Mot de passe de l'utilisateur\r
+ std::string mWaitMessage; // Progress message returned by WaitMsg()\r
+\r
+ isc_svc_handle* GetHandlePtr() { return &mHandle; }\r
+ void SetServerName(const char*);\r
+ void SetUserName(const char*);\r
+ void SetUserPassword(const char*);\r
+\r
+public:\r
+ isc_svc_handle GetHandle() { return mHandle; }\r
+\r
+ ServiceImpl(const std::string& ServerName, const std::string& UserName,\r
+ const std::string& UserPassword);\r
+ ~ServiceImpl();\r
+\r
+ // (((((((( OBJECT INTERFACE ))))))))\r
+\r
+public:\r
+ void Connect();\r
+ bool Connected() { return mHandle == 0 ? false : true; }\r
+ void Disconnect();\r
+\r
+ void GetVersion(std::string& version);\r
+\r
+ void AddUser(const IBPP::User&);\r
+ void GetUser(IBPP::User&);\r
+ void GetUsers(std::vector<IBPP::User>&);\r
+ void ModifyUser(const IBPP::User&);\r
+ void RemoveUser(const std::string& username);\r
+\r
+ void SetPageBuffers(const std::string& dbfile, int buffers);\r
+ void SetSweepInterval(const std::string& dbfile, int sweep);\r
+ void SetSyncWrite(const std::string& dbfile, bool);\r
+ void SetReadOnly(const std::string& dbfile, bool);\r
+ void SetReserveSpace(const std::string& dbfile, bool);\r
+\r
+ void Shutdown(const std::string& dbfile, IBPP::DSM mode, int sectimeout);\r
+ void Restart(const std::string& dbfile);\r
+ void Sweep(const std::string& dbfile);\r
+ void Repair(const std::string& dbfile, IBPP::RPF flags);\r
+\r
+ void StartBackup(const std::string& dbfile, const std::string& bkfile,\r
+ IBPP::BRF flags = IBPP::BRF(0));\r
+ void StartRestore(const std::string& bkfile, const std::string& dbfile,\r
+ int pagesize, IBPP::BRF flags = IBPP::BRF(0));\r
+\r
+ const char* WaitMsg();\r
+ void Wait();\r
+\r
+ IBPP::IService* AddRef();\r
+ void Release();\r
+};\r
+\r
+class DatabaseImpl : public IBPP::IDatabase\r
+{\r
+ // (((((((( OBJECT INTERNALS ))))))))\r
+\r
+ int mRefCount; // Reference counter\r
+ isc_db_handle mHandle; // InterBase API Session Handle\r
+ std::string mServerName; // Server name\r
+ std::string mDatabaseName; // Database name (path/file)\r
+ std::string mUserName; // User name\r
+ std::string mUserPassword; // User password\r
+ std::string mRoleName; // Role used for the duration of the connection\r
+ std::string mCharSet; // Character Set used for the connection\r
+ std::string mCreateParams; // Other parameters (creation only)\r
+\r
+ int mDialect; // 1 if IB5, 1 or 3 if IB6/FB1\r
+ std::vector<TransactionImpl*> mTransactions;// Table of Transaction*\r
+ std::vector<StatementImpl*> mStatements;// Table of Statement*\r
+ std::vector<BlobImpl*> mBlobs; // Table of Blob*\r
+ std::vector<ArrayImpl*> mArrays; // Table of Array*\r
+ std::vector<EventsImpl*> mEvents; // Table of Events*\r
+\r
+public:\r
+ isc_db_handle* GetHandlePtr() { return &mHandle; }\r
+ isc_db_handle GetHandle() { return mHandle; }\r
+\r
+ void AttachTransactionImpl(TransactionImpl*);\r
+ void DetachTransactionImpl(TransactionImpl*);\r
+ void AttachStatementImpl(StatementImpl*);\r
+ void DetachStatementImpl(StatementImpl*);\r
+ void AttachBlobImpl(BlobImpl*);\r
+ void DetachBlobImpl(BlobImpl*);\r
+ void AttachArrayImpl(ArrayImpl*);\r
+ void DetachArrayImpl(ArrayImpl*);\r
+ void AttachEventsImpl(EventsImpl*);\r
+ void DetachEventsImpl(EventsImpl*);\r
+\r
+ DatabaseImpl(const std::string& ServerName, const std::string& DatabaseName,\r
+ const std::string& UserName, const std::string& UserPassword,\r
+ const std::string& RoleName, const std::string& CharSet,\r
+ const std::string& CreateParams);\r
+ ~DatabaseImpl();\r
+\r
+ // (((((((( OBJECT INTERFACE ))))))))\r
+\r
+public:\r
+ const char* ServerName() const { return mServerName.c_str(); }\r
+ const char* DatabaseName() const { return mDatabaseName.c_str(); }\r
+ const char* Username() const { return mUserName.c_str(); }\r
+ const char* UserPassword() const { return mUserPassword.c_str(); }\r
+ const char* RoleName() const { return mRoleName.c_str(); }\r
+ const char* CharSet() const { return mCharSet.c_str(); }\r
+ const char* CreateParams() const { return mCreateParams.c_str(); }\r
+\r
+ void Info(int* ODSMajor, int* ODSMinor,\r
+ int* PageSize, int* Pages, int* Buffers, int* Sweep,\r
+ bool* SyncWrites, bool* Reserve);\r
+ void Statistics(int* Fetches, int* Marks, int* Reads, int* Writes);\r
+ void Counts(int* Insert, int* Update, int* Delete,\r
+ int* ReadIdx, int* ReadSeq);\r
+ void Users(std::vector<std::string>& users);\r
+ int Dialect() { return mDialect; }\r
+\r
+ void Create(int dialect);\r
+ void Connect();\r
+ bool Connected() { return mHandle == 0 ? false : true; }\r
+ void Inactivate();\r
+ void Disconnect();\r
+ void Drop();\r
+\r
+ IBPP::IDatabase* AddRef();\r
+ void Release();\r
+};\r
+\r
+class TransactionImpl : public IBPP::ITransaction\r
+{\r
+ // (((((((( OBJECT INTERNALS ))))))))\r
+\r
+private:\r
+ int mRefCount; // Reference counter\r
+ isc_tr_handle mHandle; // Transaction InterBase\r
+\r
+ std::vector<DatabaseImpl*> mDatabases; // Tableau de IDatabase*\r
+ std::vector<StatementImpl*> mStatements; // Tableau de IStatement*\r
+ std::vector<BlobImpl*> mBlobs; // Tableau de IBlob*\r
+ std::vector<ArrayImpl*> mArrays; // Tableau de Array*\r
+ std::vector<TPB*> mTPBs; // Tableau de TPB\r
+\r
+ void Init(); // A usage exclusif des constructeurs\r
+\r
+public:\r
+ isc_tr_handle* GetHandlePtr() { return &mHandle; }\r
+ isc_tr_handle GetHandle() { return mHandle; }\r
+\r
+ void AttachStatementImpl(StatementImpl*);\r
+ void DetachStatementImpl(StatementImpl*);\r
+ void AttachBlobImpl(BlobImpl*);\r
+ void DetachBlobImpl(BlobImpl*);\r
+ void AttachArrayImpl(ArrayImpl*);\r
+ void DetachArrayImpl(ArrayImpl*);\r
+ void AttachDatabaseImpl(DatabaseImpl* dbi, IBPP::TAM am = IBPP::amWrite,\r
+ IBPP::TIL il = IBPP::ilConcurrency,\r
+ IBPP::TLR lr = IBPP::lrWait, IBPP::TFF flags = IBPP::TFF(0));\r
+ void DetachDatabaseImpl(DatabaseImpl* dbi);\r
+\r
+ TransactionImpl(DatabaseImpl* db, IBPP::TAM am = IBPP::amWrite,\r
+ IBPP::TIL il = IBPP::ilConcurrency,\r
+ IBPP::TLR lr = IBPP::lrWait, IBPP::TFF flags = IBPP::TFF(0));\r
+ ~TransactionImpl();\r
+\r
+ // (((((((( OBJECT INTERFACE ))))))))\r
+\r
+public:\r
+ void AttachDatabase(IBPP::Database db, IBPP::TAM am = IBPP::amWrite,\r
+ IBPP::TIL il = IBPP::ilConcurrency,\r
+ IBPP::TLR lr = IBPP::lrWait, IBPP::TFF flags = IBPP::TFF(0));\r
+ void DetachDatabase(IBPP::Database db);\r
+ void AddReservation(IBPP::Database db,\r
+ const std::string& table, IBPP::TTR tr);\r
+\r
+ void Start();\r
+ bool Started() { return mHandle == 0 ? false : true; }\r
+ void Commit();\r
+ void Rollback();\r
+ void CommitRetain();\r
+ void RollbackRetain();\r
+\r
+ IBPP::ITransaction* AddRef();\r
+ void Release();\r
+};\r
+\r
+class RowImpl : public IBPP::IRow\r
+{\r
+ // (((((((( OBJECT INTERNALS ))))))))\r
+\r
+private:\r
+ int mRefCount; // Reference counter\r
+\r
+ XSQLDA* mDescrArea; // XSQLDA descriptor itself\r
+ std::vector<double> mNumerics; // Temporary storage for Numerics\r
+ std::vector<float> mFloats; // Temporary storage for Floats\r
+ std::vector<int64_t> mInt64s; // Temporary storage for 64 bits\r
+ std::vector<int32_t> mInt32s; // Temporary storage for 32 bits\r
+ std::vector<int16_t> mInt16s; // Temporary storage for 16 bits\r
+ std::vector<char> mBools; // Temporary storage for Bools\r
+ std::vector<std::string> mStrings; // Temporary storage for Strings\r
+ std::vector<bool> mUpdated; // Which columns where updated (Set()) ?\r
+\r
+ int mDialect; // Related database dialect\r
+ DatabaseImpl* mDatabase; // Related Database (important for Blobs, ...)\r
+ TransactionImpl* mTransaction; // Related Transaction (same remark)\r
+\r
+ void SetValue(int, IITYPE, const void* value, int = 0);\r
+ void* GetValue(int, IITYPE, void* = 0);\r
+\r
+public:\r
+ void Free();\r
+ short AllocatedSize() { return mDescrArea->sqln; }\r
+ void Resize(int n);\r
+ void AllocVariables();\r
+ bool MissingValues(); // Returns wether one of the mMissing[] is true\r
+ XSQLDA* Self() { return mDescrArea; }\r
+\r
+ RowImpl& operator=(const RowImpl& copied);\r
+ RowImpl(const RowImpl& copied);\r
+ RowImpl(int dialect, int size, DatabaseImpl* db, TransactionImpl* tr);\r
+ ~RowImpl();\r
+\r
+ // (((((((( OBJECT INTERFACE ))))))))\r
+\r
+public:\r
+ void SetNull(int);\r
+ void Set(int, bool);\r
+ void Set(int, const char*); // c-strings\r
+ void Set(int, const void*, int); // byte buffers\r
+ void Set(int, const std::string&);\r
+ void Set(int, int16_t);\r
+ void Set(int, int32_t);\r
+ void Set(int, int64_t);\r
+ void Set(int, float);\r
+ void Set(int, double);\r
+ void Set(int, const IBPP::Timestamp&);\r
+ void Set(int, const IBPP::Date&);\r
+ void Set(int, const IBPP::Time&);\r
+ void Set(int, const IBPP::DBKey&);\r
+ void Set(int, const IBPP::Blob&);\r
+ void Set(int, const IBPP::Array&);\r
+\r
+ bool IsNull(int);\r
+ bool Get(int, bool&);\r
+ bool Get(int, char*); // c-strings, len unchecked\r
+ bool Get(int, void*, int&); // byte buffers\r
+ bool Get(int, std::string&);\r
+ bool Get(int, int16_t&);\r
+ bool Get(int, int32_t&);\r
+ bool Get(int, int64_t&);\r
+ bool Get(int, float&);\r
+ bool Get(int, double&);\r
+ bool Get(int, IBPP::Timestamp&);\r
+ bool Get(int, IBPP::Date&);\r
+ bool Get(int, IBPP::Time&);\r
+ bool Get(int, IBPP::DBKey&);\r
+ bool Get(int, IBPP::Blob&);\r
+ bool Get(int, IBPP::Array&);\r
+\r
+ bool IsNull(const std::string&);\r
+ bool Get(const std::string&, bool&);\r
+ bool Get(const std::string&, char*); // c-strings, len unchecked\r
+ bool Get(const std::string&, void*, int&); // byte buffers\r
+ bool Get(const std::string&, std::string&);\r
+ bool Get(const std::string&, int16_t&);\r
+ bool Get(const std::string&, int32_t&);\r
+ bool Get(const std::string&, int64_t&);\r
+ bool Get(const std::string&, float&);\r
+ bool Get(const std::string&, double&);\r
+ bool Get(const std::string&, IBPP::Timestamp&);\r
+ bool Get(const std::string&, IBPP::Date&);\r
+ bool Get(const std::string&, IBPP::Time&);\r
+ bool Get(const std::string&, IBPP::DBKey&);\r
+ bool Get(const std::string&, IBPP::Blob&);\r
+ bool Get(const std::string&, IBPP::Array&);\r
+\r
+ int ColumnNum(const std::string&);\r
+ const char* ColumnName(int);\r
+ const char* ColumnAlias(int);\r
+ const char* ColumnTable(int);\r
+ IBPP::SDT ColumnType(int);\r
+ int ColumnSubtype(int);\r
+ int ColumnSize(int);\r
+ int ColumnScale(int);\r
+ int Columns();\r
+\r
+ bool ColumnUpdated(int);\r
+ bool Updated();\r
+\r
+ IBPP::Database DatabasePtr() const;\r
+ IBPP::Transaction TransactionPtr() const;\r
+\r
+ IBPP::IRow* Clone();\r
+ IBPP::IRow* AddRef();\r
+ void Release();\r
+};\r
+\r
+class StatementImpl : public IBPP::IStatement\r
+{\r
+ // (((((((( OBJECT INTERNALS ))))))))\r
+\r
+private:\r
+ friend class TransactionImpl;\r
+\r
+ int mRefCount; // Reference counter\r
+ isc_stmt_handle mHandle; // Statement Handle\r
+\r
+ DatabaseImpl* mDatabase; // Attached database\r
+ TransactionImpl* mTransaction; // Attached transaction\r
+ RowImpl* mInRow;\r
+ //bool* mInMissing; // Quels paramètres n'ont pas été spécifiés\r
+ RowImpl* mOutRow;\r
+ bool mResultSetAvailable; // Executed and result set is available\r
+ bool mCursorOpened; // dsql_set_cursor_name was called\r
+ IBPP::STT mType; // Type de requète\r
+ std::string mSql; // Last SQL statement prepared or executed\r
+\r
+ // Internal Methods\r
+ void CursorFree();\r
+\r
+public:\r
+ // Properties and Attributes Access Methods\r
+ isc_stmt_handle GetHandle() { return mHandle; }\r
+\r
+ void AttachDatabaseImpl(DatabaseImpl*);\r
+ void DetachDatabaseImpl();\r
+ void AttachTransactionImpl(TransactionImpl*);\r
+ void DetachTransactionImpl();\r
+\r
+ StatementImpl(DatabaseImpl*, TransactionImpl*, const std::string&);\r
+ ~StatementImpl();\r
+\r
+ // (((((((( OBJECT INTERFACE ))))))))\r
+\r
+public:\r
+ void Prepare(const std::string& sql);\r
+ void Execute(const std::string& sql);\r
+ inline void Execute() { Execute(std::string()); }\r
+ void ExecuteImmediate(const std::string&);\r
+ void CursorExecute(const std::string& cursor, const std::string& sql);\r
+ inline void CursorExecute(const std::string& cursor) { CursorExecute(cursor, std::string()); }\r
+ bool Fetch();\r
+ bool Fetch(IBPP::Row&);\r
+ int AffectedRows();\r
+ void Close(); // Free resources, attachments maintained\r
+ std::string& Sql() { return mSql; }\r
+ IBPP::STT Type() { return mType; }\r
+\r
+ void SetNull(int);\r
+ void Set(int, bool);\r
+ void Set(int, const char*); // c-strings\r
+ void Set(int, const void*, int); // byte buffers\r
+ void Set(int, const std::string&);\r
+ void Set(int, int16_t);\r
+ void Set(int, int32_t);\r
+ void Set(int, int64_t);\r
+ void Set(int, float);\r
+ void Set(int, double);\r
+ void Set(int, const IBPP::Timestamp&);\r
+ void Set(int, const IBPP::Date&);\r
+ void Set(int, const IBPP::Time&);\r
+ void Set(int, const IBPP::DBKey&);\r
+ void Set(int, const IBPP::Blob&);\r
+ void Set(int, const IBPP::Array&);\r
+\r
+ bool IsNull(int);\r
+ bool Get(int, bool*);\r
+ bool Get(int, bool&);\r
+ bool Get(int, char*); // c-strings, len unchecked\r
+ bool Get(int, void*, int&); // byte buffers\r
+ bool Get(int, std::string&);\r
+ bool Get(int, int16_t*);\r
+ bool Get(int, int16_t&);\r
+ bool Get(int, int32_t*);\r
+ bool Get(int, int32_t&);\r
+ bool Get(int, int64_t*);\r
+ bool Get(int, int64_t&);\r
+ bool Get(int, float*);\r
+ bool Get(int, float&);\r
+ bool Get(int, double*);\r
+ bool Get(int, double&);\r
+ bool Get(int, IBPP::Timestamp&);\r
+ bool Get(int, IBPP::Date&);\r
+ bool Get(int, IBPP::Time&);\r
+ bool Get(int, IBPP::DBKey&);\r
+ bool Get(int, IBPP::Blob&);\r
+ bool Get(int, IBPP::Array&);\r
+\r
+ bool IsNull(const std::string&);\r
+ bool Get(const std::string&, bool*);\r
+ bool Get(const std::string&, bool&);\r
+ bool Get(const std::string&, char*); // c-strings, len unchecked\r
+ bool Get(const std::string&, void*, int&); // byte buffers\r
+ bool Get(const std::string&, std::string&);\r
+ bool Get(const std::string&, int16_t*);\r
+ bool Get(const std::string&, int16_t&);\r
+ bool Get(const std::string&, int32_t*);\r
+ bool Get(const std::string&, int32_t&);\r
+ bool Get(const std::string&, int64_t*);\r
+ bool Get(const std::string&, int64_t&);\r
+ bool Get(const std::string&, float*);\r
+ bool Get(const std::string&, float&);\r
+ bool Get(const std::string&, double*);\r
+ bool Get(const std::string&, double&);\r
+ bool Get(const std::string&, IBPP::Timestamp&);\r
+ bool Get(const std::string&, IBPP::Date&);\r
+ bool Get(const std::string&, IBPP::Time&);\r
+ bool Get(const std::string&, IBPP::DBKey&);\r
+ bool Get(const std::string&, IBPP::Blob&);\r
+ bool Get(const std::string&, IBPP::Array&);\r
+\r
+ int ColumnNum(const std::string&);\r
+ int ColumnNumAlias(const std::string&);\r
+ const char* ColumnName(int);\r
+ const char* ColumnAlias(int);\r
+ const char* ColumnTable(int);\r
+ IBPP::SDT ColumnType(int);\r
+ int ColumnSubtype(int);\r
+ int ColumnSize(int);\r
+ int ColumnScale(int);\r
+ int Columns();\r
+\r
+ IBPP::SDT ParameterType(int);\r
+ int ParameterSubtype(int);\r
+ int ParameterSize(int);\r
+ int ParameterScale(int);\r
+ int Parameters();\r
+\r
+ void Plan(std::string&);\r
+\r
+ IBPP::Database DatabasePtr() const;\r
+ IBPP::Transaction TransactionPtr() const;\r
+\r
+ IBPP::IStatement* AddRef();\r
+ void Release();\r
+};\r
+\r
+class BlobImpl : public IBPP::IBlob\r
+{\r
+ // (((((((( OBJECT INTERNALS ))))))))\r
+\r
+private:\r
+ friend class RowImpl;\r
+\r
+ int mRefCount;\r
+ bool mIdAssigned;\r
+ ISC_QUAD mId;\r
+ isc_blob_handle mHandle;\r
+ bool mWriteMode;\r
+ DatabaseImpl* mDatabase; // Belongs to this database\r
+ TransactionImpl* mTransaction; // Belongs to this transaction\r
+\r
+ void Init();\r
+ void SetId(ISC_QUAD*);\r
+ void GetId(ISC_QUAD*);\r
+\r
+public:\r
+ void AttachDatabaseImpl(DatabaseImpl*);\r
+ void DetachDatabaseImpl();\r
+ void AttachTransactionImpl(TransactionImpl*);\r
+ void DetachTransactionImpl();\r
+\r
+ BlobImpl(const BlobImpl&);\r
+ BlobImpl(DatabaseImpl*, TransactionImpl* = 0);\r
+ ~BlobImpl();\r
+\r
+ // (((((((( OBJECT INTERFACE ))))))))\r
+\r
+public:\r
+ void Create();\r
+ void Open();\r
+ void Close();\r
+ void Cancel();\r
+ int Read(void*, int size);\r
+ void Write(const void*, int size);\r
+ void Info(int* Size, int* Largest, int* Segments);\r
+\r
+ void Save(const std::string& data);\r
+ void Load(std::string& data);\r
+\r
+ IBPP::Database DatabasePtr() const;\r
+ IBPP::Transaction TransactionPtr() const;\r
+\r
+ IBPP::IBlob* AddRef();\r
+ void Release();\r
+};\r
+\r
+class ArrayImpl : public IBPP::IArray\r
+{\r
+ // (((((((( OBJECT INTERNALS ))))))))\r
+\r
+private:\r
+ friend class RowImpl;\r
+\r
+ int mRefCount; // Reference counter\r
+ bool mIdAssigned;\r
+ ISC_QUAD mId;\r
+ bool mDescribed;\r
+ ISC_ARRAY_DESC mDesc;\r
+ DatabaseImpl* mDatabase; // Database attachée\r
+ TransactionImpl* mTransaction; // Transaction attachée\r
+ void* mBuffer; // Buffer for native data\r
+ int mBufferSize; // Size of this buffer in bytes\r
+ int mElemCount; // Count of elements in this array\r
+ int mElemSize; // Size of an element in the buffer\r
+\r
+ void Init();\r
+ void SetId(ISC_QUAD*);\r
+ void GetId(ISC_QUAD*);\r
+ void ResetId();\r
+ void AllocArrayBuffer();\r
+\r
+public:\r
+ void AttachDatabaseImpl(DatabaseImpl*);\r
+ void DetachDatabaseImpl();\r
+ void AttachTransactionImpl(TransactionImpl*);\r
+ void DetachTransactionImpl();\r
+\r
+ ArrayImpl(const ArrayImpl&);\r
+ ArrayImpl(DatabaseImpl*, TransactionImpl* = 0);\r
+ ~ArrayImpl();\r
+\r
+ // (((((((( OBJECT INTERFACE ))))))))\r
+\r
+public:\r
+ void Describe(const std::string& table, const std::string& column);\r
+ void ReadTo(IBPP::ADT, void*, int);\r
+ void WriteFrom(IBPP::ADT, const void*, int);\r
+ IBPP::SDT ElementType();\r
+ int ElementSize();\r
+ int ElementScale();\r
+ int Dimensions();\r
+ void Bounds(int dim, int* low, int* high);\r
+ void SetBounds(int dim, int low, int high);\r
+\r
+ IBPP::Database DatabasePtr() const;\r
+ IBPP::Transaction TransactionPtr() const;\r
+\r
+ IBPP::IArray* AddRef();\r
+ void Release();\r
+};\r
+\r
+//\r
+// EventBufferIterator: used in EventsImpl implementation.\r
+//\r
+\r
+template<class It>\r
+struct EventBufferIterator\r
+{\r
+ It mIt;\r
+\r
+public:\r
+ EventBufferIterator& operator++()\r
+ { mIt += 1 + static_cast<int>(*mIt) + 4; return *this; }\r
+\r
+ bool operator == (const EventBufferIterator& i) const { return i.mIt == mIt; }\r
+ bool operator != (const EventBufferIterator& i) const { return i.mIt != mIt; }\r
+\r
+#ifdef __BCPLUSPLUS__\r
+#pragma warn -8027\r
+#endif\r
+ std::string get_name() const\r
+ {\r
+ return std::string(mIt + 1, mIt + 1 + static_cast<int32_t>(*mIt));\r
+ }\r
+#ifdef __BCPLUSPLUS__\r
+#pragma warn .8027\r
+#endif\r
+\r
+ uint32_t get_count() const\r
+ {\r
+ return (*gds.Call()->m_vax_integer)\r
+ (const_cast<char*>(&*(mIt + 1 + static_cast<int>(*mIt))), 4);\r
+ }\r
+\r
+ // Those container like begin() and end() allow access to the underlying type\r
+ It begin() { return mIt; }\r
+ It end() { return mIt + 1 + static_cast<int>(*mIt) + 4; }\r
+\r
+ EventBufferIterator() {}\r
+ EventBufferIterator(It it) : mIt(it) {}\r
+};\r
+\r
+class EventsImpl : public IBPP::IEvents\r
+{\r
+ static const size_t MAXEVENTNAMELEN;\r
+ static void EventHandler(const char*, short, const char*);\r
+\r
+ typedef std::vector<IBPP::EventInterface*> ObjRefs;\r
+ ObjRefs mObjectReferences;\r
+\r
+ typedef std::vector<char> Buffer;\r
+ Buffer mEventBuffer;\r
+ Buffer mResultsBuffer;\r
+\r
+ int mRefCount; // Reference counter\r
+\r
+ DatabaseImpl* mDatabase;\r
+ ISC_LONG mId; // Firebird internal Id of these events\r
+ bool mQueued; // Has isc_que_events() been called?\r
+ bool mTrapped; // EventHandled() was called since last que_events()\r
+\r
+ void FireActions();\r
+ void Queue();\r
+ void Cancel();\r
+\r
+ EventsImpl& operator=(const EventsImpl&);\r
+ EventsImpl(const EventsImpl&);\r
+\r
+public:\r
+ void AttachDatabaseImpl(DatabaseImpl*);\r
+ void DetachDatabaseImpl();\r
+ \r
+ EventsImpl(DatabaseImpl* dbi);\r
+ ~EventsImpl();\r
+ \r
+ // (((((((( OBJECT INTERFACE ))))))))\r
+\r
+public:\r
+ void Add(const std::string&, IBPP::EventInterface*);\r
+ void Drop(const std::string&);\r
+ void List(std::vector<std::string>&);\r
+ void Clear(); // Drop all events\r
+ void Dispatch(); // Dispatch NON async events\r
+\r
+ IBPP::Database DatabasePtr() const;\r
+\r
+ IBPP::IEvents* AddRef();\r
+ void Release();\r
+};\r
+\r
+void encodeDate(ISC_DATE& isc_dt, const IBPP::Date& dt);\r
+void decodeDate(IBPP::Date& dt, const ISC_DATE& isc_dt);\r
+\r
+void encodeTime(ISC_TIME& isc_tm, const IBPP::Time& tm);\r
+void decodeTime(IBPP::Time& tm, const ISC_TIME& isc_tm);\r
+\r
+void encodeTimestamp(ISC_TIMESTAMP& isc_ts, const IBPP::Timestamp& ts);\r
+void decodeTimestamp(IBPP::Timestamp& ts, const ISC_TIMESTAMP& isc_ts);\r
+\r
+struct consts // See _ibpp.cpp for initializations of these constants\r
+{\r
+ static const double dscales[19];\r
+ static const int Dec31_1899;\r
+ static const int16_t min16;\r
+ static const int16_t max16;\r
+ static const int32_t min32;\r
+ static const int32_t max32;\r
+};\r
+\r
+} // namespace ibpp_internal\r
+\r
+#endif // __INTERNAL_IBPP_H__\r
+\r
+//\r
+// Eof\r
+//\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: _ibs.cpp,v 1.2 2009/03/19 20:00:27 faust Exp $\r
+// Subject : IBPP, internal Status class implementation\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning(disable: 4786 4996)\r
+#ifndef _DEBUG\r
+#pragma warning(disable: 4702)\r
+#endif\r
+#endif\r
+\r
+#include "_ibpp.h"\r
+\r
+#ifdef HAS_HDRSTOP\r
+#pragma hdrstop\r
+#endif\r
+\r
+#include <cstring>\r
+\r
+using namespace ibpp_internals;\r
+\r
+int IBS::SqlCode() const\r
+{\r
+ return (int)(*gds.Call()->m_sqlcode)(&mVector[0]);\r
+}\r
+\r
+const char* IBS::ErrorMessage() const\r
+{\r
+ char msg[1024];\r
+ ISC_LONG sqlcode;\r
+\r
+ if (! mMessage.empty()) return mMessage.c_str(); // If message compiled, returns it\r
+\r
+ // Compiles the message (SQL part)\r
+ std::ostringstream message;\r
+ sqlcode = (*gds.Call()->m_sqlcode)(mVector);\r
+ if (sqlcode != -999)\r
+ {\r
+ (*gds.Call()->m_sql_interprete)((short)sqlcode, msg, sizeof(msg));\r
+ message<< _("SQL Message : ")<< sqlcode<< "\n"<< msg<< "\n\n";\r
+ }\r
+\r
+ message<< _("Engine Code : ")<< EngineCode()<< "\n";\r
+\r
+ // Compiles the message (Engine part)\r
+ ISC_STATUS* error = &mVector[0];\r
+ try { (*gds.Call()->m_interprete)(msg, &error); }\r
+ catch(...) { msg[0] = '\0'; }\r
+ message<< _("Engine Message :")<< "\n"<< msg;\r
+ try\r
+ {\r
+ while ((*gds.Call()->m_interprete)(msg, &error))\r
+ message<< "\n"<< msg;\r
+ }\r
+ catch (...) { }\r
+\r
+ message<< "\n";\r
+ mMessage = message.str();\r
+ return mMessage.c_str();\r
+}\r
+\r
+void IBS::Reset()\r
+{\r
+ for (int i = 0; i < 20; i++) mVector[i] = 0;\r
+ mMessage.erase();\r
+}\r
+\r
+IBS::IBS()\r
+{\r
+ Reset();\r
+}\r
+\r
+IBS::~IBS()\r
+{\r
+}\r
+\r
+/** Copy Constructor\r
+*/\r
+\r
+IBS::IBS(IBS& copied)\r
+{\r
+ memcpy(mVector, copied.mVector, sizeof(mVector));\r
+}\r
+\r
+//\r
+// EOF\r
+//\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: _rb.cpp,v 1.2 2009/03/19 20:00:27 faust Exp $\r
+// Subject : IBPP, internal RB class implementation\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * RB == Result Block/Buffer, see Interbase 6.0 C-API\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning(disable: 4786 4996)\r
+#ifndef _DEBUG\r
+#pragma warning(disable: 4702)\r
+#endif\r
+#endif\r
+\r
+#include "_ibpp.h"\r
+\r
+#ifdef HAS_HDRSTOP\r
+#pragma hdrstop\r
+#endif\r
+\r
+#include <cstring>\r
+\r
+using namespace ibpp_internals;\r
+\r
+char* RB::FindToken(char token)\r
+{\r
+ char* p = mBuffer;\r
+\r
+ while (*p != isc_info_end)\r
+ {\r
+ int len;\r
+\r
+ if (*p == token) return p;\r
+ len = (*gds.Call()->m_vax_integer)(p+1, 2);\r
+ p += (len + 3);\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+char* RB::FindToken(char token, char subtoken)\r
+{\r
+ char* p = mBuffer;\r
+\r
+ while (*p != isc_info_end)\r
+ {\r
+ int len;\r
+\r
+ if (*p == token)\r
+ {\r
+ // Found token, now find subtoken\r
+ int inlen = (*gds.Call()->m_vax_integer)(p+1, 2);\r
+ p += 3;\r
+ while (inlen > 0)\r
+ {\r
+ if (*p == subtoken) return p;\r
+ len = (*gds.Call()->m_vax_integer)(p+1, 2);\r
+ p += (len + 3);\r
+ inlen -= (len + 3);\r
+ }\r
+ return 0;\r
+ }\r
+ len = (*gds.Call()->m_vax_integer)(p+1, 2);\r
+ p += (len + 3);\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+int RB::GetValue(char token)\r
+{\r
+ int value;\r
+ int len;\r
+ char* p = FindToken(token);\r
+\r
+ if (p == 0)\r
+ throw LogicExceptionImpl("RB::GetValue", _("Token not found."));\r
+\r
+ len = (*gds.Call()->m_vax_integer)(p+1, 2);\r
+ if (len == 0) value = 0;\r
+ else value = (*gds.Call()->m_vax_integer)(p+3, (short)len);\r
+\r
+ return value;\r
+}\r
+\r
+int RB::GetCountValue(char token)\r
+{\r
+ // Specifically used on tokens like isc_info_insert_count and the like\r
+ // which return detailed counts per relation. We sum up the values.\r
+ int value;\r
+ int len;\r
+ char* p = FindToken(token);\r
+\r
+ if (p == 0)\r
+ throw LogicExceptionImpl("RB::GetCountValue", _("Token not found."));\r
+\r
+ // len is the number of bytes in the following array\r
+ len = (*gds.Call()->m_vax_integer)(p+1, 2);\r
+ p += 3;\r
+ value = 0;\r
+ while (len > 0)\r
+ {\r
+ // Each array item is 6 bytes : 2 bytes for the relation_id which\r
+ // we skip, and 4 bytes for the count value which we sum up accross\r
+ // all tables.\r
+ value += (*gds.Call()->m_vax_integer)(p+2, 4);\r
+ p += 6;\r
+ len -= 6;\r
+ }\r
+\r
+ return value;\r
+}\r
+\r
+int RB::GetValue(char token, char subtoken)\r
+{\r
+ int value;\r
+ int len;\r
+ char* p = FindToken(token, subtoken);\r
+\r
+ if (p == 0)\r
+ throw LogicExceptionImpl("RB::GetValue", _("Token/Subtoken not found."));\r
+\r
+ len = (*gds.Call()->m_vax_integer)(p+1, 2);\r
+ if (len == 0) value = 0;\r
+ else value = (*gds.Call()->m_vax_integer)(p+3, (short)len);\r
+\r
+ return value;\r
+}\r
+\r
+bool RB::GetBool(char token)\r
+{\r
+ int value;\r
+ char* p = FindToken(token);\r
+\r
+ if (p == 0)\r
+ throw LogicExceptionImpl("RB::GetBool", _("Token not found."));\r
+\r
+ value = (*gds.Call()->m_vax_integer)(p+1, 4);\r
+\r
+ return value == 0 ? false : true;\r
+}\r
+\r
+int RB::GetString(char token, std::string& data)\r
+{\r
+ int len;\r
+ char* p = FindToken(token);\r
+\r
+ if (p == 0)\r
+ throw LogicExceptionImpl("RB::GetString", _("Token not found."));\r
+\r
+ len = (*gds.Call()->m_vax_integer)(p+1, 2);\r
+ data = std::string(p+3, len);\r
+ return len;\r
+}\r
+\r
+void RB::Reset()\r
+{\r
+ delete [] mBuffer;\r
+ mBuffer = new char [mSize];\r
+ memset(mBuffer, 255, mSize);\r
+}\r
+\r
+RB::RB()\r
+{\r
+ mSize = 1024;\r
+ mBuffer = new char [1024];\r
+ memset(mBuffer, 255, mSize);\r
+}\r
+\r
+RB::RB(int Size)\r
+{\r
+ mSize = Size;\r
+ mBuffer = new char [Size];\r
+ memset(mBuffer, 255, mSize);\r
+}\r
+\r
+RB::~RB()\r
+{\r
+ try { delete [] mBuffer; }\r
+ catch (...) { }\r
+}\r
+\r
+//\r
+// EOF\r
+//\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: _spb.cpp,v 1.2 2009/03/19 20:00:27 faust Exp $\r
+// Subject : IBPP, internal SPB class implementation\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * SPB == Service Parameter Block/Buffer, see Interbase 6.0 C-API\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning(disable: 4786 4996)\r
+#ifndef _DEBUG\r
+#pragma warning(disable: 4702)\r
+#endif\r
+#endif\r
+\r
+#include "_ibpp.h"\r
+\r
+#ifdef HAS_HDRSTOP\r
+#pragma hdrstop\r
+#endif\r
+\r
+#include <cstring>\r
+\r
+using namespace ibpp_internals;\r
+\r
+const int SPB::BUFFERINCR = 128;\r
+\r
+void SPB::Grow(int needed)\r
+{\r
+ if ((mSize + needed) > mAlloc)\r
+ {\r
+ // We need to grow the buffer. We use increments of BUFFERINCR bytes.\r
+ needed = (needed / BUFFERINCR + 1) * BUFFERINCR;\r
+ char* newbuffer = new char[mAlloc + needed];\r
+ if (mBuffer != 0)\r
+ {\r
+ // Move the old buffer content to the new one\r
+ memcpy(newbuffer, mBuffer, mSize);\r
+ delete [] mBuffer;\r
+ }\r
+ mBuffer = newbuffer;\r
+ mAlloc += needed;\r
+ }\r
+}\r
+\r
+void SPB::Insert(char opcode)\r
+{\r
+ Grow(1);\r
+ mBuffer[mSize++] = opcode;\r
+}\r
+\r
+void SPB::InsertString(char type, int lenwidth, const char* data)\r
+{\r
+ int16_t len = (int16_t)strlen(data);\r
+\r
+ Grow(1 + lenwidth + len);\r
+ mBuffer[mSize++] = type;\r
+ switch (lenwidth)\r
+ {\r
+ case 1 : mBuffer[mSize] = char(len); mSize++; break;\r
+ case 2 : *(int16_t*)&mBuffer[mSize] = int16_t((*gds.Call()->m_vax_integer)((char*)&len, 2));\r
+ mSize += 2; break;\r
+ default : throw LogicExceptionImpl("IISPB::IISPB", _("Invalid length parameter"));\r
+ }\r
+ strncpy(&mBuffer[mSize], data, len);\r
+ mSize += len;\r
+}\r
+\r
+void SPB::InsertByte(char type, char data)\r
+{\r
+ Grow(1 + 1);\r
+ mBuffer[mSize++] = type;\r
+ mBuffer[mSize++] = data;\r
+}\r
+\r
+void SPB::InsertQuad(char type, int32_t data)\r
+{\r
+ Grow(1 + 4);\r
+ mBuffer[mSize++] = type;\r
+ *(int32_t*)&mBuffer[mSize] = int32_t((*gds.Call()->m_vax_integer)((char*)&data, 4));\r
+ mSize += 4;\r
+}\r
+\r
+void SPB::Reset()\r
+{\r
+ if (mBuffer != 0)\r
+ {\r
+ delete [] mBuffer;\r
+ mBuffer = 0;\r
+ mSize = 0;\r
+ mAlloc = 0;\r
+ }\r
+}\r
+\r
+/*\r
+void SPB::Insert(char type, short data)\r
+{\r
+ Grow(1 + 3);\r
+ mBuffer[mSize++] = type;\r
+ mBuffer[mSize++] = char(2);\r
+ *(short*)&mBuffer[mSize] = data;\r
+ mSize += 2;\r
+}\r
+\r
+void SPB::Insert(char type, bool data)\r
+{\r
+ Grow(1 + 2);\r
+ mBuffer[mSize++] = type;\r
+ mBuffer[mSize++] = char(1);\r
+ mBuffer[mSize++] = char(data ? 1 : 0);\r
+}\r
+*/\r
+\r
+//\r
+// EOF\r
+//\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: _tpb.cpp,v 1.2 2009/03/19 20:00:28 faust Exp $\r
+// Subject : IBPP, internal TPB class implementation\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * TPB == Transaction Parameter Block/Buffer, see Interbase 6.0 C-API\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning(disable: 4786 4996)\r
+#ifndef _DEBUG\r
+#pragma warning(disable: 4702)\r
+#endif\r
+#endif\r
+\r
+#include "_ibpp.h"\r
+\r
+#ifdef HAS_HDRSTOP\r
+#pragma hdrstop\r
+#endif\r
+\r
+#include <cstring>\r
+\r
+using namespace ibpp_internals;\r
+\r
+const int TPB::BUFFERINCR = 128;\r
+\r
+void TPB::Grow(int needed)\r
+{\r
+ if (mBuffer == 0) ++needed; // Initial alloc will require one more byte\r
+ if ((mSize + needed) > mAlloc)\r
+ {\r
+ // We need to grow the buffer. We use increments of BUFFERINCR bytes.\r
+ needed = (needed / BUFFERINCR + 1) * BUFFERINCR;\r
+ char* newbuffer = new char[mAlloc + needed];\r
+ if (mBuffer == 0)\r
+ {\r
+ // Initial allocation, initialize the version tag\r
+ newbuffer[0] = isc_tpb_version3;\r
+ mSize = 1;\r
+ }\r
+ else\r
+ {\r
+ // Move the old buffer content to the new one\r
+ memcpy(newbuffer, mBuffer, mSize);\r
+ delete [] mBuffer;\r
+ }\r
+ mBuffer = newbuffer;\r
+ mAlloc += needed;\r
+ }\r
+}\r
+\r
+void TPB::Insert(char item)\r
+{\r
+ Grow(1);\r
+ mBuffer[mSize++] = item;\r
+}\r
+\r
+void TPB::Insert(const std::string& data)\r
+{\r
+ int len = (int)data.length();\r
+ Grow(1 + len);\r
+ mBuffer[mSize++] = (char)len;\r
+ strncpy(&mBuffer[mSize], data.c_str(), len);\r
+ mSize += len;\r
+}\r
+\r
+void TPB::Reset()\r
+{\r
+ if (mSize != 0)\r
+ {\r
+ delete [] mBuffer;\r
+ mBuffer = 0;\r
+ mSize = 0;\r
+ mAlloc = 0;\r
+ }\r
+}\r
+\r
+//\r
+// EOF\r
+//\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: all_in_one.cpp,v 1.1 2007/05/05 17:00:42 faust Exp $\r
+// Subject : "All In One" source code file\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * Tabulations should be set every four characters when editing this file.\r
+// * This file is just an "all in one" holder for all the core source files\r
+// of IBPP. When you build a project made of each individual source code\r
+// files, please DON'T include this one.\r
+// Though if you prefer, maybe for better compiler optimizations, you can\r
+// compile all of IBPP at once by just compiling this single .cpp file,\r
+// which in turn, includes all the others. Presenting such a single\r
+// compilation unit to the compiler may help it do better optimizations.\r
+// This is just provided for convenience and is in no case required.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#include "_ibpp.cpp"\r
+#include "_dpb.cpp"\r
+#include "_ibs.cpp"\r
+#include "_rb.cpp"\r
+#include "_spb.cpp"\r
+#include "_tpb.cpp"\r
+\r
+#include "array.cpp"\r
+#include "blob.cpp"\r
+#include "database.cpp"\r
+#include "date.cpp"\r
+#include "dbkey.cpp"\r
+#include "events.cpp"\r
+#include "exception.cpp"\r
+#include "row.cpp"\r
+#include "service.cpp"\r
+#include "statement.cpp"\r
+#include "time.cpp"\r
+#include "transaction.cpp"\r
+#include "user.cpp"\r
+\r
+// Eof\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: array.cpp,v 1.2 2009/03/19 20:00:28 faust Exp $\r
+// Subject : IBPP, Array class implementation\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning(disable: 4786 4996)\r
+#ifndef _DEBUG\r
+#pragma warning(disable: 4702)\r
+#endif\r
+#endif\r
+\r
+#include "_ibpp.h"\r
+\r
+#ifdef HAS_HDRSTOP\r
+#pragma hdrstop\r
+#endif\r
+\r
+#include <math.h>\r
+#include <cstring>\r
+\r
+using namespace ibpp_internals;\r
+\r
+// (((((((( OBJECT INTERFACE IMPLEMENTATION ))))))))\r
+\r
+void ArrayImpl::Describe(const std::string& table, const std::string& column)\r
+{\r
+ //if (mIdAssigned)\r
+ // throw LogicExceptionImpl("Array::Lookup", _("Array already in use."));\r
+ if (mDatabase == 0)\r
+ throw LogicExceptionImpl("Array::Lookup", _("No Database is attached."));\r
+ if (mTransaction == 0)\r
+ throw LogicExceptionImpl("Array::Lookup", _("No Transaction is attached."));\r
+\r
+ ResetId(); // Re-use this array object if was previously assigned\r
+\r
+ IBS status;\r
+ (*gds.Call()->m_array_lookup_bounds)(status.Self(), mDatabase->GetHandlePtr(),\r
+ mTransaction->GetHandlePtr(), const_cast<char*>(table.c_str()),\r
+ const_cast<char*>(column.c_str()), &mDesc);\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Array::Lookup",\r
+ _("isc_array_lookup_bounds failed."));\r
+\r
+ AllocArrayBuffer();\r
+\r
+ mDescribed = true;\r
+}\r
+\r
+void ArrayImpl::SetBounds(int dim, int low, int high)\r
+{\r
+ if (! mDescribed)\r
+ throw LogicExceptionImpl("Array::SetBounds", _("Array description not set."));\r
+ if (mDatabase == 0)\r
+ throw LogicExceptionImpl("Array::SetBounds", _("No Database is attached."));\r
+ if (mTransaction == 0)\r
+ throw LogicExceptionImpl("Array::SetBounds", _("No Transaction is attached."));\r
+ if (dim < 0 || dim > mDesc.array_desc_dimensions-1)\r
+ throw LogicExceptionImpl("Array::SetBounds", _("Invalid dimension."));\r
+ if (low > high ||\r
+ low < mDesc.array_desc_bounds[dim].array_bound_lower ||\r
+ low > mDesc.array_desc_bounds[dim].array_bound_upper ||\r
+ high > mDesc.array_desc_bounds[dim].array_bound_upper ||\r
+ high < mDesc.array_desc_bounds[dim].array_bound_lower)\r
+ throw LogicExceptionImpl("Array::SetBounds",\r
+ _("Invalid bounds. You can only narrow the bounds."));\r
+\r
+ mDesc.array_desc_bounds[dim].array_bound_lower = short(low);\r
+ mDesc.array_desc_bounds[dim].array_bound_upper = short(high);\r
+\r
+ AllocArrayBuffer();\r
+}\r
+\r
+IBPP::SDT ArrayImpl::ElementType()\r
+{\r
+ if (! mDescribed)\r
+ throw LogicExceptionImpl("Array::ElementType",\r
+ _("Array description not set."));\r
+\r
+ IBPP::SDT value;\r
+ switch (mDesc.array_desc_dtype)\r
+ {\r
+ case blr_text : value = IBPP::sdString; break;\r
+ case blr_varying : value = IBPP::sdString; break;\r
+ case blr_cstring : value = IBPP::sdString; break;\r
+ case blr_short : value = IBPP::sdSmallint; break;\r
+ case blr_long : value = IBPP::sdInteger; break;\r
+ case blr_int64 : value = IBPP::sdLargeint; break;\r
+ case blr_float : value = IBPP::sdFloat; break;\r
+ case blr_double : value = IBPP::sdDouble; break;\r
+ case blr_timestamp : value = IBPP::sdTimestamp; break;\r
+ case blr_sql_date : value = IBPP::sdDate; break;\r
+ case blr_sql_time : value = IBPP::sdTime; break;\r
+ default : throw LogicExceptionImpl("Array::ElementType",\r
+ _("Found an unknown sqltype !"));\r
+ }\r
+\r
+ return value;\r
+}\r
+\r
+int ArrayImpl::ElementSize()\r
+{\r
+ if (! mDescribed)\r
+ throw LogicExceptionImpl("Array::ElementSize",\r
+ _("Array description not set."));\r
+\r
+ return mDesc.array_desc_length;\r
+}\r
+\r
+int ArrayImpl::ElementScale()\r
+{\r
+ if (! mDescribed)\r
+ throw LogicExceptionImpl("Array::ElementScale",\r
+ _("Array description not set."));\r
+\r
+ return mDesc.array_desc_scale;\r
+}\r
+\r
+int ArrayImpl::Dimensions()\r
+{\r
+ if (! mDescribed)\r
+ throw LogicExceptionImpl("Array::Dimensions",\r
+ _("Array description not set."));\r
+\r
+ return mDesc.array_desc_dimensions;\r
+}\r
+\r
+void ArrayImpl::Bounds(int dim, int* low, int* high)\r
+{\r
+ if (! mDescribed)\r
+ throw LogicExceptionImpl("Array::Bounds", _("Array description not set."));\r
+ if (dim < 0 || dim > mDesc.array_desc_dimensions-1)\r
+ throw LogicExceptionImpl("Array::Bounds", _("Invalid dimension."));\r
+ if (low == 0 || high == 0)\r
+ throw LogicExceptionImpl("Array::Bounds", _("Null reference detected."));\r
+\r
+ *low = mDesc.array_desc_bounds[dim].array_bound_lower;\r
+ *high = mDesc.array_desc_bounds[dim].array_bound_upper;\r
+}\r
+\r
+/*\r
+\r
+COMMENTS\r
+\r
+1)\r
+For an array column of type CHAR(X), the internal type returned or expected is blr_text.\r
+In such case, the byte array received or submitted to get/put_slice is formatted in\r
+elements of X bytes, which correspond to what is reported in array_desc_length.\r
+The elements are not '\0' terminated but are right-padded with spaces ' '.\r
+\r
+2)\r
+For an array column of type VARCHAR(X), the internal type is blr_varying.\r
+The underlying format is rather curious and different than what is used in XSQLDA.\r
+The element size is reported in array_desc_length as X.\r
+Yet each element of the byte array is expected to be of size X+2 (just as if we were\r
+to stuff a short in the first 2 bytes to store the length (as is done with XSQLDA).\r
+No. The string of X characters maximum has to be stored in the chunks of X+2 bytes as\r
+a zero-terminated c-string. Note that the buffer is indeed one byte too large.\r
+Internally, the API probably convert in-place in these chunks the zero-terminated string\r
+to a variable-size string with a short in front and the string data non zero-terminated\r
+behind.\r
+\r
+3)\r
+With Interbase 6.0 and Firebird 1.0 (initial april 2002 release), the int64 support is\r
+broken regarding the arrays. It is not possible to work on arrays using a datatype stored\r
+in an int64, as for instance any NUMERIC(x,0) where x is equal or greater than 10. That's\r
+a bug in the engine, not in IBPP, which has been fixed in june 2002. Engines compiled from\r
+the current Firebird CVS code as of july 2002 are okay. As will be the 1.01 Firebird version.\r
+We have no idea if this is fixed or not in Interbase 6.5 though.\r
+\r
+*/\r
+\r
+void ArrayImpl::ReadTo(IBPP::ADT adtype, void* data, int datacount)\r
+{\r
+ if (! mIdAssigned)\r
+ throw LogicExceptionImpl("Array::ReadTo", _("Array Id not read from column."));\r
+ if (! mDescribed)\r
+ throw LogicExceptionImpl("Array::ReadTo", _("Array description not set."));\r
+ if (mDatabase == 0)\r
+ throw LogicExceptionImpl("Array::ReadTo", _("No Database is attached."));\r
+ if (mTransaction == 0)\r
+ throw LogicExceptionImpl("Array::ReadTo", _("No Transaction is attached."));\r
+ if (datacount != mElemCount)\r
+ throw LogicExceptionImpl("Array::ReadTo", _("Wrong count of array elements"));\r
+\r
+ IBS status;\r
+ ISC_LONG lenbuf = mBufferSize;\r
+ (*gds.Call()->m_array_get_slice)(status.Self(), mDatabase->GetHandlePtr(),\r
+ mTransaction->GetHandlePtr(), &mId, &mDesc, mBuffer, &lenbuf);\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Array::ReadTo", _("isc_array_get_slice failed."));\r
+ if (lenbuf != mBufferSize)\r
+ throw SQLExceptionImpl(status, "Array::ReadTo", _("Internal buffer size discrepancy."));\r
+\r
+ // Now, convert the types and copy values to the user array...\r
+ int len;\r
+ char* src = (char*)mBuffer;\r
+ char* dst = (char*)data;\r
+\r
+ switch (mDesc.array_desc_dtype)\r
+ {\r
+ case blr_text :\r
+ if (adtype == IBPP::adString)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ strncpy(dst, src, mElemSize);\r
+ dst[mElemSize] = '\0';\r
+ src += mElemSize;\r
+ dst += (mElemSize + 1);\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adBool)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ if (*src == 't' || *src == 'T' || *src == 'y' || *src == 'Y' || *src == '1')\r
+ *(bool*)dst = true;\r
+ else *(bool*)dst = false;\r
+ src += mElemSize;\r
+ dst += sizeof(bool);\r
+ }\r
+ }\r
+ else throw LogicExceptionImpl("Array::ReadTo", _("Incompatible types."));\r
+ break;\r
+\r
+ case blr_varying :\r
+ if (adtype == IBPP::adString)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ len = (int)strlen(src);\r
+ if (len > mElemSize-2) len = mElemSize-2;\r
+ strncpy(dst, src, len);\r
+ dst[len] = '\0';\r
+ src += mElemSize;\r
+ dst += (mElemSize - 2 + 1);\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adBool)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ if (*src == 't' || *src == 'T' || *src == 'y' || *src == 'Y' || *src == '1')\r
+ *(bool*)dst = true;\r
+ else *(bool*)dst = false;\r
+ src += mElemSize;\r
+ dst += sizeof(bool);\r
+ }\r
+ }\r
+ else throw LogicExceptionImpl("Array::ReadTo", _("Incompatible types."));\r
+ break;\r
+\r
+ case blr_short :\r
+ if (adtype == IBPP::adBool)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(bool*)dst = (*(short*)src != 0) ? true : false;\r
+ src += mElemSize;\r
+ dst += sizeof(bool);\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adInt16)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(short*)dst = *(short*)src;\r
+ src += mElemSize;\r
+ dst += sizeof(short);\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adInt32)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(int*)dst = (int)*(short*)src;\r
+ src += mElemSize;\r
+ dst += sizeof(int);\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adInt64)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(int64_t*)dst = (int64_t)*(short*)src;\r
+ src += mElemSize;\r
+ dst += sizeof(int64_t);\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adFloat)\r
+ {\r
+ // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
+ double divisor = consts::dscales[-mDesc.array_desc_scale];\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(float*)dst = (float)(*(short*)src / divisor);\r
+ src += mElemSize;\r
+ dst += sizeof(float);\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adDouble)\r
+ {\r
+ // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
+ double divisor = consts::dscales[-mDesc.array_desc_scale];\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(double*)dst = (double)(*(short*)src / divisor);\r
+ src += mElemSize;\r
+ dst += sizeof(double);\r
+ }\r
+ }\r
+ else throw LogicExceptionImpl("Array::ReadTo", _("Incompatible types."));\r
+ break;\r
+\r
+ case blr_long :\r
+ if (adtype == IBPP::adBool)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(bool*)dst = (*(long*)src != 0) ? true : false;\r
+ src += mElemSize;\r
+ dst += sizeof(bool);\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adInt16)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ if (*(long*)src < consts::min16 || *(long*)src > consts::max16)\r
+ throw LogicExceptionImpl("Array::ReadTo",\r
+ _("Out of range numeric conversion !"));\r
+ *(short*)dst = short(*(long*)src);\r
+ src += mElemSize;\r
+ dst += sizeof(short);\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adInt32)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(long*)dst = *(long*)src;\r
+ src += mElemSize;\r
+ dst += sizeof(long);\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adInt64)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(int64_t*)dst = (int64_t)*(long*)src;\r
+ src += mElemSize;\r
+ dst += sizeof(int64_t);\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adFloat)\r
+ {\r
+ // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
+ double divisor = consts::dscales[-mDesc.array_desc_scale];\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(float*)dst = (float)(*(long*)src / divisor);\r
+ src += mElemSize;\r
+ dst += sizeof(float);\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adDouble)\r
+ {\r
+ // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
+ double divisor = consts::dscales[-mDesc.array_desc_scale];\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(double*)dst = (double)(*(long*)src / divisor);\r
+ src += mElemSize;\r
+ dst += sizeof(double);\r
+ }\r
+ }\r
+ else throw LogicExceptionImpl("Array::ReadTo", _("Incompatible types."));\r
+ break;\r
+\r
+ case blr_int64 :\r
+ if (adtype == IBPP::adBool)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(bool*)dst = (*(int64_t*)src != 0) ? true : false;\r
+ src += mElemSize;\r
+ dst += sizeof(bool);\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adInt16)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ if (*(int64_t*)src < consts::min16 || *(int64_t*)src > consts::max16)\r
+ throw LogicExceptionImpl("Array::ReadTo",\r
+ _("Out of range numeric conversion !"));\r
+ *(short*)dst = short(*(int64_t*)src);\r
+ src += mElemSize;\r
+ dst += sizeof(short);\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adInt32)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ if (*(int64_t*)src < consts::min32 || *(int64_t*)src > consts::max32)\r
+ throw LogicExceptionImpl("Array::ReadTo",\r
+ _("Out of range numeric conversion !"));\r
+ *(long*)dst = (long)*(int64_t*)src;\r
+ src += mElemSize;\r
+ dst += sizeof(long);\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adInt64)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(int64_t*)dst = *(int64_t*)src;\r
+ src += mElemSize;\r
+ dst += sizeof(int64_t);\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adFloat)\r
+ {\r
+ // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
+ double divisor = consts::dscales[-mDesc.array_desc_scale];\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(float*)dst = (float)(*(int64_t*)src / divisor);\r
+ src += mElemSize;\r
+ dst += sizeof(float);\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adDouble)\r
+ {\r
+ // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
+ double divisor = consts::dscales[-mDesc.array_desc_scale];\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(double*)dst = (double)(*(int64_t*)src / divisor);\r
+ src += mElemSize;\r
+ dst += sizeof(double);\r
+ }\r
+ }\r
+ else throw LogicExceptionImpl("Array::ReadTo", _("Incompatible types."));\r
+ break;\r
+\r
+ case blr_float :\r
+ if (adtype != IBPP::adFloat || mDesc.array_desc_scale != 0)\r
+ throw LogicExceptionImpl("Array::ReadTo", _("Incompatible types."));\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(float*)dst = *(float*)src;\r
+ src += mElemSize;\r
+ dst += sizeof(float);\r
+ }\r
+ break;\r
+\r
+ case blr_double :\r
+ if (adtype != IBPP::adDouble) throw LogicExceptionImpl("Array::ReadTo",\r
+ _("Incompatible types."));\r
+ if (mDesc.array_desc_scale != 0)\r
+ {\r
+ // Round to scale of NUMERIC(x,y)\r
+ double divisor = consts::dscales[-mDesc.array_desc_scale];\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(double*)dst = (double)(*(double*)src / divisor);\r
+ src += mElemSize;\r
+ dst += sizeof(double);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(double*)dst = *(double*)src;\r
+ src += mElemSize;\r
+ dst += sizeof(double);\r
+ }\r
+ }\r
+ break;\r
+\r
+ case blr_timestamp :\r
+ if (adtype != IBPP::adTimestamp) throw LogicExceptionImpl("Array::ReadTo",\r
+ _("Incompatible types."));\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ decodeTimestamp(*(IBPP::Timestamp*)dst, *(ISC_TIMESTAMP*)src);\r
+ src += mElemSize;\r
+ dst += sizeof(IBPP::Timestamp);\r
+ }\r
+ break;\r
+\r
+ case blr_sql_date :\r
+ if (adtype != IBPP::adDate) throw LogicExceptionImpl("Array::ReadTo",\r
+ _("Incompatible types."));\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ decodeDate(*(IBPP::Date*)dst, *(ISC_DATE*)src);\r
+ src += mElemSize;\r
+ dst += sizeof(IBPP::Date);\r
+ }\r
+ break;\r
+\r
+ case blr_sql_time :\r
+ if (adtype != IBPP::adTime) throw LogicExceptionImpl("Array::ReadTo",\r
+ _("Incompatible types."));\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ decodeTime(*(IBPP::Time*)dst, *(ISC_TIME*)src);\r
+ src += mElemSize;\r
+ dst += sizeof(IBPP::Time);\r
+ }\r
+ break;\r
+\r
+ default :\r
+ throw LogicExceptionImpl("Array::ReadTo", _("Unknown sql type."));\r
+ }\r
+}\r
+\r
+void ArrayImpl::WriteFrom(IBPP::ADT adtype, const void* data, int datacount)\r
+{\r
+ if (! mDescribed)\r
+ throw LogicExceptionImpl("Array::WriteFrom", _("Array description not set."));\r
+ if (mDatabase == 0)\r
+ throw LogicExceptionImpl("Array::WriteFrom", _("No Database is attached."));\r
+ if (mTransaction == 0)\r
+ throw LogicExceptionImpl("Array::WriteFrom", _("No Transaction is attached."));\r
+ if (datacount != mElemCount)\r
+ throw LogicExceptionImpl("Array::ReadTo", _("Wrong count of array elements"));\r
+\r
+ // Read user data and convert types to the mBuffer\r
+ int len;\r
+ char* src = (char*)data;\r
+ char* dst = (char*)mBuffer;\r
+\r
+ switch (mDesc.array_desc_dtype)\r
+ {\r
+ case blr_text :\r
+ if (adtype == IBPP::adString)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ len = (int)strlen(src);\r
+ if (len > mElemSize) len = mElemSize;\r
+ strncpy(dst, src, len);\r
+ while (len < mElemSize) dst[len++] = ' ';\r
+ src += (mElemSize + 1);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adBool)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *dst = *(bool*)src ? 'T' : 'F';\r
+ len = 1;\r
+ while (len < mElemSize) dst[len++] = ' ';\r
+ src += sizeof(bool);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else throw LogicExceptionImpl("Array::WriteFrom", _("Incompatible types."));\r
+ break;\r
+\r
+ case blr_varying :\r
+ if (adtype == IBPP::adString)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ len = (int)strlen(src);\r
+ if (len > mElemSize-2) len = mElemSize-2;\r
+ strncpy(dst, src, len);\r
+ dst[len] = '\0';\r
+ src += (mElemSize - 2 + 1);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adBool)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(short*)dst = (short)1;\r
+ dst[2] = *(bool*)src ? 'T' : 'F';\r
+ src += sizeof(bool);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else throw LogicExceptionImpl("Array::WriteFrom", _("Incompatible types."));\r
+ break;\r
+\r
+ case blr_short :\r
+ if (adtype == IBPP::adBool)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(short*)dst = short(*(bool*)src ? 1 : 0);\r
+ src += sizeof(bool);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adInt16)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(short*)dst = *(short*)src;\r
+ src += sizeof(short);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adInt32)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ if (*(long*)src < consts::min16 || *(long*)src > consts::max16)\r
+ throw LogicExceptionImpl("Array::WriteFrom",\r
+ _("Out of range numeric conversion !"));\r
+ *(short*)dst = (short)*(int*)src;\r
+ src += sizeof(int);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adInt64)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ if (*(int64_t*)src < consts::min16 || *(int64_t*)src > consts::max16)\r
+ throw LogicExceptionImpl("Array::WriteFrom",\r
+ _("Out of range numeric conversion !"));\r
+ *(short*)dst = (short)*(int64_t*)src;\r
+ src += sizeof(int64_t);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adFloat)\r
+ {\r
+ // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
+ double multiplier = consts::dscales[-mDesc.array_desc_scale];\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(short*)dst =\r
+ (short)floor(*(float*)src * multiplier + 0.5);\r
+ src += sizeof(float);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adDouble)\r
+ {\r
+ // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
+ double multiplier = consts::dscales[-mDesc.array_desc_scale];\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(short*)dst =\r
+ (short)floor(*(double*)src * multiplier + 0.5);\r
+ src += sizeof(double);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else throw LogicExceptionImpl("Array::WriteFrom", _("Incompatible types."));\r
+ break;\r
+\r
+ case blr_long :\r
+ if (adtype == IBPP::adBool)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(long*)dst = *(bool*)src ? 1 : 0;\r
+ src += sizeof(bool);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adInt16)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(long*)dst = *(short*)src;\r
+ src += sizeof(short);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adInt32)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(long*)dst = *(long*)src;\r
+ src += sizeof(long);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adInt64)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ if (*(int64_t*)src < consts::min32 || *(int64_t*)src > consts::max32)\r
+ throw LogicExceptionImpl("Array::WriteFrom",\r
+ _("Out of range numeric conversion !"));\r
+ *(long*)dst = (long)*(int64_t*)src;\r
+ src += sizeof(int64_t);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adFloat)\r
+ {\r
+ // This SQL_INT is a NUMERIC(x,y), scale it !\r
+ double multiplier = consts::dscales[-mDesc.array_desc_scale];\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(long*)dst =\r
+ (long)floor(*(float*)src * multiplier + 0.5);\r
+ src += sizeof(float);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adDouble)\r
+ {\r
+ // This SQL_INT is a NUMERIC(x,y), scale it !\r
+ double multiplier = consts::dscales[-mDesc.array_desc_scale];\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(long*)dst =\r
+ (long)floor(*(double*)src * multiplier + 0.5);\r
+ src += sizeof(double);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else throw LogicExceptionImpl("Array::WriteFrom", _("Incompatible types."));\r
+ break;\r
+\r
+ case blr_int64 :\r
+ if (adtype == IBPP::adBool)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(int64_t*)dst = *(bool*)src ? 1 : 0;\r
+ src += sizeof(bool);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adInt16)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(int64_t*)dst = *(short*)src;\r
+ src += sizeof(short);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adInt32)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(int64_t*)dst = *(long*)src;\r
+ src += sizeof(long);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adInt64)\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(int64_t*)dst = *(int64_t*)src;\r
+ src += sizeof(int64_t);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adFloat)\r
+ {\r
+ // This SQL_INT is a NUMERIC(x,y), scale it !\r
+ double multiplier = consts::dscales[-mDesc.array_desc_scale];\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(int64_t*)dst =\r
+ (int64_t)floor(*(float*)src * multiplier + 0.5);\r
+ src += sizeof(float);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else if (adtype == IBPP::adDouble)\r
+ {\r
+ // This SQL_INT is a NUMERIC(x,y), scale it !\r
+ double multiplier = consts::dscales[-mDesc.array_desc_scale];\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(int64_t*)dst =\r
+ (int64_t)floor(*(double*)src * multiplier + 0.5);\r
+ src += sizeof(double);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else\r
+ throw LogicExceptionImpl("Array::WriteFrom",\r
+ _("Incompatible types (blr_int64 and ADT %d)."), (int)adtype);\r
+ break;\r
+\r
+ case blr_float :\r
+ if (adtype != IBPP::adFloat || mDesc.array_desc_scale != 0)\r
+ throw LogicExceptionImpl("Array::WriteFrom", _("Incompatible types."));\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(float*)dst = *(float*)src;\r
+ src += sizeof(float);\r
+ dst += mElemSize;\r
+ }\r
+ break;\r
+\r
+ case blr_double :\r
+ if (adtype != IBPP::adDouble) throw LogicExceptionImpl("Array::WriteFrom",\r
+ _("Incompatible types."));\r
+ if (mDesc.array_desc_scale != 0)\r
+ {\r
+ // Round to scale of NUMERIC(x,y)\r
+ double multiplier = consts::dscales[-mDesc.array_desc_scale];\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(double*)dst =\r
+ floor(*(double*)src * multiplier + 0.5) / multiplier;\r
+ src += sizeof(double);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ *(double*)dst = *(double*)src;\r
+ src += sizeof(double);\r
+ dst += mElemSize;\r
+ }\r
+ }\r
+ break;\r
+\r
+ case blr_timestamp :\r
+ if (adtype != IBPP::adTimestamp) throw LogicExceptionImpl("Array::ReadTo",\r
+ _("Incompatible types."));\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ encodeTimestamp(*(ISC_TIMESTAMP*)dst, *(IBPP::Timestamp*)src);\r
+ src += sizeof(IBPP::Timestamp);\r
+ dst += mElemSize;\r
+ }\r
+ break;\r
+\r
+ case blr_sql_date :\r
+ if (adtype != IBPP::adDate) throw LogicExceptionImpl("Array::ReadTo",\r
+ _("Incompatible types."));\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ encodeDate(*(ISC_DATE*)dst, *(IBPP::Date*)src); \r
+ src += sizeof(IBPP::Date);\r
+ dst += mElemSize;\r
+ }\r
+ break;\r
+\r
+ case blr_sql_time :\r
+ if (adtype != IBPP::adTime) throw LogicExceptionImpl("Array::ReadTo",\r
+ _("Incompatible types."));\r
+ for (int i = 0; i < mElemCount; i++)\r
+ {\r
+ encodeTime(*(ISC_TIME*)dst, *(IBPP::Time*)src);\r
+ src += sizeof(IBPP::Time);\r
+ dst += mElemSize;\r
+ }\r
+ break;\r
+\r
+ default :\r
+ throw LogicExceptionImpl("Array::WriteFrom", _("Unknown sql type."));\r
+ }\r
+\r
+ IBS status;\r
+ ISC_LONG lenbuf = mBufferSize;\r
+ (*gds.Call()->m_array_put_slice)(status.Self(), mDatabase->GetHandlePtr(),\r
+ mTransaction->GetHandlePtr(), &mId, &mDesc, mBuffer, &lenbuf);\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Array::WriteFrom", _("isc_array_put_slice failed."));\r
+ if (lenbuf != mBufferSize)\r
+ throw SQLExceptionImpl(status, "Array::WriteFrom", _("Internal buffer size discrepancy."));\r
+}\r
+\r
+IBPP::Database ArrayImpl::DatabasePtr() const\r
+{\r
+ if (mDatabase == 0) throw LogicExceptionImpl("Array::DatabasePtr",\r
+ _("No Database is attached."));\r
+ return mDatabase;\r
+}\r
+\r
+IBPP::Transaction ArrayImpl::TransactionPtr() const\r
+{\r
+ if (mTransaction == 0) throw LogicExceptionImpl("Array::TransactionPtr",\r
+ _("No Transaction is attached."));\r
+ return mTransaction;\r
+}\r
+\r
+IBPP::IArray* ArrayImpl::AddRef()\r
+{\r
+ ASSERTION(mRefCount >= 0);\r
+ ++mRefCount;\r
+ return this;\r
+}\r
+\r
+void ArrayImpl::Release()\r
+{\r
+ // Release cannot throw, except in DEBUG builds on assertion\r
+ ASSERTION(mRefCount >= 0);\r
+ --mRefCount;\r
+ try { if (mRefCount <= 0) delete this; }\r
+ catch (...) { }\r
+}\r
+\r
+// (((((((( OBJECT INTERNAL METHODS ))))))))\r
+\r
+void ArrayImpl::Init()\r
+{\r
+ ResetId();\r
+ mDescribed = false;\r
+ mDatabase = 0;\r
+ mTransaction = 0;\r
+ mBuffer = 0;\r
+ mBufferSize = 0;\r
+}\r
+\r
+void ArrayImpl::SetId(ISC_QUAD* quad)\r
+{\r
+ if (quad == 0)\r
+ throw LogicExceptionImpl("ArrayImpl::SetId", _("Null Id reference detected."));\r
+\r
+ memcpy(&mId, quad, sizeof(mId));\r
+ mIdAssigned = true;\r
+}\r
+\r
+void ArrayImpl::GetId(ISC_QUAD* quad)\r
+{\r
+ if (quad == 0)\r
+ throw LogicExceptionImpl("ArrayImpl::GetId", _("Null Id reference detected."));\r
+\r
+ memcpy(quad, &mId, sizeof(mId));\r
+}\r
+\r
+void ArrayImpl::ResetId()\r
+{\r
+ memset(&mId, 0, sizeof(mId));\r
+ mIdAssigned = false;\r
+}\r
+\r
+void ArrayImpl::AllocArrayBuffer()\r
+{\r
+ // Clean previous buffer if any\r
+ if (mBuffer != 0) delete [] (char*)mBuffer;\r
+ mBuffer = 0;\r
+\r
+ // Computes total number of elements in the array or slice\r
+ mElemCount = 1;\r
+ for (int i = 0; i < mDesc.array_desc_dimensions; i++)\r
+ {\r
+ mElemCount = mElemCount *\r
+ (mDesc.array_desc_bounds[i].array_bound_upper -\r
+ mDesc.array_desc_bounds[i].array_bound_lower + 1);\r
+ }\r
+\r
+ // Allocates a buffer for this count of elements\r
+ mElemSize = mDesc.array_desc_length;\r
+ if (mDesc.array_desc_dtype == blr_varying) mElemSize += 2;\r
+ else if (mDesc.array_desc_dtype == blr_cstring) mElemSize += 1;\r
+ mBufferSize = mElemSize * mElemCount;\r
+ mBuffer = (void*) new char[mBufferSize];\r
+}\r
+\r
+void ArrayImpl::AttachDatabaseImpl(DatabaseImpl* database)\r
+{\r
+ if (database == 0) throw LogicExceptionImpl("Array::AttachDatabase",\r
+ _("Can't attach a 0 Database object."));\r
+\r
+ if (mDatabase != 0) mDatabase->DetachArrayImpl(this);\r
+ mDatabase = database;\r
+ mDatabase->AttachArrayImpl(this);\r
+}\r
+\r
+void ArrayImpl::AttachTransactionImpl(TransactionImpl* transaction)\r
+{\r
+ if (transaction == 0) throw LogicExceptionImpl("Array::AttachTransaction",\r
+ _("Can't attach a 0 Transaction object."));\r
+\r
+ if (mTransaction != 0) mTransaction->DetachArrayImpl(this);\r
+ mTransaction = transaction;\r
+ mTransaction->AttachArrayImpl(this);\r
+}\r
+\r
+void ArrayImpl::DetachDatabaseImpl()\r
+{\r
+ if (mDatabase == 0) return;\r
+\r
+ mDatabase->DetachArrayImpl(this);\r
+ mDatabase = 0;\r
+}\r
+\r
+void ArrayImpl::DetachTransactionImpl()\r
+{\r
+ if (mTransaction == 0) return;\r
+\r
+ mTransaction->DetachArrayImpl(this);\r
+ mTransaction = 0;\r
+}\r
+\r
+ArrayImpl::ArrayImpl(DatabaseImpl* database, TransactionImpl* transaction)\r
+ : mRefCount(0)\r
+{\r
+ Init();\r
+ AttachDatabaseImpl(database);\r
+ if (transaction != 0) AttachTransactionImpl(transaction);\r
+}\r
+\r
+ArrayImpl::~ArrayImpl()\r
+{\r
+ try { if (mTransaction != 0) mTransaction->DetachArrayImpl(this); }\r
+ catch (...) {}\r
+ try { if (mDatabase != 0) mDatabase->DetachArrayImpl(this); }\r
+ catch (...) {}\r
+ try { if (mBuffer != 0) delete [] (char*)mBuffer; }\r
+ catch (...) {}\r
+}\r
+\r
+//\r
+// EOF\r
+//\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: blob.cpp,v 1.2 2009/03/19 20:00:28 faust Exp $\r
+// Subject : IBPP, Blob class implementation\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning(disable: 4786 4996)\r
+#ifndef _DEBUG\r
+#pragma warning(disable: 4702)\r
+#endif\r
+#endif\r
+\r
+#include "_ibpp.h"\r
+\r
+#ifdef HAS_HDRSTOP\r
+#pragma hdrstop\r
+#endif\r
+\r
+#include <cstring>\r
+\r
+using namespace ibpp_internals;\r
+\r
+// (((((((( OBJECT INTERFACE IMPLEMENTATION ))))))))\r
+\r
+void BlobImpl::Open()\r
+{\r
+ if (mHandle != 0)\r
+ throw LogicExceptionImpl("Blob::Open", _("Blob already opened."));\r
+ if (mDatabase == 0)\r
+ throw LogicExceptionImpl("Blob::Open", _("No Database is attached."));\r
+ if (mTransaction == 0)\r
+ throw LogicExceptionImpl("Blob::Open", _("No Transaction is attached."));\r
+ if (! mIdAssigned)\r
+ throw LogicExceptionImpl("Blob::Open", _("Blob Id is not assigned."));\r
+\r
+ IBS status;\r
+ (*gds.Call()->m_open_blob2)(status.Self(), mDatabase->GetHandlePtr(),\r
+ mTransaction->GetHandlePtr(), &mHandle, &mId, 0, 0);\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Blob::Open", _("isc_open_blob2 failed."));\r
+ mWriteMode = false;\r
+}\r
+\r
+void BlobImpl::Create()\r
+{\r
+ if (mHandle != 0)\r
+ throw LogicExceptionImpl("Blob::Create", _("Blob already opened."));\r
+ if (mDatabase == 0)\r
+ throw LogicExceptionImpl("Blob::Create", _("No Database is attached."));\r
+ if (mTransaction == 0)\r
+ throw LogicExceptionImpl("Blob::Create", _("No Transaction is attached."));\r
+\r
+ IBS status;\r
+ (*gds.Call()->m_create_blob2)(status.Self(), mDatabase->GetHandlePtr(),\r
+ mTransaction->GetHandlePtr(), &mHandle, &mId, 0, 0);\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Blob::Create",\r
+ _("isc_create_blob failed."));\r
+ mIdAssigned = true;\r
+ mWriteMode = true;\r
+}\r
+\r
+void BlobImpl::Close()\r
+{\r
+ if (mHandle == 0) return; // Not opened anyway\r
+\r
+ IBS status;\r
+ (*gds.Call()->m_close_blob)(status.Self(), &mHandle);\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Blob::Close", _("isc_close_blob failed."));\r
+ mHandle = 0;\r
+}\r
+\r
+void BlobImpl::Cancel()\r
+{\r
+ if (mHandle == 0) return; // Not opened anyway\r
+\r
+ if (! mWriteMode)\r
+ throw LogicExceptionImpl("Blob::Cancel", _("Can't cancel a Blob opened for read"));\r
+\r
+ IBS status;\r
+ (*gds.Call()->m_cancel_blob)(status.Self(), &mHandle);\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Blob::Cancel", _("isc_cancel_blob failed."));\r
+ mHandle = 0;\r
+ mIdAssigned = false;\r
+}\r
+\r
+int BlobImpl::Read(void* buffer, int size)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Blob::Read", _("The Blob is not opened"));\r
+ if (mWriteMode)\r
+ throw LogicExceptionImpl("Blob::Read", _("Can't read from Blob opened for write"));\r
+ if (size < 1 || size > (64*1024-1))\r
+ throw LogicExceptionImpl("Blob::Read", _("Invalid segment size (max 64Kb-1)"));\r
+\r
+ IBS status;\r
+ unsigned short bytesread;\r
+ int result = (*gds.Call()->m_get_segment)(status.Self(), &mHandle, &bytesread,\r
+ (unsigned short)size, (char*)buffer);\r
+ if (result == isc_segstr_eof) return 0; // Fin du blob\r
+ if (result != isc_segment && status.Errors())\r
+ throw SQLExceptionImpl(status, "Blob::Read", _("isc_get_segment failed."));\r
+ return (int)bytesread;\r
+}\r
+\r
+void BlobImpl::Write(const void* buffer, int size)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Blob::Write", _("The Blob is not opened"));\r
+ if (! mWriteMode)\r
+ throw LogicExceptionImpl("Blob::Write", _("Can't write to Blob opened for read"));\r
+ if (size < 1 || size > (64*1024-1))\r
+ throw LogicExceptionImpl("Blob::Write", _("Invalid segment size (max 64Kb-1)"));\r
+\r
+ IBS status;\r
+ (*gds.Call()->m_put_segment)(status.Self(), &mHandle,\r
+ (unsigned short)size, (char*)buffer);\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Blob::Write", _("isc_put_segment failed."));\r
+}\r
+\r
+void BlobImpl::Info(int* Size, int* Largest, int* Segments)\r
+{\r
+ char items[] = {isc_info_blob_total_length,\r
+ isc_info_blob_max_segment,\r
+ isc_info_blob_num_segments};\r
+\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Blob::GetInfo", _("The Blob is not opened"));\r
+\r
+ IBS status;\r
+ RB result(100);\r
+ (*gds.Call()->m_blob_info)(status.Self(), &mHandle, sizeof(items), items,\r
+ (short)result.Size(), result.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Blob::GetInfo", _("isc_blob_info failed."));\r
+\r
+ if (Size != 0) *Size = result.GetValue(isc_info_blob_total_length);\r
+ if (Largest != 0) *Largest = result.GetValue(isc_info_blob_max_segment);\r
+ if (Segments != 0) *Segments = result.GetValue(isc_info_blob_num_segments);\r
+}\r
+\r
+void BlobImpl::Save(const std::string& data)\r
+{\r
+ if (mHandle != 0)\r
+ throw LogicExceptionImpl("Blob::Save", _("Blob already opened."));\r
+ if (mDatabase == 0)\r
+ throw LogicExceptionImpl("Blob::Save", _("No Database is attached."));\r
+ if (mTransaction == 0)\r
+ throw LogicExceptionImpl("Blob::Save", _("No Transaction is attached."));\r
+\r
+ IBS status;\r
+ (*gds.Call()->m_create_blob2)(status.Self(), mDatabase->GetHandlePtr(),\r
+ mTransaction->GetHandlePtr(), &mHandle, &mId, 0, 0);\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Blob::Save",\r
+ _("isc_create_blob failed."));\r
+ mIdAssigned = true;\r
+ mWriteMode = true;\r
+\r
+ size_t pos = 0;\r
+ size_t len = data.size();\r
+ while (len != 0)\r
+ {\r
+ size_t blklen = (len < 32*1024-1) ? len : 32*1024-1;\r
+ status.Reset();\r
+ (*gds.Call()->m_put_segment)(status.Self(), &mHandle,\r
+ (unsigned short)blklen, const_cast<char*>(data.data()+pos));\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Blob::Save",\r
+ _("isc_put_segment failed."));\r
+ pos += blklen;\r
+ len -= blklen;\r
+ }\r
+ \r
+ status.Reset();\r
+ (*gds.Call()->m_close_blob)(status.Self(), &mHandle);\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Blob::Save", _("isc_close_blob failed."));\r
+ mHandle = 0;\r
+}\r
+\r
+void BlobImpl::Load(std::string& data)\r
+{\r
+ if (mHandle != 0)\r
+ throw LogicExceptionImpl("Blob::Load", _("Blob already opened."));\r
+ if (mDatabase == 0)\r
+ throw LogicExceptionImpl("Blob::Load", _("No Database is attached."));\r
+ if (mTransaction == 0)\r
+ throw LogicExceptionImpl("Blob::Load", _("No Transaction is attached."));\r
+ if (! mIdAssigned)\r
+ throw LogicExceptionImpl("Blob::Load", _("Blob Id is not assigned."));\r
+\r
+ IBS status;\r
+ (*gds.Call()->m_open_blob2)(status.Self(), mDatabase->GetHandlePtr(),\r
+ mTransaction->GetHandlePtr(), &mHandle, &mId, 0, 0);\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Blob::Load", _("isc_open_blob2 failed."));\r
+ mWriteMode = false;\r
+\r
+ size_t blklen = 32*1024-1;\r
+ data.resize(blklen);\r
+\r
+ size_t size = 0;\r
+ size_t pos = 0;\r
+ for (;;)\r
+ {\r
+ status.Reset();\r
+ unsigned short bytesread;\r
+ int result = (*gds.Call()->m_get_segment)(status.Self(), &mHandle,\r
+ &bytesread, (unsigned short)blklen,\r
+ const_cast<char*>(data.data()+pos));\r
+ if (result == isc_segstr_eof) break; // End of blob\r
+ if (result != isc_segment && status.Errors())\r
+ throw SQLExceptionImpl(status, "Blob::Load", _("isc_get_segment failed."));\r
+\r
+ pos += bytesread;\r
+ size += bytesread;\r
+ data.resize(size + blklen);\r
+ }\r
+ data.resize(size);\r
+ \r
+ status.Reset();\r
+ (*gds.Call()->m_close_blob)(status.Self(), &mHandle);\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Blob::Load", _("isc_close_blob failed."));\r
+ mHandle = 0;\r
+}\r
+\r
+IBPP::Database BlobImpl::DatabasePtr() const\r
+{\r
+ if (mDatabase == 0) throw LogicExceptionImpl("Blob::DatabasePtr",\r
+ _("No Database is attached."));\r
+ return mDatabase;\r
+}\r
+\r
+IBPP::Transaction BlobImpl::TransactionPtr() const\r
+{\r
+ if (mTransaction == 0) throw LogicExceptionImpl("Blob::TransactionPtr",\r
+ _("No Transaction is attached."));\r
+ return mTransaction;\r
+}\r
+\r
+IBPP::IBlob* BlobImpl::AddRef()\r
+{\r
+ ASSERTION(mRefCount >= 0);\r
+ ++mRefCount;\r
+ return this;\r
+}\r
+\r
+void BlobImpl::Release()\r
+{\r
+ // Release cannot throw, except in DEBUG builds on assertion\r
+ ASSERTION(mRefCount >= 0);\r
+ --mRefCount;\r
+ try { if (mRefCount <= 0) delete this; }\r
+ catch (...) { }\r
+}\r
+\r
+// (((((((( OBJECT INTERNAL METHODS ))))))))\r
+\r
+void BlobImpl::Init()\r
+{\r
+ mIdAssigned = false;\r
+ mWriteMode = false;\r
+ mHandle = 0;\r
+ mDatabase = 0;\r
+ mTransaction = 0;\r
+}\r
+\r
+void BlobImpl::SetId(ISC_QUAD* quad)\r
+{\r
+ if (mHandle != 0)\r
+ throw LogicExceptionImpl("BlobImpl::SetId", _("Can't set Id on an opened BlobImpl."));\r
+ if (quad == 0)\r
+ throw LogicExceptionImpl("BlobImpl::SetId", _("Null Id reference detected."));\r
+\r
+ memcpy(&mId, quad, sizeof(mId));\r
+ mIdAssigned = true;\r
+}\r
+\r
+void BlobImpl::GetId(ISC_QUAD* quad)\r
+{\r
+ if (mHandle != 0)\r
+ throw LogicExceptionImpl("BlobImpl::GetId", _("Can't get Id on an opened BlobImpl."));\r
+ if (! mWriteMode)\r
+ throw LogicExceptionImpl("BlobImpl::GetId", _("Can only get Id of a newly created Blob."));\r
+ if (quad == 0)\r
+ throw LogicExceptionImpl("BlobImpl::GetId", _("Null Id reference detected."));\r
+\r
+ memcpy(quad, &mId, sizeof(mId));\r
+}\r
+\r
+void BlobImpl::AttachDatabaseImpl(DatabaseImpl* database)\r
+{\r
+ if (database == 0) throw LogicExceptionImpl("Blob::AttachDatabase",\r
+ _("Can't attach a NULL Database object."));\r
+\r
+ if (mDatabase != 0) mDatabase->DetachBlobImpl(this);\r
+ mDatabase = database;\r
+ mDatabase->AttachBlobImpl(this);\r
+}\r
+\r
+void BlobImpl::AttachTransactionImpl(TransactionImpl* transaction)\r
+{\r
+ if (transaction == 0) throw LogicExceptionImpl("Blob::AttachTransaction",\r
+ _("Can't attach a NULL Transaction object."));\r
+\r
+ if (mTransaction != 0) mTransaction->DetachBlobImpl(this);\r
+ mTransaction = transaction;\r
+ mTransaction->AttachBlobImpl(this);\r
+}\r
+\r
+void BlobImpl::DetachDatabaseImpl()\r
+{\r
+ if (mDatabase == 0) return;\r
+\r
+ mDatabase->DetachBlobImpl(this);\r
+ mDatabase = 0;\r
+}\r
+\r
+void BlobImpl::DetachTransactionImpl()\r
+{\r
+ if (mTransaction == 0) return;\r
+\r
+ mTransaction->DetachBlobImpl(this);\r
+ mTransaction = 0;\r
+}\r
+\r
+BlobImpl::BlobImpl(DatabaseImpl* database, TransactionImpl* transaction)\r
+ : mRefCount(0)\r
+{\r
+ Init();\r
+ AttachDatabaseImpl(database);\r
+ if (transaction != 0) AttachTransactionImpl(transaction);\r
+}\r
+\r
+BlobImpl::~BlobImpl()\r
+{\r
+ try\r
+ {\r
+ if (mHandle != 0)\r
+ {\r
+ if (mWriteMode) Cancel();\r
+ else Close();\r
+ }\r
+ }\r
+ catch (...) { }\r
+ \r
+ try { if (mTransaction != 0) mTransaction->DetachBlobImpl(this); }\r
+ catch (...) { }\r
+ try { if (mDatabase != 0) mDatabase->DetachBlobImpl(this); }\r
+ catch (...) { }\r
+}\r
+\r
+//\r
+// EOF\r
+//\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: database.cpp,v 1.1 2007/05/05 17:00:42 faust Exp $\r
+// Subject : IBPP, Database class implementation\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning(disable: 4786 4996)\r
+#ifndef _DEBUG\r
+#pragma warning(disable: 4702)\r
+#endif\r
+#endif\r
+\r
+#include "_ibpp.h"\r
+\r
+#ifdef HAS_HDRSTOP\r
+#pragma hdrstop\r
+#endif\r
+\r
+#include <algorithm>\r
+\r
+using namespace ibpp_internals;\r
+\r
+// (((((((( OBJECT INTERFACE IMPLEMENTATION ))))))))\r
+\r
+void DatabaseImpl::Create(int dialect)\r
+{\r
+ if (mHandle != 0)\r
+ throw LogicExceptionImpl("Database::Create", _("Database is already connected."));\r
+ if (mDatabaseName.empty())\r
+ throw LogicExceptionImpl("Database::Create", _("Unspecified database name."));\r
+ if (mUserName.empty())\r
+ throw LogicExceptionImpl("Database::Create", _("Unspecified user name."));\r
+ if (dialect != 1 && dialect != 3)\r
+ throw LogicExceptionImpl("Database::Create", _("Only dialects 1 and 3 are supported."));\r
+\r
+ // Build the SQL Create Statement\r
+ std::string create;\r
+ create.assign("CREATE DATABASE '");\r
+ if (! mServerName.empty()) create.append(mServerName).append(":");\r
+ create.append(mDatabaseName).append("' ");\r
+\r
+ create.append("USER '").append(mUserName).append("' ");\r
+ if (! mUserPassword.empty())\r
+ create.append("PASSWORD '").append(mUserPassword).append("' ");\r
+\r
+ if (! mCreateParams.empty()) create.append(mCreateParams);\r
+\r
+ // Call ExecuteImmediate to create the database\r
+ isc_tr_handle tr_handle = 0;\r
+ IBS status;\r
+ (*gds.Call()->m_dsql_execute_immediate)(status.Self(), &mHandle, &tr_handle,\r
+ 0, const_cast<char*>(create.c_str()), short(dialect), NULL);\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Database::Create", _("isc_dsql_execute_immediate failed"));\r
+\r
+ Disconnect();\r
+}\r
+\r
+void DatabaseImpl::Connect()\r
+{\r
+ if (mHandle != 0) return; // Already connected\r
+\r
+ if (mDatabaseName.empty())\r
+ throw LogicExceptionImpl("Database::Connect", _("Unspecified database name."));\r
+ if (mUserName.empty())\r
+ throw LogicExceptionImpl("Database::Connect", _("Unspecified user name."));\r
+\r
+ // Build a DPB based on the properties\r
+ DPB dpb;\r
+ dpb.Insert(isc_dpb_user_name, mUserName.c_str());\r
+ dpb.Insert(isc_dpb_password, mUserPassword.c_str());\r
+ if (! mRoleName.empty()) dpb.Insert(isc_dpb_sql_role_name, mRoleName.c_str());\r
+ if (! mCharSet.empty()) dpb.Insert(isc_dpb_lc_ctype, mCharSet.c_str());\r
+\r
+ std::string connect;\r
+ if (! mServerName.empty())\r
+ connect.assign(mServerName).append(":");\r
+ connect.append(mDatabaseName);\r
+\r
+ IBS status;\r
+ (*gds.Call()->m_attach_database)(status.Self(), (short)connect.size(),\r
+ const_cast<char*>(connect.c_str()), &mHandle, dpb.Size(), dpb.Self());\r
+ if (status.Errors())\r
+ {\r
+ mHandle = 0; // Should be, but better be sure...\r
+ throw SQLExceptionImpl(status, "Database::Connect", _("isc_attach_database failed"));\r
+ }\r
+\r
+ // Now, get ODS version information and dialect.\r
+ // If ODS major is lower of equal to 9, we reject the connection.\r
+ // If ODS major is 10 or higher, this is at least an InterBase 6.x Server\r
+ // OR FireBird 1.x Server.\r
+\r
+ char items[] = {isc_info_ods_version,\r
+ isc_info_db_SQL_dialect,\r
+ isc_info_end};\r
+ RB result(100);\r
+\r
+ status.Reset();\r
+ (*gds.Call()->m_database_info)(status.Self(), &mHandle, sizeof(items), items,\r
+ result.Size(), result.Self());\r
+ if (status.Errors())\r
+ {\r
+ status.Reset();\r
+ (*gds.Call()->m_detach_database)(status.Self(), &mHandle);\r
+ mHandle = 0; // Should be, but better be sure...\r
+ throw SQLExceptionImpl(status, "Database::Connect", _("isc_database_info failed"));\r
+ }\r
+\r
+ int ODS = result.GetValue(isc_info_ods_version);\r
+ if (ODS <= 9)\r
+ {\r
+ status.Reset();\r
+ (*gds.Call()->m_detach_database)(status.Self(), &mHandle);\r
+ mHandle = 0; // Should be, but better be sure...\r
+ throw LogicExceptionImpl("Database::Connect",\r
+ _("Unsupported Server : wrong ODS version (%d), at least '10' required."), ODS);\r
+ }\r
+\r
+ mDialect = result.GetValue(isc_info_db_SQL_dialect);\r
+ if (mDialect != 1 && mDialect != 3)\r
+ {\r
+ status.Reset();\r
+ (*gds.Call()->m_detach_database)(status.Self(), &mHandle);\r
+ mHandle = 0; // Should be, but better be sure...\r
+ throw LogicExceptionImpl("Database::Connect", _("Dialect 1 or 3 required"));\r
+ }\r
+\r
+ // Now, verify the GDS32.DLL we are using is compatible with the server\r
+ if (ODS >= 10 && gds.Call()->mGDSVersion < 60)\r
+ {\r
+ status.Reset();\r
+ (*gds.Call()->m_detach_database)(status.Self(), &mHandle);\r
+ mHandle = 0; // Should be, but better be sure...\r
+ throw LogicExceptionImpl("Database::Connect", _("GDS32.DLL version 5 against IBSERVER 6"));\r
+ }\r
+}\r
+\r
+void DatabaseImpl::Inactivate()\r
+{\r
+ if (mHandle == 0) return; // Not connected anyway\r
+\r
+ IBS status;\r
+\r
+ // Rollback any started transaction...\r
+ for (unsigned i = 0; i < mTransactions.size(); i++)\r
+ {\r
+ if (mTransactions[i]->Started())\r
+ mTransactions[i]->Rollback();\r
+ }\r
+\r
+ // Cancel all pending event traps\r
+ for (unsigned i = 0; i < mEvents.size(); i++)\r
+ mEvents[i]->Clear();\r
+\r
+ // Let's detach from all Blobs\r
+ while (mBlobs.size() > 0)\r
+ mBlobs.back()->DetachDatabaseImpl();\r
+\r
+ // Let's detach from all Arrays\r
+ while (mArrays.size() > 0)\r
+ mArrays.back()->DetachDatabaseImpl();\r
+\r
+ // Let's detach from all Statements\r
+ while (mStatements.size() > 0)\r
+ mStatements.back()->DetachDatabaseImpl();\r
+\r
+ // Let's detach from all Transactions\r
+ while (mTransactions.size() > 0)\r
+ mTransactions.back()->DetachDatabaseImpl(this);\r
+\r
+ // Let's detach from all Events\r
+ while (mEvents.size() > 0)\r
+ mEvents.back()->DetachDatabaseImpl();\r
+}\r
+\r
+void DatabaseImpl::Disconnect()\r
+{\r
+ if (mHandle == 0) return; // Not connected anyway\r
+\r
+ // Put the connection to rest\r
+ Inactivate();\r
+\r
+ // Detach from the server\r
+ IBS status;\r
+ (*gds.Call()->m_detach_database)(status.Self(), &mHandle);\r
+\r
+ // Should we throw, set mHandle to 0 first, because Disconnect() may\r
+ // be called from Database destructor (keeps the object coherent).\r
+ mHandle = 0;\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Database::Disconnect", _("isc_detach_database failed"));\r
+}\r
+\r
+void DatabaseImpl::Drop()\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Database::Drop", _("Database must be connected."));\r
+\r
+ // Put the connection to a rest\r
+ Inactivate();\r
+\r
+ IBS vector;\r
+ (*gds.Call()->m_drop_database)(vector.Self(), &mHandle);\r
+ if (vector.Errors())\r
+ throw SQLExceptionImpl(vector, "Database::Drop", _("isc_drop_database failed"));\r
+\r
+ mHandle = 0;\r
+}\r
+\r
+void DatabaseImpl::Info(int* ODSMajor, int* ODSMinor,\r
+ int* PageSize, int* Pages, int* Buffers, int* Sweep,\r
+ bool* Sync, bool* Reserve)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Database::Info", _("Database is not connected."));\r
+\r
+ char items[] = {isc_info_ods_version,\r
+ isc_info_ods_minor_version,\r
+ isc_info_page_size,\r
+ isc_info_allocation,\r
+ isc_info_num_buffers,\r
+ isc_info_sweep_interval,\r
+ isc_info_forced_writes,\r
+ isc_info_no_reserve,\r
+ isc_info_end};\r
+ IBS status;\r
+ RB result(256);\r
+\r
+ status.Reset();\r
+ (*gds.Call()->m_database_info)(status.Self(), &mHandle, sizeof(items), items,\r
+ result.Size(), result.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Database::Info", _("isc_database_info failed"));\r
+\r
+ if (ODSMajor != 0) *ODSMajor = result.GetValue(isc_info_ods_version);\r
+ if (ODSMinor != 0) *ODSMinor = result.GetValue(isc_info_ods_minor_version);\r
+ if (PageSize != 0) *PageSize = result.GetValue(isc_info_page_size);\r
+ if (Pages != 0) *Pages = result.GetValue(isc_info_allocation);\r
+ if (Buffers != 0) *Buffers = result.GetValue(isc_info_num_buffers);\r
+ if (Sweep != 0) *Sweep = result.GetValue(isc_info_sweep_interval);\r
+ if (Sync != 0)\r
+ *Sync = result.GetValue(isc_info_forced_writes) == 1 ? true : false;\r
+ if (Reserve != 0)\r
+ *Reserve = result.GetValue(isc_info_no_reserve) == 1 ? false : true;\r
+}\r
+\r
+void DatabaseImpl::Statistics(int* Fetches, int* Marks, int* Reads, int* Writes)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Database::Statistics", _("Database is not connected."));\r
+\r
+ char items[] = {isc_info_fetches,\r
+ isc_info_marks,\r
+ isc_info_reads,\r
+ isc_info_writes,\r
+ isc_info_end};\r
+ IBS status;\r
+ RB result(128);\r
+\r
+ status.Reset();\r
+ (*gds.Call()->m_database_info)(status.Self(), &mHandle, sizeof(items), items,\r
+ result.Size(), result.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Database::Statistics", _("isc_database_info failed"));\r
+\r
+ if (Fetches != 0) *Fetches = result.GetValue(isc_info_fetches);\r
+ if (Marks != 0) *Marks = result.GetValue(isc_info_marks);\r
+ if (Reads != 0) *Reads = result.GetValue(isc_info_reads);\r
+ if (Writes != 0) *Writes = result.GetValue(isc_info_writes);\r
+}\r
+\r
+void DatabaseImpl::Counts(int* Insert, int* Update, int* Delete, \r
+ int* ReadIdx, int* ReadSeq)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Database::Counts", _("Database is not connected."));\r
+\r
+ char items[] = {isc_info_insert_count,\r
+ isc_info_update_count,\r
+ isc_info_delete_count,\r
+ isc_info_read_idx_count,\r
+ isc_info_read_seq_count,\r
+ isc_info_end};\r
+ IBS status;\r
+ RB result(1024);\r
+\r
+ status.Reset();\r
+ (*gds.Call()->m_database_info)(status.Self(), &mHandle, sizeof(items), items,\r
+ result.Size(), result.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Database::Counts", _("isc_database_info failed"));\r
+\r
+ if (Insert != 0) *Insert = result.GetCountValue(isc_info_insert_count);\r
+ if (Update != 0) *Update = result.GetCountValue(isc_info_update_count);\r
+ if (Delete != 0) *Delete = result.GetCountValue(isc_info_delete_count);\r
+ if (ReadIdx != 0) *ReadIdx = result.GetCountValue(isc_info_read_idx_count);\r
+ if (ReadSeq != 0) *ReadSeq = result.GetCountValue(isc_info_read_seq_count);\r
+}\r
+\r
+void DatabaseImpl::Users(std::vector<std::string>& users)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Database::Users", _("Database is not connected."));\r
+\r
+ char items[] = {isc_info_user_names,\r
+ isc_info_end};\r
+ IBS status;\r
+ RB result(8000);\r
+\r
+ status.Reset();\r
+ (*gds.Call()->m_database_info)(status.Self(), &mHandle, sizeof(items), items,\r
+ result.Size(), result.Self());\r
+ if (status.Errors())\r
+ {\r
+ status.Reset();\r
+ throw SQLExceptionImpl(status, "Database::Users", _("isc_database_info failed"));\r
+ }\r
+\r
+ users.clear();\r
+ char* p = result.Self();\r
+ while (*p == isc_info_user_names)\r
+ {\r
+ p += 3; // Get to the length byte (there are two undocumented bytes which we skip)\r
+ int len = (int)(*p);\r
+ ++p; // Get to the first char of username\r
+ if (len != 0) users.push_back(std::string().append(p, len));\r
+ p += len; // Skip username\r
+ }\r
+ return;\r
+}\r
+\r
+IBPP::IDatabase* DatabaseImpl::AddRef()\r
+{\r
+ ASSERTION(mRefCount >= 0);\r
+ ++mRefCount;\r
+ return this;\r
+}\r
+\r
+void DatabaseImpl::Release()\r
+{\r
+ // Release cannot throw, except in DEBUG builds on assertion\r
+ ASSERTION(mRefCount >= 0);\r
+ --mRefCount;\r
+ try { if (mRefCount <= 0) delete this; }\r
+ catch (...) { }\r
+}\r
+\r
+// (((((((( OBJECT INTERNAL METHODS ))))))))\r
+\r
+void DatabaseImpl::AttachTransactionImpl(TransactionImpl* tr)\r
+{\r
+ if (tr == 0)\r
+ throw LogicExceptionImpl("Database::AttachTransaction",\r
+ _("Transaction object is null."));\r
+\r
+ mTransactions.push_back(tr);\r
+}\r
+\r
+void DatabaseImpl::DetachTransactionImpl(TransactionImpl* tr)\r
+{\r
+ if (tr == 0)\r
+ throw LogicExceptionImpl("Database::DetachTransaction",\r
+ _("ITransaction object is null."));\r
+\r
+ mTransactions.erase(std::find(mTransactions.begin(), mTransactions.end(), tr));\r
+}\r
+\r
+void DatabaseImpl::AttachStatementImpl(StatementImpl* st)\r
+{\r
+ if (st == 0)\r
+ throw LogicExceptionImpl("Database::AttachStatement",\r
+ _("Can't attach a null Statement object."));\r
+\r
+ mStatements.push_back(st);\r
+}\r
+\r
+void DatabaseImpl::DetachStatementImpl(StatementImpl* st)\r
+{\r
+ if (st == 0)\r
+ throw LogicExceptionImpl("Database::DetachStatement",\r
+ _("Can't detach a null Statement object."));\r
+\r
+ mStatements.erase(std::find(mStatements.begin(), mStatements.end(), st));\r
+}\r
+\r
+void DatabaseImpl::AttachBlobImpl(BlobImpl* bb)\r
+{\r
+ if (bb == 0)\r
+ throw LogicExceptionImpl("Database::AttachBlob",\r
+ _("Can't attach a null Blob object."));\r
+\r
+ mBlobs.push_back(bb);\r
+}\r
+\r
+void DatabaseImpl::DetachBlobImpl(BlobImpl* bb)\r
+{\r
+ if (bb == 0)\r
+ throw LogicExceptionImpl("Database::DetachBlob",\r
+ _("Can't detach a null Blob object."));\r
+\r
+ mBlobs.erase(std::find(mBlobs.begin(), mBlobs.end(), bb));\r
+}\r
+\r
+void DatabaseImpl::AttachArrayImpl(ArrayImpl* ar)\r
+{\r
+ if (ar == 0)\r
+ throw LogicExceptionImpl("Database::AttachArray",\r
+ _("Can't attach a null Array object."));\r
+\r
+ mArrays.push_back(ar);\r
+}\r
+\r
+void DatabaseImpl::DetachArrayImpl(ArrayImpl* ar)\r
+{\r
+ if (ar == 0)\r
+ throw LogicExceptionImpl("Database::DetachArray",\r
+ _("Can't detach a null Array object."));\r
+\r
+ mArrays.erase(std::find(mArrays.begin(), mArrays.end(), ar));\r
+}\r
+\r
+void DatabaseImpl::AttachEventsImpl(EventsImpl* ev)\r
+{\r
+ if (ev == 0)\r
+ throw LogicExceptionImpl("Database::AttachEventsImpl",\r
+ _("Can't attach a null Events object."));\r
+\r
+ mEvents.push_back(ev);\r
+}\r
+\r
+void DatabaseImpl::DetachEventsImpl(EventsImpl* ev)\r
+{\r
+ if (ev == 0)\r
+ throw LogicExceptionImpl("Database::DetachEventsImpl",\r
+ _("Can't detach a null Events object."));\r
+\r
+ mEvents.erase(std::find(mEvents.begin(), mEvents.end(), ev));\r
+}\r
+\r
+DatabaseImpl::DatabaseImpl(const std::string& ServerName, const std::string& DatabaseName,\r
+ const std::string& UserName, const std::string& UserPassword,\r
+ const std::string& RoleName, const std::string& CharSet,\r
+ const std::string& CreateParams) :\r
+\r
+ mRefCount(0), mHandle(0),\r
+ mServerName(ServerName), mDatabaseName(DatabaseName),\r
+ mUserName(UserName), mUserPassword(UserPassword), mRoleName(RoleName),\r
+ mCharSet(CharSet), mCreateParams(CreateParams),\r
+ mDialect(3)\r
+{\r
+}\r
+\r
+DatabaseImpl::~DatabaseImpl()\r
+{\r
+ try { if (Connected()) Disconnect(); }\r
+ catch(...) { }\r
+}\r
+\r
+//\r
+// EOF\r
+//\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: date.cpp,v 1.1 2007/05/05 17:00:42 faust Exp $\r
+// Subject : IBPP, Date class implementation\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning(disable: 4786 4996)\r
+#ifndef _DEBUG\r
+#pragma warning(disable: 4702)\r
+#endif\r
+#endif\r
+\r
+#include "_ibpp.h"\r
+\r
+#ifdef HAS_HDRSTOP\r
+#pragma hdrstop\r
+#endif\r
+\r
+#include <time.h> // Can't use <ctime> thanks to MSVC6 buggy library\r
+\r
+using namespace ibpp_internals;\r
+\r
+void IBPP::Date::Today()\r
+{\r
+ time_t systime = time(0);\r
+ tm* loctime = localtime(&systime);\r
+\r
+ if (! IBPP::itod(&mDate, loctime->tm_year + 1900,\r
+ loctime->tm_mon + 1, loctime->tm_mday))\r
+ throw LogicExceptionImpl("Date::Today", _("Out of range"));\r
+}\r
+\r
+void IBPP::Date::SetDate(int dt)\r
+{\r
+ if (! IBPP::dtoi(dt, 0, 0, 0))\r
+ throw LogicExceptionImpl("Date::SetDate", _("Out of range"));\r
+ mDate = dt;\r
+}\r
+\r
+void IBPP::Date::SetDate(int year, int month, int day)\r
+{\r
+ if (! IBPP::itod(&mDate, year, month, day))\r
+ throw LogicExceptionImpl("Date::SetDate", _("Out of range"));\r
+}\r
+\r
+void IBPP::Date::GetDate(int& year, int& month, int& day) const\r
+{\r
+ if (! IBPP::dtoi(mDate, &year, &month, &day))\r
+ throw LogicExceptionImpl("Date::GetDate", _("Out of range"));\r
+}\r
+\r
+int IBPP::Date::Year() const\r
+{\r
+ int year;\r
+ if (! IBPP::dtoi(mDate, &year, 0, 0))\r
+ throw LogicExceptionImpl("Date::Year", _("Out of range"));\r
+ return year;\r
+}\r
+\r
+int IBPP::Date::Month() const\r
+{\r
+ int month;\r
+ if (! IBPP::dtoi(mDate, 0, &month, 0))\r
+ throw LogicExceptionImpl("Date::Month", _("Out of range"));\r
+ return month;\r
+}\r
+\r
+int IBPP::Date::Day() const\r
+{\r
+ int day;\r
+ if (! IBPP::dtoi(mDate, 0, 0, &day))\r
+ throw LogicExceptionImpl("Date::Day", _("Out of range"));\r
+ return day;\r
+}\r
+\r
+void IBPP::Date::Add(int days)\r
+{\r
+ int newdate = mDate + days; // days can be signed\r
+ if (! IBPP::dtoi(newdate, 0, 0, 0))\r
+ throw LogicExceptionImpl("Date::Add()", _("Out of range"));\r
+ mDate = newdate;\r
+}\r
+\r
+void IBPP::Date::StartOfMonth()\r
+{\r
+ int year, month;\r
+ if (! IBPP::dtoi(mDate, &year, &month, 0))\r
+ throw LogicExceptionImpl("Date::StartOfMonth()", _("Out of range"));\r
+ if (! IBPP::itod(&mDate, year, month, 1)) // First of same month\r
+ throw LogicExceptionImpl("Date::StartOfMonth()", _("Out of range"));\r
+}\r
+\r
+void IBPP::Date::EndOfMonth()\r
+{\r
+ int year, month;\r
+ if (! IBPP::dtoi(mDate, &year, &month, 0))\r
+ throw LogicExceptionImpl("Date::EndOfMonth()", _("Out of range"));\r
+ if (++month > 12) { month = 1; year++; }\r
+ if (! IBPP::itod(&mDate, year, month, 1)) // First of next month\r
+ throw LogicExceptionImpl("Date::EndOfMonth()", _("Out of range"));\r
+ mDate--; // Last day of original month, all weird cases accounted for\r
+}\r
+\r
+IBPP::Date::Date(int year, int month, int day)\r
+{\r
+ SetDate(year, month, day);\r
+}\r
+\r
+IBPP::Date::Date(const IBPP::Date& copied)\r
+{\r
+ mDate = copied.mDate;\r
+}\r
+\r
+IBPP::Date& IBPP::Date::operator=(const IBPP::Timestamp& assigned)\r
+{\r
+ mDate = assigned.GetDate();\r
+ return *this;\r
+}\r
+\r
+IBPP::Date& IBPP::Date::operator=(const IBPP::Date& assigned)\r
+{\r
+ mDate = assigned.mDate;\r
+ return *this;\r
+}\r
+\r
+// The following date calculations were inspired by web pages found on\r
+// Peter Baum web homepage at 'http://www.capecod.net/~pbaum/'.\r
+// His contact info is at : 'http://home.capecod.net/~pbaum/contact.htm'.\r
+// Please, understand that Peter Baum is not related to this IBPP project.\r
+// So __please__, do not contact him regarding IBPP matters.\r
+\r
+// Take a date, in its integer format as used in IBPP internals and splits\r
+// it in year (4 digits), month (1-12), day (1-31)\r
+\r
+bool IBPP::dtoi (int date, int *y, int *m, int *d)\r
+{\r
+ int RataDie, Z, H, A, B, C;\r
+ int year, month, day;\r
+\r
+ // Validity control.\r
+ if (date < IBPP::MinDate || date > IBPP::MaxDate)\r
+ return false;\r
+\r
+ // The "Rata Die" is the date specified as the number of days elapsed since\r
+ // 31 Dec of year 0. So 1 Jan 0001 is 1.\r
+\r
+ RataDie = date + ibpp_internals::consts::Dec31_1899; // Because IBPP sets the '0' on 31 Dec 1899.\r
+\r
+ Z = RataDie + 306;\r
+ H = 100*Z - 25;\r
+ A = H/3652425;\r
+ B = A - A/4;\r
+ year = (100*B + H) / 36525;\r
+ C = B + Z - 365*year - year / 4;\r
+ month = (5*C + 456) / 153;\r
+ day = C - (153*month - 457) / 5;\r
+ if (month > 12) { year += 1; month -= 12; }\r
+\r
+ if (y != 0) *y = (int)year;\r
+ if (m != 0) *m = (int)month;\r
+ if (d != 0) *d = (int)day;\r
+\r
+ return true;\r
+}\r
+\r
+// Take a date from its components year, month, day and convert it to the\r
+// integer representation used internally in IBPP.\r
+\r
+bool IBPP::itod (int *pdate, int year, int month, int day)\r
+{\r
+ int RataDie, result;\r
+ int y, m, d;\r
+\r
+ d = day; m = month; y = year;\r
+ if (m < 3) { m += 12; y -= 1; }\r
+ RataDie = d + (153*m - 457) / 5 + 365*y + y/4 - y/100 + y/400 - 306;\r
+\r
+ result = RataDie - ibpp_internals::consts::Dec31_1899; // Because IBPP sets the '0' on 31 Dec 1899\r
+\r
+ // Validity control\r
+ if (result < IBPP::MinDate || result > IBPP::MaxDate)\r
+ return false;\r
+\r
+ *pdate = result;\r
+ return true;\r
+}\r
+\r
+// Eof\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: dbkey.cpp,v 1.1 2007/05/05 17:00:42 faust Exp $\r
+// Subject : IBPP, DBKey class implementation\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning(disable: 4786 4996)\r
+#ifndef _DEBUG\r
+#pragma warning(disable: 4702)\r
+#endif\r
+#endif\r
+\r
+#include "_ibpp.h"\r
+\r
+#ifdef HAS_HDRSTOP\r
+#pragma hdrstop\r
+#endif\r
+\r
+#include <iostream>\r
+#include <sstream>\r
+#include <iomanip>\r
+\r
+using namespace ibpp_internals;\r
+\r
+// Private implementation\r
+\r
+// Public implementation\r
+\r
+void IBPP::DBKey::Clear()\r
+{\r
+ mDBKey.erase();\r
+ mString.erase();\r
+}\r
+\r
+void IBPP::DBKey::SetKey(const void* key, int size)\r
+{\r
+ if (key == 0)\r
+ throw LogicExceptionImpl("IBPP::DBKey::SetKey", _("Null DBKey reference detected."));\r
+ if (size <= 0 || ((size >> 3) << 3) != size)\r
+ throw LogicExceptionImpl("IBPP::DBKey::SetKey", _("Invalid DBKey size."));\r
+\r
+ mDBKey.assign((const char*)key, (size_t)size);\r
+ mString.erase();\r
+}\r
+\r
+void IBPP::DBKey::GetKey(void* key, int size) const\r
+{\r
+ if (mDBKey.empty())\r
+ throw LogicExceptionImpl("IBPP::DBKey::GetKey", _("DBKey not assigned."));\r
+ if (key == 0)\r
+ throw LogicExceptionImpl("IBPP::DBKey::GetKey", _("Null DBKey reference detected."));\r
+ if (size != (int)mDBKey.size())\r
+ throw LogicExceptionImpl("IBPP::DBKey::GetKey", _("Incompatible DBKey size detected."));\r
+\r
+ mDBKey.copy((char*)key, mDBKey.size());\r
+}\r
+\r
+const char* IBPP::DBKey::AsString() const\r
+{\r
+ if (mDBKey.empty())\r
+ throw LogicExceptionImpl("IBPP::DBKey::GetString", _("DBKey not assigned."));\r
+\r
+ if (mString.empty())\r
+ {\r
+ std::ostringstream hexkey;\r
+ hexkey.setf(std::ios::hex, std::ios::basefield);\r
+ hexkey.setf(std::ios::uppercase);\r
+\r
+ const uint32_t* key = reinterpret_cast<const uint32_t*>(mDBKey.data());\r
+ int n = (int)mDBKey.size() / 8;\r
+ for (int i = 0; i < n; i++)\r
+ {\r
+ if (i != 0) hexkey<< "-";\r
+ hexkey<< std::setw(4)<< key[i*2]<< ":";\r
+ hexkey<< std::setw(8)<< key[i*2+1];\r
+ }\r
+\r
+ mString = hexkey.str();\r
+ }\r
+\r
+ return mString.c_str();\r
+}\r
+\r
+IBPP::DBKey::DBKey(const DBKey& copied)\r
+{\r
+ mDBKey = copied.mDBKey;\r
+ mString = copied.mString;\r
+}\r
+\r
+IBPP::DBKey& IBPP::DBKey::operator=(const IBPP::DBKey& assigned)\r
+{\r
+ mDBKey = assigned.mDBKey;\r
+ mString = assigned.mString;\r
+ return *this;\r
+}\r
+\r
+//\r
+// EOF\r
+//\r
--- /dev/null
+array.o: array.cpp _ibpp.h ibpp.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ ibase.h iberror.h Makefile ../../Makefile.conf
+ $(CC) -g3 -W -Wall -I/usr/local/include -DARCH_LE -fPIC -DIBPP_LINUX -I /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include -I ./ -DDEBUG -DLINUX -DSTG_TIME -c $<
+blob.o: blob.cpp _ibpp.h ibpp.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ ibase.h iberror.h Makefile ../../Makefile.conf
+ $(CC) -g3 -W -Wall -I/usr/local/include -DARCH_LE -fPIC -DIBPP_LINUX -I /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include -I ./ -DDEBUG -DLINUX -DSTG_TIME -c $<
+database.o: database.cpp _ibpp.h ibpp.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ ibase.h iberror.h Makefile ../../Makefile.conf
+ $(CC) -g3 -W -Wall -I/usr/local/include -DARCH_LE -fPIC -DIBPP_LINUX -I /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include -I ./ -DDEBUG -DLINUX -DSTG_TIME -c $<
+date.o: date.cpp _ibpp.h ibpp.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ ibase.h iberror.h Makefile ../../Makefile.conf
+ $(CC) -g3 -W -Wall -I/usr/local/include -DARCH_LE -fPIC -DIBPP_LINUX -I /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include -I ./ -DDEBUG -DLINUX -DSTG_TIME -c $<
+dbkey.o: dbkey.cpp _ibpp.h ibpp.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ ibase.h iberror.h Makefile ../../Makefile.conf
+ $(CC) -g3 -W -Wall -I/usr/local/include -DARCH_LE -fPIC -DIBPP_LINUX -I /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include -I ./ -DDEBUG -DLINUX -DSTG_TIME -c $<
+_dpb.o: _dpb.cpp _ibpp.h ibpp.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ ibase.h iberror.h Makefile ../../Makefile.conf
+ $(CC) -g3 -W -Wall -I/usr/local/include -DARCH_LE -fPIC -DIBPP_LINUX -I /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include -I ./ -DDEBUG -DLINUX -DSTG_TIME -c $<
+events.o: events.cpp _ibpp.h ibpp.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ ibase.h iberror.h Makefile ../../Makefile.conf
+ $(CC) -g3 -W -Wall -I/usr/local/include -DARCH_LE -fPIC -DIBPP_LINUX -I /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include -I ./ -DDEBUG -DLINUX -DSTG_TIME -c $<
+exception.o: exception.cpp _ibpp.h ibpp.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ ibase.h iberror.h Makefile ../../Makefile.conf
+ $(CC) -g3 -W -Wall -I/usr/local/include -DARCH_LE -fPIC -DIBPP_LINUX -I /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include -I ./ -DDEBUG -DLINUX -DSTG_TIME -c $<
+_ibpp.o: _ibpp.cpp _ibpp.h ibpp.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ ibase.h iberror.h Makefile ../../Makefile.conf
+ $(CC) -g3 -W -Wall -I/usr/local/include -DARCH_LE -fPIC -DIBPP_LINUX -I /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include -I ./ -DDEBUG -DLINUX -DSTG_TIME -c $<
+_ibs.o: _ibs.cpp _ibpp.h ibpp.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ ibase.h iberror.h Makefile ../../Makefile.conf
+ $(CC) -g3 -W -Wall -I/usr/local/include -DARCH_LE -fPIC -DIBPP_LINUX -I /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include -I ./ -DDEBUG -DLINUX -DSTG_TIME -c $<
+_rb.o: _rb.cpp _ibpp.h ibpp.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ ibase.h iberror.h Makefile ../../Makefile.conf
+ $(CC) -g3 -W -Wall -I/usr/local/include -DARCH_LE -fPIC -DIBPP_LINUX -I /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include -I ./ -DDEBUG -DLINUX -DSTG_TIME -c $<
+row.o: row.cpp _ibpp.h ibpp.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ ibase.h iberror.h Makefile ../../Makefile.conf
+ $(CC) -g3 -W -Wall -I/usr/local/include -DARCH_LE -fPIC -DIBPP_LINUX -I /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include -I ./ -DDEBUG -DLINUX -DSTG_TIME -c $<
+service.o: service.cpp _ibpp.h ibpp.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ ibase.h iberror.h Makefile ../../Makefile.conf
+ $(CC) -g3 -W -Wall -I/usr/local/include -DARCH_LE -fPIC -DIBPP_LINUX -I /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include -I ./ -DDEBUG -DLINUX -DSTG_TIME -c $<
+_spb.o: _spb.cpp _ibpp.h ibpp.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ ibase.h iberror.h Makefile ../../Makefile.conf
+ $(CC) -g3 -W -Wall -I/usr/local/include -DARCH_LE -fPIC -DIBPP_LINUX -I /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include -I ./ -DDEBUG -DLINUX -DSTG_TIME -c $<
+statement.o: statement.cpp _ibpp.h ibpp.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ ibase.h iberror.h Makefile ../../Makefile.conf
+ $(CC) -g3 -W -Wall -I/usr/local/include -DARCH_LE -fPIC -DIBPP_LINUX -I /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include -I ./ -DDEBUG -DLINUX -DSTG_TIME -c $<
+time.o: time.cpp _ibpp.h ibpp.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ ibase.h iberror.h Makefile ../../Makefile.conf
+ $(CC) -g3 -W -Wall -I/usr/local/include -DARCH_LE -fPIC -DIBPP_LINUX -I /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include -I ./ -DDEBUG -DLINUX -DSTG_TIME -c $<
+_tpb.o: _tpb.cpp _ibpp.h ibpp.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ ibase.h iberror.h Makefile ../../Makefile.conf
+ $(CC) -g3 -W -Wall -I/usr/local/include -DARCH_LE -fPIC -DIBPP_LINUX -I /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include -I ./ -DDEBUG -DLINUX -DSTG_TIME -c $<
+transaction.o: transaction.cpp _ibpp.h ibpp.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ ibase.h iberror.h Makefile ../../Makefile.conf
+ $(CC) -g3 -W -Wall -I/usr/local/include -DARCH_LE -fPIC -DIBPP_LINUX -I /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include -I ./ -DDEBUG -DLINUX -DSTG_TIME -c $<
+user.o: user.cpp _ibpp.h ibpp.h \
+ /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include/os_int.h \
+ ibase.h iberror.h Makefile ../../Makefile.conf
+ $(CC) -g3 -W -Wall -I/usr/local/include -DARCH_LE -fPIC -DIBPP_LINUX -I /mnt/tank/home/Projects/STG/stg-2.5/projects/stargazer/../../include -I ./ -DDEBUG -DLINUX -DSTG_TIME -c $<
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: events.cpp,v 1.1 2007/05/05 17:00:42 faust Exp $\r
+// Subject : IBPP, internal EventsImpl class implementation\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+// SPECIAL WARNING COMMENT (by Olivier Mascia, 2000 Nov 12)\r
+// The way this source file handles events is not publicly documented, in\r
+// the ibase.h header file or in the IB 6.0 documentation. This documentation\r
+// suggests to use the API isc_event_block to construct vectors of events.\r
+// Unfortunately, this API takes a variable number of parameters to specify\r
+// the list of event names. In addition, the documentation warn on not using\r
+// more than 15 names. This is a sad limitation, partly because the maximum\r
+// number of parameters safely processed in such an API is very compiler\r
+// dependant and also because isc_event_counts() is designed to return counts\r
+// through the IB status vector which is a vector of 20 32-bits integers !\r
+// From reverse engineering of the isc_event_block() API in\r
+// source file jrd/alt.c (as available on fourceforge.net/project/InterBase as\r
+// of 2000 Nov 12), it looks like the internal format of those EPB is simple.\r
+// An EPB starts by a byte with value 1. A version identifier of some sort.\r
+// Then a small cluster is used for each event name. The cluster starts with\r
+// a byte for the length of the event name (no final '\0'). Followed by the N\r
+// characters of the name itself (no final '\0'). The cluster ends with 4 bytes\r
+// preset to 0.\r
+//\r
+// SPECIAL CREDIT (July 2004) : this is a complete re-implementation of this\r
+// class, directly based on work by Val Samko.\r
+// The whole event handling has then be completely redesigned, based on the old\r
+// EPB class to bring up the current IBPP::Events implementation.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning(disable: 4786 4996)\r
+#ifndef _DEBUG\r
+#pragma warning(disable: 4702)\r
+#endif\r
+#endif\r
+\r
+#include "_ibpp.h"\r
+\r
+#ifdef HAS_HDRSTOP\r
+#pragma hdrstop\r
+#endif\r
+\r
+using namespace ibpp_internals;\r
+\r
+const size_t EventsImpl::MAXEVENTNAMELEN = 127;\r
+\r
+// (((((((( OBJECT INTERFACE IMPLEMENTATION ))))))))\r
+\r
+void EventsImpl::Add(const std::string& eventname, IBPP::EventInterface* objref)\r
+{\r
+ if (eventname.size() == 0)\r
+ throw LogicExceptionImpl("Events::Add", _("Zero length event names not permitted"));\r
+ if (eventname.size() > MAXEVENTNAMELEN)\r
+ throw LogicExceptionImpl("Events::Add", _("Event name is too long"));\r
+ if ((mEventBuffer.size() + eventname.length() + 5) > 32766) // max signed 16 bits integer minus one\r
+ throw LogicExceptionImpl("Events::Add",\r
+ _("Can't add this event, the events list would overflow IB/FB limitation"));\r
+\r
+ Cancel();\r
+\r
+ // 1) Alloc or grow the buffers\r
+ size_t prev_buffer_size = mEventBuffer.size();\r
+ size_t needed = ((prev_buffer_size==0) ? 1 : 0) + eventname.length() + 5;\r
+ // Initial alloc will require one more byte, we need 4 more bytes for\r
+ // the count itself, and one byte for the string length prefix\r
+\r
+ mEventBuffer.resize(mEventBuffer.size() + needed);\r
+ mResultsBuffer.resize(mResultsBuffer.size() + needed);\r
+ if (prev_buffer_size == 0)\r
+ mEventBuffer[0] = mResultsBuffer[0] = 1; // First byte is a 'one'. Documentation ??\r
+\r
+ // 2) Update the buffers (append)\r
+ {\r
+ Buffer::iterator it = mEventBuffer.begin() +\r
+ ((prev_buffer_size==0) ? 1 : prev_buffer_size); // Byte after current content\r
+ *(it++) = static_cast<char>(eventname.length());\r
+ it = std::copy(eventname.begin(), eventname.end(), it);\r
+ // We initialize the counts to (uint32_t)(-1) to initialize properly, see FireActions()\r
+ *(it++) = -1; *(it++) = -1; *(it++) = -1; *it = -1;\r
+ }\r
+\r
+ // copying new event to the results buffer to keep event_buffer_ and results_buffer_ consistant,\r
+ // otherwise we might get a problem in `FireActions`\r
+ // Val Samko, val@digiways.com\r
+ std::copy(mEventBuffer.begin() + prev_buffer_size,\r
+ mEventBuffer.end(), mResultsBuffer.begin() + prev_buffer_size);\r
+\r
+ // 3) Alloc or grow the objref array and update the objref array (append)\r
+ mObjectReferences.push_back(objref);\r
+\r
+ Queue();\r
+}\r
+\r
+void EventsImpl::Drop(const std::string& eventname)\r
+{\r
+ if (eventname.size() == 0)\r
+ throw LogicExceptionImpl("EventsImpl::Drop", _("Zero length event names not permitted"));\r
+ if (eventname.size() > MAXEVENTNAMELEN)\r
+ throw LogicExceptionImpl("EventsImpl::Drop", _("Event name is too long"));\r
+\r
+ if (mEventBuffer.size() <= 1) return; // Nothing to do, but not an error\r
+\r
+ Cancel();\r
+\r
+ // 1) Find the event in the buffers\r
+ typedef EventBufferIterator<Buffer::iterator> EventIterator;\r
+ EventIterator eit(mEventBuffer.begin()+1);\r
+ EventIterator rit(mResultsBuffer.begin()+1);\r
+\r
+ for (ObjRefs::iterator oit = mObjectReferences.begin();\r
+ oit != mObjectReferences.end();\r
+ ++oit, ++eit, ++rit)\r
+ {\r
+ if (eventname != eit.get_name()) continue;\r
+ \r
+ // 2) Event found, remove it\r
+ mEventBuffer.erase(eit.begin(), eit.end());\r
+ mResultsBuffer.erase(rit.begin(), rit.end());\r
+ mObjectReferences.erase(oit);\r
+ break;\r
+ }\r
+\r
+ Queue();\r
+}\r
+\r
+void EventsImpl::List(std::vector<std::string>& events)\r
+{\r
+ events.clear();\r
+ \r
+ if (mEventBuffer.size() <= 1) return; // Nothing to do, but not an error\r
+\r
+ typedef EventBufferIterator<Buffer::iterator> EventIterator;\r
+ EventIterator eit(mEventBuffer.begin()+1);\r
+\r
+ for (ObjRefs::iterator oit = mObjectReferences.begin();\r
+ oit != mObjectReferences.end();\r
+ ++oit, ++eit)\r
+ {\r
+ events.push_back(eit.get_name());\r
+ }\r
+}\r
+\r
+void EventsImpl::Clear()\r
+{\r
+ Cancel();\r
+ \r
+ mObjectReferences.clear();\r
+ mEventBuffer.clear();\r
+ mResultsBuffer.clear();\r
+}\r
+\r
+void EventsImpl::Dispatch()\r
+{\r
+ // If no events registered, nothing to do of course.\r
+ if (mEventBuffer.size() == 0) return;\r
+\r
+ // Let's fire the events actions for all the events which triggered, if any, and requeue.\r
+ FireActions();\r
+ Queue();\r
+}\r
+\r
+IBPP::Database EventsImpl::DatabasePtr() const\r
+{\r
+ if (mDatabase == 0) throw LogicExceptionImpl("Events::DatabasePtr",\r
+ _("No Database is attached."));\r
+ return mDatabase;\r
+}\r
+\r
+IBPP::IEvents* EventsImpl::AddRef()\r
+{\r
+ ASSERTION(mRefCount >= 0);\r
+ ++mRefCount;\r
+ return this;\r
+}\r
+\r
+void EventsImpl::Release()\r
+{\r
+ // Release cannot throw, except in DEBUG builds on assertion\r
+ ASSERTION(mRefCount >= 0);\r
+ --mRefCount;\r
+ try { if (mRefCount <= 0) delete this; }\r
+ catch (...) { }\r
+}\r
+\r
+// (((((((( OBJECT INTERNAL METHODS ))))))))\r
+\r
+void EventsImpl::Queue()\r
+{\r
+ if (! mQueued)\r
+ {\r
+ if (mDatabase->GetHandle() == 0)\r
+ throw LogicExceptionImpl("EventsImpl::Queue",\r
+ _("Database is not connected"));\r
+\r
+ IBS vector;\r
+ mTrapped = false;\r
+ mQueued = true;\r
+ (*gds.Call()->m_que_events)(vector.Self(), mDatabase->GetHandlePtr(), &mId,\r
+ short(mEventBuffer.size()), &mEventBuffer[0],\r
+ (isc_callback)EventHandler, (char*)this);\r
+\r
+ if (vector.Errors())\r
+ {\r
+ mId = 0; // Should be, but better be safe\r
+ mQueued = false;\r
+ throw SQLExceptionImpl(vector, "EventsImpl::Queue",\r
+ _("isc_que_events failed"));\r
+ }\r
+ }\r
+}\r
+\r
+void EventsImpl::Cancel()\r
+{\r
+ if (mQueued)\r
+ {\r
+ if (mDatabase->GetHandle() == 0) throw LogicExceptionImpl("EventsImpl::Cancel",\r
+ _("Database is not connected"));\r
+\r
+ IBS vector;\r
+\r
+ // A call to cancel_events will call *once* the handler routine, even\r
+ // though no events had fired. This is why we first set mEventsQueued\r
+ // to false, so that we can be sure to dismiss those unwanted callbacks\r
+ // subsequent to the execution of isc_cancel_events().\r
+ mTrapped = false;\r
+ mQueued = false;\r
+ (*gds.Call()->m_cancel_events)(vector.Self(), mDatabase->GetHandlePtr(), &mId);\r
+\r
+ if (vector.Errors())\r
+ {\r
+ mQueued = true; // Need to restore this as cancel failed\r
+ throw SQLExceptionImpl(vector, "EventsImpl::Cancel",\r
+ _("isc_cancel_events failed"));\r
+ }\r
+\r
+ mId = 0; // Should be, but better be safe\r
+ }\r
+}\r
+\r
+void EventsImpl::FireActions()\r
+{\r
+ if (mTrapped)\r
+ {\r
+ typedef EventBufferIterator<Buffer::iterator> EventIterator;\r
+ EventIterator eit(mEventBuffer.begin()+1);\r
+ EventIterator rit(mResultsBuffer.begin()+1);\r
+\r
+ for (ObjRefs::iterator oit = mObjectReferences.begin();\r
+ oit != mObjectReferences.end();\r
+ ++oit, ++eit, ++rit)\r
+ {\r
+ if (eit == EventIterator(mEventBuffer.end())\r
+ || rit == EventIterator(mResultsBuffer.end()))\r
+ throw LogicExceptionImpl("EventsImpl::FireActions", _("Internal buffer size error"));\r
+ uint32_t vnew = rit.get_count();\r
+ uint32_t vold = eit.get_count();\r
+ if (vnew > vold)\r
+ {\r
+ // Fire the action\r
+ try\r
+ {\r
+ (*oit)->ibppEventHandler(this, eit.get_name(), (int)(vnew - vold));\r
+ }\r
+ catch (...)\r
+ {\r
+ std::copy(rit.begin(), rit.end(), eit.begin());\r
+ throw;\r
+ }\r
+ std::copy(rit.begin(), rit.end(), eit.begin());\r
+ }\r
+ // This handles initialization too, where vold == (uint32_t)(-1)\r
+ // Thanks to M. Hieke for this idea and related initialization to (-1)\r
+ if (vnew != vold)\r
+ std::copy(rit.begin(), rit.end(), eit.begin());\r
+ }\r
+ }\r
+}\r
+\r
+// This function must keep this prototype to stay compatible with\r
+// what isc_que_events() expects\r
+\r
+void EventsImpl::EventHandler(const char* object, short size, const char* tmpbuffer)\r
+{\r
+ // >>>>> This method is a STATIC member !! <<<<<\r
+ // Consider this method as a kind of "interrupt handler". It should do as\r
+ // few work as possible as quickly as possible and then return.\r
+ // Never forget: this is called by the Firebird client code, on *some*\r
+ // thread which might not be (and won't probably be) any of your application\r
+ // thread. This function is to be considered as an "interrupt-handler" of a\r
+ // hardware driver.\r
+\r
+ // There can be spurious calls to EventHandler from FB internal. We must\r
+ // dismiss those calls.\r
+ if (object == 0 || size == 0 || tmpbuffer == 0) return;\r
+ \r
+ EventsImpl* evi = (EventsImpl*)object; // Ugly, but wanted, c-style cast\r
+\r
+ if (evi->mQueued)\r
+ {\r
+ try\r
+ {\r
+ char* rb = &evi->mResultsBuffer[0];\r
+ if (evi->mEventBuffer.size() < (unsigned)size) size = (short)evi->mEventBuffer.size();\r
+ for (int i = 0; i < size; i++)\r
+ rb[i] = tmpbuffer[i];\r
+ evi->mTrapped = true;\r
+ evi->mQueued = false;\r
+ }\r
+ catch (...) { }\r
+ }\r
+}\r
+\r
+void EventsImpl::AttachDatabaseImpl(DatabaseImpl* database)\r
+{\r
+ if (database == 0) throw LogicExceptionImpl("EventsImpl::AttachDatabase",\r
+ _("Can't attach a null Database object."));\r
+\r
+ if (mDatabase != 0) mDatabase->DetachEventsImpl(this);\r
+ mDatabase = database;\r
+ mDatabase->AttachEventsImpl(this);\r
+}\r
+\r
+void EventsImpl::DetachDatabaseImpl()\r
+{\r
+ if (mDatabase == 0) return;\r
+\r
+ mDatabase->DetachEventsImpl(this);\r
+ mDatabase = 0;\r
+}\r
+\r
+EventsImpl::EventsImpl(DatabaseImpl* database)\r
+ : mRefCount(0)\r
+{\r
+ mDatabase = 0;\r
+ mId = 0;\r
+ mQueued = mTrapped = false;\r
+ AttachDatabaseImpl(database);\r
+}\r
+\r
+EventsImpl::~EventsImpl()\r
+{\r
+ try { Clear(); }\r
+ catch (...) { }\r
+ \r
+ try { if (mDatabase != 0) mDatabase->DetachEventsImpl(this); }\r
+ catch (...) { }\r
+}\r
+\r
+//\r
+// EOF\r
+//\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: exception.cpp,v 1.1 2007/05/05 17:00:42 faust Exp $\r
+// Subject : IBPP, Initialization of the library\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning(disable: 4786 4996)\r
+#ifndef _DEBUG\r
+#pragma warning(disable: 4702)\r
+#endif\r
+#endif\r
+\r
+#include "_ibpp.h"\r
+\r
+#ifdef HAS_HDRSTOP\r
+#pragma hdrstop\r
+#endif\r
+\r
+#include <stdarg.h>\r
+#include <stdio.h>\r
+\r
+using namespace ibpp_internals;\r
+\r
+// None of the exception classes methods are implemented inline, because they\r
+// are all declared throw() and Borland compilers at least, but possibly some\r
+// others emit a warning like "W8026 - functions with exception specification\r
+// are not expanded inline". Nothing we have to worry about, but we don't want\r
+// people concerned by such warnings.\r
+\r
+IBPP::Exception::~Exception() throw()\r
+{\r
+}\r
+\r
+IBPP::LogicException::~LogicException() throw()\r
+{\r
+}\r
+\r
+IBPP::SQLException::~SQLException() throw()\r
+{\r
+}\r
+\r
+IBPP::WrongType::~WrongType() throw()\r
+{\r
+}\r
+\r
+//\r
+// (((((((( ExceptionBase Implementation ))))))))\r
+//\r
+\r
+void ExceptionBase::buildErrorMessage(const char* message)\r
+{\r
+ if (! mContext.empty())\r
+ mWhat.append(_("Context: ")).append(mContext).append("\n");\r
+\r
+ if (message != 0 && *message != 0 )\r
+ mWhat.append(_("Message: ")).append(message).append("\n");\r
+ \r
+ mWhat.append("\n");\r
+}\r
+\r
+void ExceptionBase::raise(const std::string& context, const char* message, va_list argptr)\r
+{\r
+ mContext.assign(context);\r
+\r
+ if (message != 0)\r
+ {\r
+ char buffer[1024];\r
+#if defined(_MSC_VER) || defined(__DMC__)\r
+ _vsnprintf(buffer, sizeof(buffer)-1, message, argptr);\r
+#else\r
+ vsnprintf(buffer, sizeof(buffer)-1, message, argptr);\r
+#endif\r
+ buffer[sizeof(buffer)-1] = 0;\r
+ \r
+ buildErrorMessage(buffer);\r
+ }\r
+ else\r
+ buildErrorMessage(0);\r
+}\r
+\r
+ExceptionBase::ExceptionBase() throw()\r
+{\r
+}\r
+\r
+ExceptionBase::ExceptionBase(const ExceptionBase& copied) throw()\r
+{\r
+ mContext = copied.mContext;\r
+ mWhat = copied.mWhat;\r
+}\r
+\r
+ExceptionBase& ExceptionBase::operator=(const ExceptionBase& copied) throw()\r
+{\r
+ mContext = copied.mContext;\r
+ mWhat = copied.mWhat;\r
+ return *this;\r
+}\r
+\r
+ExceptionBase::ExceptionBase(const std::string& context,\r
+ const char* message, ...) throw()\r
+{\r
+ va_list argptr;\r
+ va_start(argptr, message);\r
+ mWhat.assign("*** IBPP::Exception ***\n");\r
+ raise(context, message, argptr);\r
+ va_end(argptr);\r
+}\r
+\r
+ExceptionBase::~ExceptionBase() throw()\r
+{\r
+}\r
+\r
+const char* ExceptionBase::Origin() const throw()\r
+{\r
+ return mContext.c_str();\r
+}\r
+\r
+const char* ExceptionBase::ErrorMessage() const throw()\r
+{\r
+ return mWhat.c_str();\r
+}\r
+\r
+const char* ExceptionBase::what() const throw()\r
+{\r
+ return mWhat.c_str();\r
+}\r
+\r
+// (((((((( LogicExceptionImpl Implementation ))))))))\r
+\r
+// The following constructors are small and could be inlined, but for object\r
+// code compacity of the library it is much better to have them non-inlined.\r
+// The amount of code generated by compilers for a throw is well-enough.\r
+\r
+LogicExceptionImpl::LogicExceptionImpl() throw()\r
+ : ExceptionBase()\r
+{\r
+}\r
+\r
+LogicExceptionImpl::LogicExceptionImpl(const LogicExceptionImpl& copied) throw()\r
+ : IBPP::LogicException(), ExceptionBase(copied)\r
+{\r
+}\r
+\r
+LogicExceptionImpl& LogicExceptionImpl::operator=(const LogicExceptionImpl& copied) throw()\r
+{\r
+ ExceptionBase::operator=(copied);\r
+ return *this;\r
+}\r
+\r
+LogicExceptionImpl::LogicExceptionImpl(const std::string& context,\r
+ const char* message, ...) throw()\r
+{\r
+ va_list argptr;\r
+ va_start(argptr, message);\r
+ mWhat.assign("*** IBPP::LogicException ***\n");\r
+ raise(context, message, argptr);\r
+ va_end(argptr);\r
+}\r
+\r
+LogicExceptionImpl::~LogicExceptionImpl() throw ()\r
+{\r
+}\r
+\r
+const char* LogicExceptionImpl::Origin() const throw()\r
+{\r
+ return ExceptionBase::Origin();\r
+}\r
+\r
+const char* LogicExceptionImpl::ErrorMessage() const throw()\r
+{\r
+ return ExceptionBase::what();\r
+}\r
+\r
+const char* LogicExceptionImpl::what() const throw()\r
+{\r
+ return ExceptionBase::what();\r
+}\r
+\r
+// (((((((( SQLExceptionImpl Implementation ))))))))\r
+\r
+SQLExceptionImpl::SQLExceptionImpl() throw()\r
+ : ExceptionBase(), mSqlCode(0), mEngineCode(0)\r
+{\r
+}\r
+\r
+SQLExceptionImpl::SQLExceptionImpl(const SQLExceptionImpl& copied) throw()\r
+ : IBPP::SQLException(), ExceptionBase(copied), mSqlCode(copied.mSqlCode),\r
+ mEngineCode(copied.mEngineCode)\r
+{\r
+}\r
+\r
+SQLExceptionImpl& SQLExceptionImpl::operator=(const SQLExceptionImpl& copied) throw()\r
+{\r
+ ExceptionBase::operator=(copied);\r
+ mSqlCode = copied.mSqlCode;\r
+ mEngineCode = copied.mEngineCode;\r
+ return *this;\r
+}\r
+\r
+SQLExceptionImpl::SQLExceptionImpl(const IBS& status, const std::string& context,\r
+ const char* message, ...) throw()\r
+{\r
+ va_list argptr;\r
+ va_start(argptr, message);\r
+ mWhat.assign("*** IBPP::SQLException ***\n");\r
+ raise(context, message, argptr);\r
+ va_end(argptr);\r
+ mSqlCode = status.SqlCode();\r
+ mEngineCode = status.EngineCode();\r
+ mWhat.append(status.ErrorMessage());\r
+}\r
+\r
+SQLExceptionImpl::~SQLExceptionImpl() throw ()\r
+{\r
+}\r
+\r
+const char* SQLExceptionImpl::Origin() const throw()\r
+{\r
+ return ExceptionBase::Origin();\r
+}\r
+\r
+const char* SQLExceptionImpl::ErrorMessage() const throw()\r
+{\r
+ return ExceptionBase::what();\r
+}\r
+\r
+const char* SQLExceptionImpl::what() const throw()\r
+{\r
+ return ExceptionBase::what();\r
+}\r
+\r
+int SQLExceptionImpl::SqlCode() const throw()\r
+{\r
+ return mSqlCode;\r
+}\r
+\r
+int SQLExceptionImpl::EngineCode() const throw()\r
+{\r
+ return mEngineCode;\r
+}\r
+\r
+// (((((((( WrongTypeImpl Implementation ))))))))\r
+\r
+// The following constructors are small and could be inlined, but for object\r
+// code compacity of the library it is much better to have them non-inlined.\r
+// The amount of code generated by compilers for a throw is well-enough.\r
+\r
+WrongTypeImpl::WrongTypeImpl() throw()\r
+ : IBPP::WrongType(), ExceptionBase()\r
+{\r
+}\r
+\r
+WrongTypeImpl::WrongTypeImpl(const WrongTypeImpl& copied) throw()\r
+ : IBPP::WrongType(), ExceptionBase(copied)\r
+{\r
+}\r
+\r
+WrongTypeImpl& WrongTypeImpl::operator=(const WrongTypeImpl& copied) throw()\r
+{\r
+ ExceptionBase::operator=(copied);\r
+ return *this;\r
+}\r
+\r
+WrongTypeImpl::WrongTypeImpl(const std::string& context, int sqlType, IITYPE varType,\r
+ const char* message, ...) throw()\r
+{\r
+ va_list argptr;\r
+ va_start(argptr, message);\r
+ mWhat.assign("*** IBPP::WrongType ***\n");\r
+ raise(context, message, argptr);\r
+ va_end(argptr);\r
+\r
+ std::string info;\r
+ switch (sqlType & ~1)\r
+ {\r
+ case SQL_TEXT : info.append("CHAR"); break;\r
+ case SQL_VARYING : info.append("VARCHAR"); break;\r
+ case SQL_SHORT : info.append("SMALLINT"); break;\r
+ case SQL_LONG : info.append("INTEGER"); break;\r
+ case SQL_INT64 : info.append("BIGINT"); break;\r
+ case SQL_FLOAT : info.append("FLOAT"); break;\r
+ case SQL_DOUBLE : info.append("DOUBLE"); break;\r
+ case SQL_TIMESTAMP : info.append("TIMESTAMP"); break;\r
+ case SQL_TYPE_DATE : info.append("DATE"); break;\r
+ case SQL_TYPE_TIME : info.append("TIME"); break;\r
+ case SQL_BLOB : info.append("BLOB"); break;\r
+ case SQL_ARRAY : info.append("ARRAY"); break;\r
+ }\r
+ info.append(" ").append(_(" and ")).append(" ");\r
+ switch (varType)\r
+ {\r
+ case ivArray : info.append("Array"); break;\r
+ case ivBlob : info.append("Blob"); break;\r
+ case ivDate : info.append("Date"); break;\r
+ case ivTime : info.append("Time"); break;\r
+ case ivTimestamp : info.append("Timestamp"); break;\r
+ case ivString : info.append("std::string"); break;\r
+ case ivInt16 : info.append("int16_t"); break;\r
+ case ivInt32 : info.append("int32_t"); break;\r
+ case ivInt64 : info.append("int64_t"); break;\r
+ case ivFloat : info.append("float"); break;\r
+ case ivDouble : info.append("double"); break;\r
+ case ivBool : info.append("bool"); break;\r
+ case ivDBKey : info.append("DBKey"); break;\r
+ case ivByte : info.append("int8_t"); break;\r
+ }\r
+ mWhat.append(info).append("\n");\r
+}\r
+\r
+WrongTypeImpl::~WrongTypeImpl() throw ()\r
+{\r
+}\r
+\r
+const char* WrongTypeImpl::Origin() const throw()\r
+{\r
+ return ExceptionBase::Origin();\r
+}\r
+\r
+const char* WrongTypeImpl::ErrorMessage() const throw()\r
+{\r
+ return ExceptionBase::what();\r
+}\r
+\r
+const char* WrongTypeImpl::what() const throw()\r
+{\r
+ return ExceptionBase::what();\r
+}\r
+\r
+//\r
+// EOF\r
+//\r
--- /dev/null
+/*\r
+ * MODULE: ibase.h\r
+ * DESCRIPTION: OSRI entrypoints and defines\r
+ *\r
+ * The contents of this file are subject to the Interbase Public\r
+ * License Version 1.0 (the "License"); you may not use this file\r
+ * except in compliance with the License. You may obtain a copy\r
+ * of the License at http://www.Inprise.com/IPL.html\r
+ *\r
+ * Software distributed under the License is distributed on an\r
+ * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express\r
+ * or implied. See the License for the specific language governing\r
+ * rights and limitations under the License.\r
+ *\r
+ * The Original Code was created by Inprise Corporation\r
+ * and its predecessors. Portions created by Inprise Corporation are\r
+ * Copyright (C) Inprise Corporation.\r
+ *\r
+ * All Rights Reserved.\r
+ * Contributor(s): ______________________________________.\r
+ * Added TCP_NO_DELAY option for superserver on Linux\r
+ * FSG 16.03.2001\r
+ * 2001.07.28: John Bellardo: Added blr_skip\r
+ * 2001.09.18: Ann Harrison: New info codes\r
+ * 17-Oct-2001 Mike Nordell: CPU affinity\r
+ * 2001-04-16 Paul Beach: ISC_TIME_SECONDS_PRECISION_SCALE modified for HP10\r
+ * Compiler Compatibility\r
+ * 2002.02.15 Sean Leyne - Code Cleanup, removed obsolete ports:\r
+ * - EPSON, XENIX, MAC (MAC_AUX), Cray and OS/2\r
+ * 2002.10.29 Nickolay Samofatov: Added support for savepoints\r
+ *\r
+ * 2002.10.29 Sean Leyne - Removed support for obsolete IPX/SPX Protocol\r
+ *\r
+ */\r
+/*\r
+$Id: ibase.h,v 1.2 2007/05/17 08:39:25 faust Exp $\r
+ */\r
+\r
+#ifndef JRD_IBASE_H\r
+#define JRD_IBASE_H\r
+\r
+\r
+/*\r
+ *\r
+ * The contents of this file are subject to the Mozilla Public\r
+ * License Version 1.1 (the "License"); you may not use this file\r
+ * except in compliance with the License. You may obtain a copy of\r
+ * the License at http://www.mozilla.org/MPL/\r
+ * Alternatively, the contents of this file may be used under the\r
+ * terms of the GNU General Public License Version 2 or later (the\r
+ * "GPL"), in which case the provisions of the GPL are applicable\r
+ * instead of those above. You may obtain a copy of the Licence at\r
+ * http://www.gnu.org/copyleft/gpl.html\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * Relevant for more details.\r
+ *\r
+ * This file was created by members of the firebird development team.\r
+ * All individual contributions remain the Copyright (C) of those\r
+ * individuals. Contributors to this file are either listed here or\r
+ * can be obtained from a CVS history command.\r
+ *\r
+ * All rights reserved.\r
+ *\r
+ * Contributor(s):\r
+ * Mike Nordel <tamlin@algonet.se>\r
+ * Mark O'Donohue <mark.odonohue@ludwig.edu.au>\r
+ *\r
+ *\r
+ * $Id: ibase.h,v 1.2 2007/05/17 08:39:25 faust Exp $\r
+ *\r
+ * 2002.02.15 Sean Leyne - Code Cleanup, removed obsolete "OS/2" port\r
+ *\r
+ */\r
+\r
+\r
+#ifndef INCLUDE_FB_TYPES_H\r
+#define INCLUDE_FB_TYPES_H\r
+\r
+\r
+/******************************************************************/\r
+/* Define type, export and other stuff based on c/c++ and Windows */\r
+/******************************************************************/\r
+\r
+#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)\r
+#ifndef __GNUC__\r
+typedef __int64 ISC_INT64;\r
+typedef unsigned __int64 ISC_UINT64;\r
+#define ISC_INT64_DEFINED\r
+#endif\r
+#define ISC_EXPORT __stdcall\r
+#define ISC_EXPORT_VARARG __cdecl\r
+#else\r
+#define ISC_EXPORT\r
+#define ISC_EXPORT_VARARG\r
+#endif\r
+\r
+/*******************************************************************/\r
+/* 64 bit Integers */\r
+/*******************************************************************/\r
+\r
+#ifdef ISC_INT64_DEFINED\r
+#undef ISC_INT64_DEFINED\r
+#else\r
+typedef long long int ISC_INT64;\r
+typedef unsigned long long int ISC_UINT64;\r
+#endif\r
+\r
+// Nickolay: it is easier to assume that integer is at least 32-bit.\r
+// This comes from limitation that we cannot reliably detect datatype size at\r
+// compile time in cases when we do not control compilation (public headers) \r
+// We are not going to support 16-bit platforms, right?\r
+//\r
+// Temporarly restrict new definition until ULONG clash with Windows\r
+// type is solved. Win64 port is not possible before that point.\r
+// Cannot use SIZEOF_LONG define here because we are in a public header\r
+#if defined(_LP64) || defined(__LP64__) || defined(__arch64__)\r
+ /* EKU: Firebird requires (S)LONG to be 32 bit */\r
+# define LONG_DEFINED\r
+ typedef int SLONG;\r
+ typedef unsigned int ULONG;\r
+#endif /* SIZEOF_LONG == 8 */\r
+\r
+\r
+\r
+/* Basic data types */\r
+\r
+\r
+#ifdef NOT_USED_OR_REPLACED\r
+typedef signed char SCHAR;\r
+#else\r
+/* TMN: TODO It seems SCHAR is used just about *everywhere* where a plain\r
+ * "char" is really intended. This currently forces us to this bad definition.\r
+ */\r
+typedef char SCHAR;\r
+#endif\r
+\r
+\r
+typedef unsigned char UCHAR;\r
+typedef short SSHORT;\r
+typedef unsigned short USHORT;\r
+\r
+\r
+#ifndef LONG_DEFINED /* 32 bit */\r
+typedef long SLONG;\r
+typedef unsigned long ULONG;\r
+#else\r
+#undef LONG_DEFINED\r
+#endif\r
+\r
+\r
+#ifndef SQUAD_DEFINED /* 64 bit */\r
+typedef struct {\r
+ SLONG high;\r
+ ULONG low;\r
+} SQUAD;\r
+#endif\r
+\r
+\r
+#ifndef DEFINED_GDS_QUAD\r
+#define DEFINED_GDS_QUAD\r
+struct GDS_QUAD_t {\r
+ SLONG gds_quad_high;\r
+ ULONG gds_quad_low;\r
+};\r
+\r
+typedef struct GDS_QUAD_t GDS_QUAD;\r
+\r
+#endif /* DEFINED_GDS_QUAD */\r
+\r
+//\r
+// TMN: some misc data types from all over the place\r
+//\r
+struct vary\r
+{\r
+ USHORT vary_length;\r
+ char vary_string[1];\r
+};\r
+// TMN: Currently we can't do this, since remote uses a different\r
+// definition of VARY than the rest of the code! :-<\r
+//typedef vary* VARY;\r
+\r
+struct lstring\r
+{\r
+ ULONG lstr_length;\r
+ ULONG lstr_allocated;\r
+ UCHAR* lstr_address;\r
+};\r
+typedef struct lstring LSTRING;\r
+\r
+\r
+typedef unsigned char BOOLEAN;\r
+typedef char TEXT; // To be expunged over time\r
+//typedef unsigned char STEXT; Signed text - not used\r
+//typedef unsigned char UTEXT; Unsigned text - not used\r
+typedef unsigned char BYTE; // Unsigned byte - common\r
+//typedef char SBYTE; Signed byte - not used\r
+typedef long ISC_STATUS;\r
+typedef long IPTR;\r
+typedef unsigned long U_IPTR;\r
+typedef void (*FPTR_VOID) ();\r
+typedef void (*FPTR_VOID_PTR) (void *);\r
+typedef int (*FPTR_INT) ();\r
+typedef int (*FPTR_INT_VOID_PTR) (void *);\r
+typedef ULONG RCRD_OFFSET;\r
+typedef USHORT FLD_LENGTH;\r
+typedef int (*lock_ast_t)(void *);\r
+\r
+typedef IPTR FB_THREAD_ID;\r
+\r
+#define ISC_STATUS_LENGTH 20\r
+typedef ISC_STATUS ISC_STATUS_ARRAY[ISC_STATUS_LENGTH];\r
+\r
+/* Number of elements in an arry */\r
+#define FB_NELEM(x) ((int)(sizeof(x) / sizeof(x[0])))\r
+#define FB_ALIGN(n,b) ((n+b-1)&~(b-1))\r
+\r
+#endif /* INCLUDE_FB_TYPES_H */\r
+\r
+#define FB_API_VER 15\r
+#define isc_version4\r
+\r
+#define ISC_TRUE 1\r
+#define ISC_FALSE 0\r
+#if !(defined __cplusplus)\r
+#define ISC__TRUE ISC_TRUE\r
+#define ISC__FALSE ISC_FALSE\r
+#endif\r
+\r
+#define ISC_FAR\r
+\r
+// It is difficult to detect 64-bit long from the redistributable header\r
+// we do not care of 16-bit platforms anymore thus we may use plain "int"\r
+// which is 32-bit on all platforms we support\r
+#if defined(_LP64) || defined(__LP64__) || defined(__arch64__)\r
+typedef int ISC_LONG;\r
+typedef unsigned int ISC_ULONG;\r
+#else\r
+typedef signed long ISC_LONG;\r
+typedef unsigned long ISC_ULONG;\r
+#endif\r
+\r
+typedef signed short ISC_SHORT;\r
+typedef unsigned short ISC_USHORT;\r
+\r
+typedef unsigned char ISC_UCHAR;\r
+\r
+#define DSQL_close 1\r
+#define DSQL_drop 2\r
+\r
+\r
+/********************************/\r
+/* InterBase Handle Definitions */\r
+/********************************/\r
+\r
+#ifndef JRD_Y_REF_H\r
+#define FRBRD void\r
+#endif\r
+\r
+typedef FRBRD * isc_att_handle;\r
+typedef FRBRD * isc_blob_handle;\r
+typedef FRBRD * isc_db_handle;\r
+typedef FRBRD * isc_req_handle;\r
+typedef FRBRD * isc_stmt_handle;\r
+typedef FRBRD * isc_svc_handle;\r
+typedef FRBRD * isc_tr_handle;\r
+typedef void (* isc_callback) ();\r
+typedef ISC_LONG isc_resv_handle;\r
+\r
+/*******************************************************************/\r
+/* Time & Date Support */\r
+/*******************************************************************/\r
+\r
+#ifndef ISC_TIMESTAMP_DEFINED\r
+typedef int ISC_DATE;\r
+typedef unsigned int ISC_TIME;\r
+typedef struct\r
+{\r
+ ISC_DATE timestamp_date;\r
+ ISC_TIME timestamp_time;\r
+} ISC_TIMESTAMP;\r
+#define ISC_TIMESTAMP_DEFINED\r
+#endif /* ISC_TIMESTAMP_DEFINED */\r
+\r
+#define ISC_TIME_SECONDS_PRECISION 10000L\r
+#define ISC_TIME_SECONDS_PRECISION_SCALE (-4)\r
+\r
+/*******************************************************************/\r
+/* Blob id structure */\r
+/*******************************************************************/\r
+\r
+#if !(defined __cplusplus)\r
+typedef GDS_QUAD GDS__QUAD;\r
+#endif /* !(defined __cplusplus) */\r
+\r
+typedef struct GDS_QUAD_t ISC_QUAD;\r
+\r
+#define isc_quad_high gds_quad_high\r
+#define isc_quad_low gds_quad_low\r
+\r
+typedef struct\r
+{\r
+ short array_bound_lower;\r
+ short array_bound_upper;\r
+} ISC_ARRAY_BOUND;\r
+\r
+typedef struct\r
+{\r
+ unsigned char array_desc_dtype;\r
+ char array_desc_scale;\r
+ unsigned short array_desc_length;\r
+ char array_desc_field_name[32];\r
+ char array_desc_relation_name[32];\r
+ short array_desc_dimensions;\r
+ short array_desc_flags;\r
+ ISC_ARRAY_BOUND array_desc_bounds[16];\r
+} ISC_ARRAY_DESC;\r
+\r
+typedef struct\r
+{\r
+ short blob_desc_subtype;\r
+ short blob_desc_charset;\r
+ short blob_desc_segment_size;\r
+ unsigned char blob_desc_field_name[32];\r
+ unsigned char blob_desc_relation_name[32];\r
+} ISC_BLOB_DESC;\r
+\r
+\r
+\r
+/***************************/\r
+/* Blob control structure */\r
+/***************************/\r
+\r
+typedef struct isc_blob_ctl\r
+{\r
+ ISC_STATUS (* ctl_source)(); /* Source filter */\r
+ struct isc_blob_ctl * ctl_source_handle; /* Argument to pass to source filter */\r
+ short ctl_to_sub_type; /* Target type */\r
+ short ctl_from_sub_type; /* Source type */\r
+ unsigned short ctl_buffer_length; /* Length of buffer */\r
+ unsigned short ctl_segment_length; /* Length of current segment */\r
+ unsigned short ctl_bpb_length; /* Length of blob parameter block */\r
+ char * ctl_bpb; /* Address of blob parameter block */\r
+ unsigned char * ctl_buffer; /* Address of segment buffer */\r
+ ISC_LONG ctl_max_segment; /* Length of longest segment */\r
+ ISC_LONG ctl_number_segments; /* Total number of segments */\r
+ ISC_LONG ctl_total_length; /* Total length of blob */\r
+ ISC_STATUS * ctl_status; /* Address of status vector */\r
+ long ctl_data[8]; /* Application specific data */\r
+} * ISC_BLOB_CTL;\r
+\r
+/***************************/\r
+/* Blob stream definitions */\r
+/***************************/\r
+\r
+typedef struct bstream\r
+{\r
+ isc_blob_handle bstr_blob; /* Blob handle */\r
+ char * bstr_buffer; /* Address of buffer */\r
+ char * bstr_ptr; /* Next character */\r
+ short bstr_length; /* Length of buffer */\r
+ short bstr_cnt; /* Characters in buffer */\r
+ char bstr_mode; /* (mode) ? OUTPUT : INPUT */\r
+} BSTREAM;\r
+\r
+/* Three ugly macros, one even using octal radix... sigh... */\r
+#define getb(p) (--(p)->bstr_cnt >= 0 ? *(p)->bstr_ptr++ & 0377: BLOB_get (p))\r
+#define putb(x,p) (((x) == '\n' || (!(--(p)->bstr_cnt))) ? BLOB_put ((x),p) : ((int) (*(p)->bstr_ptr++ = (unsigned) (x))))\r
+#define putbx(x,p) ((!(--(p)->bstr_cnt)) ? BLOB_put ((x),p) : ((int) (*(p)->bstr_ptr++ = (unsigned) (x))))\r
+\r
+\r
+/********************************************************************/\r
+/* CVC: Public blob interface definition held in val.h. */\r
+/* For some unknown reason, it was only documented in langRef */\r
+/* and being the structure passed by the engine to UDFs it never */\r
+/* made its way into this public definitions file. */\r
+/* Being its original name "blob", I renamed it blobcallback here. */\r
+/* I did the full definition with the proper parameters instead of */\r
+/* the weak C declaration with any number and type of parameters. */\r
+/* Since the first parameter -BLB- is unknown outside the engine, */\r
+/* it's more accurate to use void* than int* as the blob pointer */\r
+/********************************************************************/\r
+\r
+#if !defined(JRD_VAL_H) && !defined(REQUESTER)\r
+/* Blob passing structure */\r
+\r
+enum lseek_mode {blb_seek_relative = 1, blb_seek_from_tail = 2};\r
+\r
+typedef struct blobcallback {\r
+ short ( *blob_get_segment)\r
+ (void * hnd, unsigned char* buffer, ISC_USHORT buf_size, ISC_USHORT* result_len);\r
+ void *blob_handle;\r
+ ISC_LONG blob_number_segments;\r
+ ISC_LONG blob_max_segment;\r
+ ISC_LONG blob_total_length;\r
+ void ( *blob_put_segment)\r
+ (void * hnd, unsigned char* buffer, ISC_USHORT buf_size);\r
+ ISC_LONG ( *blob_lseek)\r
+ (void * hnd, ISC_USHORT mode, ISC_LONG offset);\r
+} *BLOBCALLBACK;\r
+#endif /* !defined(JRD_VAL_H) && !defined(REQUESTER) */\r
+\r
+\r
+\r
+/********************************************************************/\r
+/* CVC: Public descriptor interface held in dsc.h. */\r
+/* We need it documented to be able to recognize NULL in UDFs. */\r
+/* Being its original name "dsc", I renamed it paramdsc here. */\r
+/* Notice that I adjust to the original definition: contrary to */\r
+/* other cases, the typedef is the same struct not the pointer. */\r
+/* I included the enumeration of dsc_dtype possible values. */\r
+/* Ultimately, dsc.h should be part of the public interface. */\r
+/********************************************************************/\r
+\r
+#if !defined(JRD_DSC_H)\r
+/* This is the famous internal descriptor that UDFs can use, too. */\r
+typedef struct paramdsc {\r
+ unsigned char dsc_dtype;\r
+ signed char dsc_scale;\r
+ ISC_USHORT dsc_length;\r
+ short dsc_sub_type;\r
+ ISC_USHORT dsc_flags;\r
+ unsigned char *dsc_address;\r
+} PARAMDSC;\r
+\r
+#if !defined(JRD_VAL_H)\r
+/* This is a helper struct to work with varchars. */\r
+typedef struct paramvary {\r
+ ISC_USHORT vary_length;\r
+ unsigned char vary_string [1];\r
+} PARAMVARY;\r
+#endif /* !defined(JRD_VAL_H) */\r
+\r
+/* values for dsc_flags */\r
+/* Note: DSC_null is only reliably set for local variables\r
+ (blr_variable) */\r
+#define DSC_null 1\r
+#define DSC_no_subtype 2 /* dsc has no sub type specified */\r
+#define DSC_nullable 4 /* not stored. instead, is derived\r
+ from metadata primarily to flag\r
+ SQLDA (in DSQL) */\r
+\r
+/* Overload text typing information into the dsc_sub_type field.\r
+ See intl.h for definitions of text types */ \r
+\r
+#ifndef dsc_ttype\r
+#define dsc_ttype dsc_sub_type\r
+#endif\r
+\r
+\r
+/* Note that dtype_null actually means that we do not yet know the\r
+ dtype for this descriptor. A nice cleanup item would be to globally\r
+ change it to dtype_unknown. --chrisj 1999-02-17 */\r
+\r
+#define dtype_null 0\r
+#define dtype_text 1\r
+#define dtype_cstring 2\r
+#define dtype_varying 3\r
+\r
+#define dtype_packed 6\r
+#define dtype_byte 7\r
+#define dtype_short 8\r
+#define dtype_long 9\r
+#define dtype_quad 10\r
+#define dtype_real 11\r
+#define dtype_double 12\r
+#define dtype_d_float 13\r
+#define dtype_sql_date 14\r
+#define dtype_sql_time 15\r
+#define dtype_timestamp 16\r
+#define dtype_blob 17\r
+#define dtype_array 18\r
+#define dtype_int64 19\r
+#define DTYPE_TYPE_MAX 20\r
+#endif /* !defined(JRD_DSC_H) */\r
+\r
+\r
+/***************************/\r
+/* Dynamic SQL definitions */\r
+/***************************/\r
+\r
+/******************************/\r
+/* Declare the extended SQLDA */\r
+/******************************/\r
+\r
+#ifndef FB_SQLDA\r
+\r
+typedef struct\r
+{\r
+ short sqltype; /* datatype of field */\r
+ short sqlscale; /* scale factor */\r
+ short sqlsubtype; /* datatype subtype - BLOBs & Text types only */\r
+ short sqllen; /* length of data area */\r
+ char * sqldata; /* address of data */\r
+ short * sqlind; /* address of indicator variable */\r
+ short sqlname_length; /* length of sqlname field */\r
+ char sqlname[32]; /* name of field, name length + space for NULL */\r
+ short relname_length; /* length of relation name */\r
+ char relname[32]; /* field's relation name + space for NULL */\r
+ short ownname_length; /* length of owner name */\r
+ char ownname[32]; /* relation's owner name + space for NULL */\r
+ short aliasname_length; /* length of alias name */\r
+ char aliasname[32]; /* relation's alias name + space for NULL */\r
+} XSQLVAR;\r
+\r
+typedef struct\r
+{\r
+ short version; /* version of this XSQLDA */\r
+ char sqldaid[8]; /* XSQLDA name field */\r
+ ISC_LONG sqldabc; /* length in bytes of SQLDA */\r
+ short sqln; /* number of fields allocated */\r
+ short sqld; /* actual number of fields */\r
+ XSQLVAR sqlvar[1]; /* first field address */\r
+} XSQLDA;\r
+\r
+#define XSQLDA_LENGTH(n) (sizeof (XSQLDA) + ((n)-1) * sizeof (XSQLVAR))\r
+\r
+#define SQLDA_VERSION1 1\r
+\r
+#define SQL_DIALECT_V5 1 /* meaning is same as DIALECT_xsqlda */\r
+#define SQL_DIALECT_V6_TRANSITION 2 /* flagging anything that is delimited\r
+ by double quotes as an error and\r
+ flagging keyword DATE as an error */\r
+#define SQL_DIALECT_V6 3 /* supports SQL delimited identifier,\r
+ SQLDATE/DATE, TIME, TIMESTAMP,\r
+ CURRENT_DATE, CURRENT_TIME,\r
+ CURRENT_TIMESTAMP, and 64-bit exact\r
+ numeric type */\r
+#define SQL_DIALECT_CURRENT SQL_DIALECT_V6 /* latest IB DIALECT */\r
+\r
+\r
+#define FB_SQLDA\r
+#endif\r
+\r
+/***************************/\r
+/* OSRI database functions */\r
+/***************************/\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+ISC_STATUS ISC_EXPORT isc_attach_database(ISC_STATUS *,\r
+ short,\r
+ char *,\r
+ isc_db_handle *,\r
+ short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_array_gen_sdl(ISC_STATUS *,\r
+ ISC_ARRAY_DESC *,\r
+ short *,\r
+ char *,\r
+ short *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_array_get_slice(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ ISC_QUAD *,\r
+ ISC_ARRAY_DESC *,\r
+ void *,\r
+ ISC_LONG *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_array_lookup_bounds(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ char *,\r
+ char *,\r
+ ISC_ARRAY_DESC *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_array_lookup_desc(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ char *,\r
+ char *,\r
+ ISC_ARRAY_DESC *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_array_set_desc(ISC_STATUS *,\r
+ char *,\r
+ char *,\r
+ short *,\r
+ short *,\r
+ short *,\r
+ ISC_ARRAY_DESC *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_array_put_slice(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ ISC_QUAD *,\r
+ ISC_ARRAY_DESC *,\r
+ void *,\r
+ ISC_LONG *);\r
+\r
+void ISC_EXPORT isc_blob_default_desc(ISC_BLOB_DESC *,\r
+ unsigned char *,\r
+ unsigned char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_blob_gen_bpb(ISC_STATUS *,\r
+ ISC_BLOB_DESC *,\r
+ ISC_BLOB_DESC *,\r
+ unsigned short,\r
+ unsigned char *,\r
+ unsigned short *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_blob_info(ISC_STATUS *,\r
+ isc_blob_handle *,\r
+ short,\r
+ char *,\r
+ short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_blob_lookup_desc(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ unsigned char *,\r
+ unsigned char *,\r
+ ISC_BLOB_DESC *,\r
+ unsigned char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_blob_set_desc(ISC_STATUS *,\r
+ unsigned char *,\r
+ unsigned char *,\r
+ short,\r
+ short,\r
+ short,\r
+ ISC_BLOB_DESC *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_cancel_blob(ISC_STATUS *,\r
+ isc_blob_handle *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_cancel_events(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ ISC_LONG *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_close_blob(ISC_STATUS *,\r
+ isc_blob_handle *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_commit_retaining(ISC_STATUS *,\r
+ isc_tr_handle *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_commit_transaction(ISC_STATUS *,\r
+ isc_tr_handle *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_create_blob(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ isc_blob_handle *,\r
+ ISC_QUAD *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_create_blob2(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ isc_blob_handle *,\r
+ ISC_QUAD *,\r
+ short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_create_database(ISC_STATUS *,\r
+ short,\r
+ char *,\r
+ isc_db_handle *,\r
+ short,\r
+ char *,\r
+ short);\r
+\r
+ISC_STATUS ISC_EXPORT isc_database_info(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ short,\r
+ char *,\r
+ short,\r
+ char *);\r
+\r
+void ISC_EXPORT isc_decode_date(ISC_QUAD *,\r
+ void *);\r
+\r
+void ISC_EXPORT isc_decode_sql_date(ISC_DATE *,\r
+ void *);\r
+\r
+void ISC_EXPORT isc_decode_sql_time(ISC_TIME *,\r
+ void *);\r
+\r
+void ISC_EXPORT isc_decode_timestamp(ISC_TIMESTAMP *,\r
+ void *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_detach_database(ISC_STATUS *,\r
+ isc_db_handle *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_drop_database(ISC_STATUS *,\r
+ isc_db_handle *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_allocate_statement(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_stmt_handle *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_alloc_statement2(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_stmt_handle *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_describe(ISC_STATUS *,\r
+ isc_stmt_handle *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_describe_bind(ISC_STATUS *,\r
+ isc_stmt_handle *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_exec_immed2(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ XSQLDA *,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_execute(ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ isc_stmt_handle *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_execute2(ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ isc_stmt_handle *,\r
+ unsigned short,\r
+ XSQLDA *,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_execute_immediate(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_fetch(ISC_STATUS *,\r
+ isc_stmt_handle *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_finish(isc_db_handle *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_free_statement(ISC_STATUS *,\r
+ isc_stmt_handle *,\r
+ unsigned short);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_insert(ISC_STATUS *,\r
+ isc_stmt_handle *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_prepare(ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ isc_stmt_handle *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_set_cursor_name(ISC_STATUS *,\r
+ isc_stmt_handle *,\r
+ char *,\r
+ unsigned short);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_sql_info(ISC_STATUS *,\r
+ isc_stmt_handle *,\r
+ short,\r
+ const char *,\r
+ short,\r
+ char *);\r
+\r
+void ISC_EXPORT isc_encode_date(void *,\r
+ ISC_QUAD *);\r
+\r
+void ISC_EXPORT isc_encode_sql_date(void *,\r
+ ISC_DATE *);\r
+\r
+void ISC_EXPORT isc_encode_sql_time(void *,\r
+ ISC_TIME *);\r
+\r
+void ISC_EXPORT isc_encode_timestamp(void *,\r
+ ISC_TIMESTAMP *);\r
+\r
+ISC_LONG ISC_EXPORT_VARARG isc_event_block(char * *,\r
+ char * *,\r
+ unsigned short, ...);\r
+\r
+void ISC_EXPORT isc_event_counts(ISC_ULONG *,\r
+ short,\r
+ char *,\r
+ char *);\r
+\r
+/* 17 May 2001 - isc_expand_dpb is DEPRECATED */\r
+void ISC_EXPORT_VARARG isc_expand_dpb(char * *,\r
+ short *, ...);\r
+\r
+int ISC_EXPORT isc_modify_dpb(char * *,\r
+ short *,\r
+ unsigned short,\r
+ char *,\r
+ short);\r
+\r
+ISC_LONG ISC_EXPORT isc_free(char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_get_segment(ISC_STATUS *,\r
+ isc_blob_handle *,\r
+ unsigned short *,\r
+ unsigned short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_get_slice(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ ISC_QUAD *,\r
+ short,\r
+ char *,\r
+ short,\r
+ ISC_LONG *,\r
+ ISC_LONG,\r
+ void *,\r
+ ISC_LONG *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_interprete(char *,\r
+ ISC_STATUS * *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_open_blob(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ isc_blob_handle *,\r
+ ISC_QUAD *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_open_blob2(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ isc_blob_handle *,\r
+ ISC_QUAD *,\r
+ ISC_USHORT,\r
+ ISC_UCHAR *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_prepare_transaction2(ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ ISC_USHORT,\r
+ ISC_UCHAR *);\r
+\r
+void ISC_EXPORT isc_print_sqlerror(ISC_SHORT,\r
+ ISC_STATUS *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_print_status(ISC_STATUS *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_put_segment(ISC_STATUS *,\r
+ isc_blob_handle *,\r
+ unsigned short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_put_slice(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ ISC_QUAD *,\r
+ short,\r
+ char *,\r
+ short,\r
+ ISC_LONG *,\r
+ ISC_LONG,\r
+ void *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_que_events(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ ISC_LONG *,\r
+ short,\r
+ char *,\r
+ isc_callback,\r
+ void *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_rollback_retaining(ISC_STATUS *,\r
+ isc_tr_handle *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_rollback_transaction(ISC_STATUS *,\r
+ isc_tr_handle *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_start_multiple(ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ short,\r
+ void *);\r
+\r
+ISC_STATUS ISC_EXPORT_VARARG isc_start_transaction(ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ short, ...);\r
+\r
+ISC_LONG ISC_EXPORT isc_sqlcode(ISC_STATUS *);\r
+\r
+void ISC_EXPORT isc_sql_interprete(short,\r
+ char *,\r
+ short);\r
+\r
+ISC_STATUS ISC_EXPORT isc_transaction_info(ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ short,\r
+ char *,\r
+ short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_transact_request(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ char *);\r
+\r
+ISC_LONG ISC_EXPORT isc_vax_integer(char *,\r
+ short);\r
+\r
+ISC_INT64 ISC_EXPORT isc_portable_integer(unsigned char *,\r
+ short);\r
+\r
+/*************************************/\r
+/* Security Functions and structures */\r
+/*************************************/\r
+\r
+#define sec_uid_spec 0x01\r
+#define sec_gid_spec 0x02\r
+#define sec_server_spec 0x04\r
+#define sec_password_spec 0x08\r
+#define sec_group_name_spec 0x10\r
+#define sec_first_name_spec 0x20\r
+#define sec_middle_name_spec 0x40\r
+#define sec_last_name_spec 0x80\r
+#define sec_dba_user_name_spec 0x100\r
+#define sec_dba_password_spec 0x200\r
+\r
+#define sec_protocol_tcpip 1\r
+#define sec_protocol_netbeui 2\r
+#define sec_protocol_spx 3 /* -- Deprecated Protocol. Declaration retained for compatibility */\r
+#define sec_protocol_local 4\r
+\r
+typedef struct {\r
+ short sec_flags; /* which fields are specified */\r
+ int uid; /* the user's id */\r
+ int gid; /* the user's group id */\r
+ int protocol; /* protocol to use for connection */\r
+ char *server; /* server to administer */\r
+ char *user_name; /* the user's name */\r
+ char *password; /* the user's password */\r
+ char *group_name; /* the group name */\r
+ char *first_name; /* the user's first name */\r
+ char *middle_name; /* the user's middle name */\r
+ char *last_name; /* the user's last name */\r
+ char *dba_user_name; /* the dba user name */\r
+ char *dba_password; /* the dba password */\r
+} USER_SEC_DATA;\r
+\r
+int ISC_EXPORT isc_add_user(ISC_STATUS *, USER_SEC_DATA *);\r
+\r
+int ISC_EXPORT isc_delete_user(ISC_STATUS *, USER_SEC_DATA *);\r
+\r
+int ISC_EXPORT isc_modify_user(ISC_STATUS *, USER_SEC_DATA *);\r
+\r
+/**********************************/\r
+/* Other OSRI functions */\r
+/**********************************/\r
+\r
+ISC_STATUS ISC_EXPORT isc_compile_request(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_req_handle *,\r
+ short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_compile_request2(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_req_handle *,\r
+ short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_ddl(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_prepare_transaction(ISC_STATUS *,\r
+ isc_tr_handle *);\r
+\r
+\r
+ISC_STATUS ISC_EXPORT isc_receive(ISC_STATUS *,\r
+ isc_req_handle *,\r
+ short,\r
+ short,\r
+ void *,\r
+ short);\r
+\r
+ISC_STATUS ISC_EXPORT isc_reconnect_transaction(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_release_request(ISC_STATUS *,\r
+ isc_req_handle *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_request_info(ISC_STATUS *,\r
+ isc_req_handle *,\r
+ short,\r
+ short,\r
+ char *,\r
+ short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_seek_blob(ISC_STATUS *,\r
+ isc_blob_handle *,\r
+ short,\r
+ ISC_LONG,\r
+ ISC_LONG *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_send(ISC_STATUS *,\r
+ isc_req_handle *,\r
+ short,\r
+ short,\r
+ void *,\r
+ short);\r
+\r
+ISC_STATUS ISC_EXPORT isc_start_and_send(ISC_STATUS *,\r
+ isc_req_handle *,\r
+ isc_tr_handle *,\r
+ short,\r
+ short,\r
+ void *,\r
+ short);\r
+\r
+ISC_STATUS ISC_EXPORT isc_start_request(ISC_STATUS *,\r
+ isc_req_handle *,\r
+ isc_tr_handle *,\r
+ short);\r
+\r
+ISC_STATUS ISC_EXPORT isc_unwind_request(ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ short);\r
+\r
+ISC_STATUS ISC_EXPORT isc_wait_for_event(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ short,\r
+ char *,\r
+ char *);\r
+\r
+\r
+/*****************************/\r
+/* Other Sql functions */\r
+/*****************************/\r
+\r
+ISC_STATUS ISC_EXPORT isc_close(ISC_STATUS *,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_declare(ISC_STATUS *,\r
+ char *,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_describe(ISC_STATUS *,\r
+ char *,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_describe_bind(ISC_STATUS *,\r
+ char *,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_execute(ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ char *,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_execute_immediate(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ short *,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_fetch(ISC_STATUS *,\r
+ char *,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_open(ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ char *,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_prepare(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ char *,\r
+ short *,\r
+ char *,\r
+ XSQLDA *);\r
+\r
+\r
+/*************************************/\r
+/* Other Dynamic sql functions */\r
+/*************************************/\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_execute_m(ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ isc_stmt_handle *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ unsigned short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_execute2_m(ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ isc_stmt_handle *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ unsigned short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_execute_immediate_m(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ unsigned short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_exec_immed3_m(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ unsigned short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_fetch_m(ISC_STATUS *,\r
+ isc_stmt_handle *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ unsigned short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_insert_m(ISC_STATUS *,\r
+ isc_stmt_handle *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ unsigned short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_prepare_m(ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ isc_stmt_handle *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_dsql_release(ISC_STATUS *,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_embed_dsql_close(ISC_STATUS *,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_embed_dsql_declare(ISC_STATUS *,\r
+ char *,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_embed_dsql_describe(ISC_STATUS *,\r
+ char *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_embed_dsql_describe_bind(ISC_STATUS *,\r
+ char *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_embed_dsql_execute(ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ char *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_embed_dsql_execute2(ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ char *,\r
+ unsigned short,\r
+ XSQLDA *,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_embed_dsql_execute_immed(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_embed_dsql_fetch(ISC_STATUS *,\r
+ char *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_embed_dsql_open(ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ char *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_embed_dsql_open2(ISC_STATUS *,\r
+ isc_tr_handle *,\r
+ char *,\r
+ unsigned short,\r
+ XSQLDA *,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_embed_dsql_insert(ISC_STATUS *,\r
+ char *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_embed_dsql_prepare(ISC_STATUS *,\r
+ isc_db_handle *,\r
+ isc_tr_handle *,\r
+ char *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ XSQLDA *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_embed_dsql_release(ISC_STATUS *,\r
+ char *);\r
+\r
+\r
+/******************************/\r
+/* Other Blob functions */\r
+/******************************/\r
+\r
+BSTREAM *ISC_EXPORT BLOB_open(isc_blob_handle,\r
+ char *,\r
+ int);\r
+\r
+int ISC_EXPORT BLOB_put(char,\r
+ BSTREAM *);\r
+\r
+int ISC_EXPORT BLOB_close(BSTREAM *);\r
+\r
+int ISC_EXPORT BLOB_get(BSTREAM *);\r
+\r
+int ISC_EXPORT BLOB_display(ISC_QUAD *,\r
+ isc_db_handle,\r
+ isc_tr_handle,\r
+ char *);\r
+\r
+int ISC_EXPORT BLOB_dump(ISC_QUAD *,\r
+ isc_db_handle,\r
+ isc_tr_handle,\r
+ char *);\r
+\r
+int ISC_EXPORT BLOB_edit(ISC_QUAD *,\r
+ isc_db_handle,\r
+ isc_tr_handle,\r
+ char *);\r
+\r
+int ISC_EXPORT BLOB_load(ISC_QUAD *,\r
+ isc_db_handle,\r
+ isc_tr_handle,\r
+ char *);\r
+\r
+int ISC_EXPORT BLOB_text_dump(ISC_QUAD *,\r
+ isc_db_handle,\r
+ isc_tr_handle,\r
+ char *);\r
+\r
+int ISC_EXPORT BLOB_text_load(ISC_QUAD *,\r
+ isc_db_handle,\r
+ isc_tr_handle,\r
+ char *);\r
+\r
+BSTREAM *ISC_EXPORT Bopen(ISC_QUAD *,\r
+ isc_db_handle,\r
+ isc_tr_handle,\r
+ char *);\r
+\r
+BSTREAM *ISC_EXPORT Bopen2(ISC_QUAD *,\r
+ isc_db_handle,\r
+ isc_tr_handle,\r
+ char *,\r
+ unsigned short);\r
+\r
+\r
+/******************************/\r
+/* Other Misc functions */\r
+/******************************/\r
+\r
+ISC_LONG ISC_EXPORT isc_ftof(char *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short);\r
+\r
+ISC_STATUS ISC_EXPORT isc_print_blr(char *,\r
+ isc_callback,\r
+ void *,\r
+ short);\r
+\r
+void ISC_EXPORT isc_set_debug(int);\r
+\r
+void ISC_EXPORT isc_qtoq(ISC_QUAD *,\r
+ ISC_QUAD *);\r
+\r
+void ISC_EXPORT isc_vtof(char *,\r
+ char *,\r
+ unsigned short);\r
+\r
+void ISC_EXPORT isc_vtov(char *,\r
+ char *,\r
+ short);\r
+\r
+int ISC_EXPORT isc_version(isc_db_handle *,\r
+ isc_callback,\r
+ void *);\r
+\r
+ISC_LONG ISC_EXPORT isc_reset_fpe(unsigned short);\r
+\r
+\r
+/*****************************************/\r
+/* Service manager functions */\r
+/*****************************************/\r
+\r
+#define ADD_SPB_LENGTH(p, length) {*(p)++ = (length); *(p)++ = (length) >> 8;}\r
+\r
+#define ADD_SPB_NUMERIC(p, data) {*(p)++ = (SCHAR) (data); *(p)++ = (SCHAR) ((data) >> 8); *(p)++ = (SCHAR) ((data) >> 16); *(p)++ = (SCHAR) ((data) >> 24);}\r
+\r
+ISC_STATUS ISC_EXPORT isc_service_attach(ISC_STATUS *,\r
+ unsigned short,\r
+ char *,\r
+ isc_svc_handle *,\r
+ unsigned short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_service_detach(ISC_STATUS *,\r
+ isc_svc_handle *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_service_query(ISC_STATUS *,\r
+ isc_svc_handle *,\r
+ isc_resv_handle *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ char *,\r
+ unsigned short,\r
+ char *);\r
+\r
+ISC_STATUS ISC_EXPORT isc_service_start(ISC_STATUS *,\r
+ isc_svc_handle *,\r
+ isc_resv_handle *,\r
+ unsigned short,\r
+ char *);\r
+\r
+\r
+/********************************/\r
+/* Client information functions */\r
+/********************************/\r
+\r
+void ISC_EXPORT isc_get_client_version ( char *);\r
+int ISC_EXPORT isc_get_client_major_version ();\r
+int ISC_EXPORT isc_get_client_minor_version ();\r
+\r
+#ifdef __cplusplus\r
+} /* extern "C" */\r
+#endif\r
+\r
+\r
+/***************************************************/\r
+/* Actions to pass to the blob filter (ctl_source) */\r
+/***************************************************/\r
+\r
+#define isc_blob_filter_open 0\r
+#define isc_blob_filter_get_segment 1\r
+#define isc_blob_filter_close 2\r
+#define isc_blob_filter_create 3\r
+#define isc_blob_filter_put_segment 4\r
+#define isc_blob_filter_alloc 5\r
+#define isc_blob_filter_free 6\r
+#define isc_blob_filter_seek 7\r
+\r
+/*******************/\r
+/* Blr definitions */\r
+/*******************/\r
+\r
+/*\r
+ * PROGRAM: C preprocessor\r
+ * MODULE: blr.h\r
+ * DESCRIPTION: BLR constants\r
+ *\r
+ * The contents of this file are subject to the Interbase Public\r
+ * License Version 1.0 (the "License"); you may not use this file\r
+ * except in compliance with the License. You may obtain a copy\r
+ * of the License at http://www.Inprise.com/IPL.html\r
+ *\r
+ * Software distributed under the License is distributed on an\r
+ * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express\r
+ * or implied. See the License for the specific language governing\r
+ * rights and limitations under the License.\r
+ *\r
+ * The Original Code was created by Inprise Corporation\r
+ * and its predecessors. Portions created by Inprise Corporation are\r
+ * Copyright (C) Inprise Corporation.\r
+ *\r
+ * All Rights Reserved.\r
+ * Contributor(s): ______________________________________.\r
+ *\r
+ * Claudio Valderrama: 2001.6.18: Add blr_current_role.\r
+ * 2002.09.28 Dmitry Yemanov: Reworked internal_info stuff, enhanced\r
+ * exception handling in SPs/triggers,\r
+ * implemented ROWS_AFFECTED system variable\r
+ * 2002.10.21 Nickolay Samofatov: Added support for explicit pessimistic locks\r
+ * 2002.10.29 Nickolay Samofatov: Added support for savepoints\r
+ */\r
+\r
+#ifndef _JRD_BLR_H_\r
+#define _JRD_BLR_H_\r
+\r
+/* WARNING: if you add a new BLR representing a data type, and the value\r
+ * is greater than the numerically greatest value which now\r
+ * represents a data type, you must change the define for\r
+ * DTYPE_BLR_MAX in jrd/align.h, and add the necessary entries\r
+ * to all the arrays in that file.\r
+ */\r
+\r
+#define blr_text (unsigned char)14\r
+#define blr_text2 (unsigned char)15 /* added in 3.2 JPN */\r
+#define blr_short (unsigned char)7\r
+#define blr_long (unsigned char)8\r
+#define blr_quad (unsigned char)9\r
+#define blr_float (unsigned char)10\r
+#define blr_double (unsigned char)27\r
+#define blr_d_float (unsigned char)11\r
+#define blr_timestamp (unsigned char)35\r
+#define blr_varying (unsigned char)37\r
+#define blr_varying2 (unsigned char)38 /* added in 3.2 JPN */\r
+#define blr_blob (unsigned short)261\r
+#define blr_cstring (unsigned char)40 \r
+#define blr_cstring2 (unsigned char)41 /* added in 3.2 JPN */\r
+#define blr_blob_id (unsigned char)45 /* added from gds.h */\r
+#define blr_sql_date (unsigned char)12\r
+#define blr_sql_time (unsigned char)13\r
+#define blr_int64 (unsigned char)16\r
+\r
+/* Historical alias for pre V6 applications */\r
+#define blr_date blr_timestamp\r
+\r
+#define blr_inner (unsigned char)0\r
+#define blr_left (unsigned char)1\r
+#define blr_right (unsigned char)2\r
+#define blr_full (unsigned char)3\r
+\r
+#define blr_gds_code (unsigned char)0\r
+#define blr_sql_code (unsigned char)1\r
+#define blr_exception (unsigned char)2\r
+#define blr_trigger_code (unsigned char)3\r
+#define blr_default_code (unsigned char)4\r
+#define blr_raise (unsigned char)5\r
+#define blr_exception_msg (unsigned char)6\r
+\r
+#define blr_version4 (unsigned char)4\r
+#define blr_version5 (unsigned char)5\r
+#define blr_eoc (unsigned char)76\r
+#define blr_end (unsigned char)255 /* note: defined as -1 in gds.h */\r
+\r
+#define blr_assignment (unsigned char)1\r
+#define blr_begin (unsigned char)2\r
+#define blr_dcl_variable (unsigned char)3 /* added from gds.h */\r
+#define blr_message (unsigned char)4\r
+#define blr_erase (unsigned char)5\r
+#define blr_fetch (unsigned char)6\r
+#define blr_for (unsigned char)7\r
+#define blr_if (unsigned char)8\r
+#define blr_loop (unsigned char)9\r
+#define blr_modify (unsigned char)10\r
+#define blr_handler (unsigned char)11\r
+#define blr_receive (unsigned char)12\r
+#define blr_select (unsigned char)13\r
+#define blr_send (unsigned char)14\r
+#define blr_store (unsigned char)15\r
+#define blr_label (unsigned char)17\r
+#define blr_leave (unsigned char)18\r
+#define blr_store2 (unsigned char)19\r
+#define blr_post (unsigned char)20\r
+#define blr_literal (unsigned char)21\r
+#define blr_dbkey (unsigned char)22\r
+#define blr_field (unsigned char)23\r
+#define blr_fid (unsigned char)24\r
+#define blr_parameter (unsigned char)25\r
+#define blr_variable (unsigned char)26\r
+#define blr_average (unsigned char)27\r
+#define blr_count (unsigned char)28\r
+#define blr_maximum (unsigned char)29\r
+#define blr_minimum (unsigned char)30\r
+#define blr_total (unsigned char)31\r
+/* count 2\r
+#define blr_count2 32\r
+*/\r
+#define blr_add (unsigned char)34\r
+#define blr_subtract (unsigned char)35\r
+#define blr_multiply (unsigned char)36\r
+#define blr_divide (unsigned char)37\r
+#define blr_negate (unsigned char)38\r
+#define blr_concatenate (unsigned char)39\r
+#define blr_substring (unsigned char)40\r
+#define blr_parameter2 (unsigned char)41\r
+#define blr_from (unsigned char)42\r
+#define blr_via (unsigned char)43\r
+#define blr_parameter2_old (unsigned char)44 /* Confusion */\r
+#define blr_user_name (unsigned char)44 /* added from gds.h */\r
+#define blr_null (unsigned char)45\r
+\r
+#define blr_eql (unsigned char)47\r
+#define blr_neq (unsigned char)48\r
+#define blr_gtr (unsigned char)49\r
+#define blr_geq (unsigned char)50\r
+#define blr_lss (unsigned char)51\r
+#define blr_leq (unsigned char)52\r
+#define blr_containing (unsigned char)53\r
+#define blr_matching (unsigned char)54\r
+#define blr_starting (unsigned char)55\r
+#define blr_between (unsigned char)56\r
+#define blr_or (unsigned char)57\r
+#define blr_and (unsigned char)58\r
+#define blr_not (unsigned char)59\r
+#define blr_any (unsigned char)60\r
+#define blr_missing (unsigned char)61\r
+#define blr_unique (unsigned char)62\r
+#define blr_like (unsigned char)63\r
+\r
+#define blr_stream (unsigned char)65 /* added from gds.h */\r
+#define blr_set_index (unsigned char)66 /* added from gds.h */\r
+\r
+#define blr_rse (unsigned char)67\r
+#define blr_first (unsigned char)68\r
+#define blr_project (unsigned char)69\r
+#define blr_sort (unsigned char)70\r
+#define blr_boolean (unsigned char)71\r
+#define blr_ascending (unsigned char)72\r
+#define blr_descending (unsigned char)73\r
+#define blr_relation (unsigned char)74\r
+#define blr_rid (unsigned char)75\r
+#define blr_union (unsigned char)76\r
+#define blr_map (unsigned char)77\r
+#define blr_group_by (unsigned char)78\r
+#define blr_aggregate (unsigned char)79\r
+#define blr_join_type (unsigned char)80\r
+\r
+#define blr_agg_count (unsigned char)83\r
+#define blr_agg_max (unsigned char)84\r
+#define blr_agg_min (unsigned char)85\r
+#define blr_agg_total (unsigned char)86\r
+#define blr_agg_average (unsigned char)87\r
+#define blr_parameter3 (unsigned char)88 /* same as Rdb definition */\r
+#define blr_run_max (unsigned char)89\r
+#define blr_run_min (unsigned char)90\r
+#define blr_run_total (unsigned char)91\r
+#define blr_run_average (unsigned char)92\r
+#define blr_agg_count2 (unsigned char)93\r
+#define blr_agg_count_distinct (unsigned char)94\r
+#define blr_agg_total_distinct (unsigned char)95\r
+#define blr_agg_average_distinct (unsigned char)96\r
+\r
+#define blr_function (unsigned char)100\r
+#define blr_gen_id (unsigned char)101\r
+#define blr_prot_mask (unsigned char)102\r
+#define blr_upcase (unsigned char)103\r
+#define blr_lock_state (unsigned char)104\r
+#define blr_value_if (unsigned char)105\r
+#define blr_matching2 (unsigned char)106\r
+#define blr_index (unsigned char)107\r
+#define blr_ansi_like (unsigned char)108\r
+#define blr_bookmark (unsigned char)109\r
+#define blr_crack (unsigned char)110\r
+#define blr_force_crack (unsigned char)111\r
+#define blr_seek (unsigned char)112\r
+#define blr_find (unsigned char)113\r
+ \r
+/* these indicate directions for blr_seek and blr_find */\r
+\r
+#define blr_continue (unsigned char)0\r
+#define blr_forward (unsigned char)1\r
+#define blr_backward (unsigned char)2\r
+#define blr_bof_forward (unsigned char)3\r
+#define blr_eof_backward (unsigned char)4\r
+\r
+#define blr_lock_relation (unsigned char)114\r
+#define blr_lock_record (unsigned char)115\r
+#define blr_set_bookmark (unsigned char)116\r
+#define blr_get_bookmark (unsigned char)117\r
+\r
+#define blr_run_count (unsigned char)118 /* changed from 88 to avoid conflict with blr_parameter3 */\r
+#define blr_rs_stream (unsigned char)119\r
+#define blr_exec_proc (unsigned char)120\r
+#define blr_begin_range (unsigned char)121\r
+#define blr_end_range (unsigned char)122\r
+#define blr_delete_range (unsigned char)123\r
+#define blr_procedure (unsigned char)124\r
+#define blr_pid (unsigned char)125\r
+#define blr_exec_pid (unsigned char)126\r
+#define blr_singular (unsigned char)127\r
+#define blr_abort (unsigned char)128\r
+#define blr_block (unsigned char)129\r
+#define blr_error_handler (unsigned char)130\r
+\r
+#define blr_cast (unsigned char)131\r
+#define blr_release_lock (unsigned char)132\r
+#define blr_release_locks (unsigned char)133\r
+#define blr_start_savepoint (unsigned char)134\r
+#define blr_end_savepoint (unsigned char)135\r
+#define blr_find_dbkey (unsigned char)136\r
+#define blr_range_relation (unsigned char)137\r
+#define blr_delete_ranges (unsigned char)138\r
+\r
+#define blr_plan (unsigned char)139 /* access plan items */\r
+#define blr_merge (unsigned char)140\r
+#define blr_join (unsigned char)141\r
+#define blr_sequential (unsigned char)142\r
+#define blr_navigational (unsigned char)143\r
+#define blr_indices (unsigned char)144\r
+#define blr_retrieve (unsigned char)145\r
+\r
+#define blr_relation2 (unsigned char)146\r
+#define blr_rid2 (unsigned char)147\r
+#define blr_reset_stream (unsigned char)148\r
+#define blr_release_bookmark (unsigned char)149\r
+\r
+#define blr_set_generator (unsigned char)150\r
+\r
+#define blr_ansi_any (unsigned char)151 /* required for NULL handling */\r
+#define blr_exists (unsigned char)152 /* required for NULL handling */\r
+#define blr_cardinality (unsigned char)153\r
+\r
+#define blr_record_version (unsigned char)154 /* get tid of record */\r
+#define blr_stall (unsigned char)155 /* fake server stall */\r
+\r
+#define blr_seek_no_warn (unsigned char)156 \r
+#define blr_find_dbkey_version (unsigned char)157 /* find dbkey with record version */\r
+#define blr_ansi_all (unsigned char)158 /* required for NULL handling */\r
+\r
+#define blr_extract (unsigned char)159\r
+\r
+/* sub parameters for blr_extract */\r
+\r
+#define blr_extract_year (unsigned char)0\r
+#define blr_extract_month (unsigned char)1\r
+#define blr_extract_day (unsigned char)2\r
+#define blr_extract_hour (unsigned char)3\r
+#define blr_extract_minute (unsigned char)4\r
+#define blr_extract_second (unsigned char)5\r
+#define blr_extract_weekday (unsigned char)6\r
+#define blr_extract_yearday (unsigned char)7\r
+\r
+#define blr_current_date (unsigned char)160\r
+#define blr_current_timestamp (unsigned char)161\r
+#define blr_current_time (unsigned char)162\r
+\r
+/* FB 1.0 specific BLR */\r
+\r
+#define blr_current_role (unsigned char)174\r
+#define blr_skip (unsigned char)175\r
+\r
+/* FB 1.5 specific BLR */\r
+\r
+#define blr_exec_sql (unsigned char)176\r
+#define blr_internal_info (unsigned char)177\r
+#define blr_nullsfirst (unsigned char)178\r
+#define blr_writelock (unsigned char)179\r
+#define blr_nullslast (unsigned char)180\r
+\r
+/* These codes reuse BLR code space */\r
+\r
+#define blr_post_arg (unsigned char)163\r
+#define blr_exec_into (unsigned char)164\r
+#define blr_user_savepoint (unsigned char)165\r
+\r
+/* These codes are actions for user-defined savepoints */\r
+\r
+#define blr_savepoint_set (unsigned char)0\r
+#define blr_savepoint_release (unsigned char)1\r
+#define blr_savepoint_undo (unsigned char)2\r
+#define blr_savepoint_release_single (unsigned char)3\r
+\r
+#endif /* _JRD_BLR_H_ */\r
+\r
+\r
+/**********************************/\r
+/* Database parameter block stuff */\r
+/**********************************/\r
+\r
+#define isc_dpb_version1 1\r
+#define isc_dpb_cdd_pathname 1\r
+#define isc_dpb_allocation 2\r
+#define isc_dpb_journal 3\r
+#define isc_dpb_page_size 4\r
+#define isc_dpb_num_buffers 5\r
+#define isc_dpb_buffer_length 6\r
+#define isc_dpb_debug 7\r
+#define isc_dpb_garbage_collect 8\r
+#define isc_dpb_verify 9\r
+#define isc_dpb_sweep 10\r
+#define isc_dpb_enable_journal 11\r
+#define isc_dpb_disable_journal 12\r
+#define isc_dpb_dbkey_scope 13\r
+#define isc_dpb_number_of_users 14\r
+#define isc_dpb_trace 15\r
+#define isc_dpb_no_garbage_collect 16\r
+#define isc_dpb_damaged 17\r
+#define isc_dpb_license 18\r
+#define isc_dpb_sys_user_name 19\r
+#define isc_dpb_encrypt_key 20\r
+#define isc_dpb_activate_shadow 21\r
+#define isc_dpb_sweep_interval 22\r
+#define isc_dpb_delete_shadow 23\r
+#define isc_dpb_force_write 24\r
+#define isc_dpb_begin_log 25\r
+#define isc_dpb_quit_log 26\r
+#define isc_dpb_no_reserve 27\r
+#define isc_dpb_user_name 28\r
+#define isc_dpb_password 29\r
+#define isc_dpb_password_enc 30\r
+#define isc_dpb_sys_user_name_enc 31\r
+#define isc_dpb_interp 32\r
+#define isc_dpb_online_dump 33\r
+#define isc_dpb_old_file_size 34\r
+#define isc_dpb_old_num_files 35\r
+#define isc_dpb_old_file 36\r
+#define isc_dpb_old_start_page 37\r
+#define isc_dpb_old_start_seqno 38\r
+#define isc_dpb_old_start_file 39\r
+#define isc_dpb_drop_walfile 40\r
+#define isc_dpb_old_dump_id 41\r
+#define isc_dpb_wal_backup_dir 42\r
+#define isc_dpb_wal_chkptlen 43\r
+#define isc_dpb_wal_numbufs 44\r
+#define isc_dpb_wal_bufsize 45\r
+#define isc_dpb_wal_grp_cmt_wait 46\r
+#define isc_dpb_lc_messages 47\r
+#define isc_dpb_lc_ctype 48\r
+#define isc_dpb_cache_manager 49\r
+#define isc_dpb_shutdown 50\r
+#define isc_dpb_online 51\r
+#define isc_dpb_shutdown_delay 52\r
+#define isc_dpb_reserved 53\r
+#define isc_dpb_overwrite 54\r
+#define isc_dpb_sec_attach 55\r
+#define isc_dpb_disable_wal 56\r
+#define isc_dpb_connect_timeout 57\r
+#define isc_dpb_dummy_packet_interval 58\r
+#define isc_dpb_gbak_attach 59\r
+#define isc_dpb_sql_role_name 60\r
+#define isc_dpb_set_page_buffers 61\r
+#define isc_dpb_working_directory 62\r
+#define isc_dpb_sql_dialect 63\r
+#define isc_dpb_set_db_readonly 64\r
+#define isc_dpb_set_db_sql_dialect 65\r
+#define isc_dpb_gfix_attach 66\r
+#define isc_dpb_gstat_attach 67\r
+#define isc_dpb_set_db_charset 68\r
+\r
+/*********************************/\r
+/* isc_dpb_verify specific flags */\r
+/*********************************/\r
+\r
+#define isc_dpb_pages 1\r
+#define isc_dpb_records 2\r
+#define isc_dpb_indices 4\r
+#define isc_dpb_transactions 8\r
+#define isc_dpb_no_update 16\r
+#define isc_dpb_repair 32\r
+#define isc_dpb_ignore 64\r
+\r
+/***********************************/\r
+/* isc_dpb_shutdown specific flags */\r
+/***********************************/\r
+\r
+#define isc_dpb_shut_cache 1\r
+#define isc_dpb_shut_attachment 2\r
+#define isc_dpb_shut_transaction 4\r
+#define isc_dpb_shut_force 8\r
+\r
+/**************************************/\r
+/* Bit assignments in RDB$SYSTEM_FLAG */\r
+/**************************************/\r
+\r
+#define RDB_system 1\r
+#define RDB_id_assigned 2\r
+\r
+\r
+/*************************************/\r
+/* Transaction parameter block stuff */\r
+/*************************************/\r
+\r
+#define isc_tpb_version1 1\r
+#define isc_tpb_version3 3\r
+#define isc_tpb_consistency 1\r
+#define isc_tpb_concurrency 2\r
+#define isc_tpb_shared 3\r
+#define isc_tpb_protected 4\r
+#define isc_tpb_exclusive 5\r
+#define isc_tpb_wait 6\r
+#define isc_tpb_nowait 7\r
+#define isc_tpb_read 8\r
+#define isc_tpb_write 9\r
+#define isc_tpb_lock_read 10\r
+#define isc_tpb_lock_write 11\r
+#define isc_tpb_verb_time 12\r
+#define isc_tpb_commit_time 13\r
+#define isc_tpb_ignore_limbo 14\r
+#define isc_tpb_read_committed 15\r
+#define isc_tpb_autocommit 16\r
+#define isc_tpb_rec_version 17\r
+#define isc_tpb_no_rec_version 18\r
+#define isc_tpb_restart_requests 19\r
+#define isc_tpb_no_auto_undo 20\r
+\r
+\r
+/************************/\r
+/* Blob Parameter Block */\r
+/************************/\r
+\r
+#define isc_bpb_version1 1\r
+#define isc_bpb_source_type 1\r
+#define isc_bpb_target_type 2\r
+#define isc_bpb_type 3\r
+#define isc_bpb_source_interp 4\r
+#define isc_bpb_target_interp 5\r
+#define isc_bpb_filter_parameter 6\r
+\r
+#define isc_bpb_type_segmented 0\r
+#define isc_bpb_type_stream 1\r
+\r
+\r
+/*********************************/\r
+/* Service parameter block stuff */\r
+/*********************************/\r
+\r
+#define isc_spb_version1 1\r
+#define isc_spb_current_version 2\r
+#define isc_spb_version isc_spb_current_version\r
+#define isc_spb_user_name isc_dpb_user_name\r
+#define isc_spb_sys_user_name isc_dpb_sys_user_name\r
+#define isc_spb_sys_user_name_enc isc_dpb_sys_user_name_enc\r
+#define isc_spb_password isc_dpb_password\r
+#define isc_spb_password_enc isc_dpb_password_enc\r
+#define isc_spb_command_line 105\r
+#define isc_spb_dbname 106\r
+#define isc_spb_verbose 107\r
+#define isc_spb_options 108\r
+\r
+#define isc_spb_connect_timeout isc_dpb_connect_timeout\r
+#define isc_spb_dummy_packet_interval isc_dpb_dummy_packet_interval\r
+#define isc_spb_sql_role_name isc_dpb_sql_role_name\r
+\r
+\r
+/*********************************/\r
+/* Information call declarations */\r
+/*********************************/\r
+\r
+/****************************/\r
+/* Common, structural codes */\r
+/****************************/\r
+\r
+#define isc_info_end 1\r
+#define isc_info_truncated 2\r
+#define isc_info_error 3\r
+#define isc_info_data_not_ready 4\r
+#define isc_info_flag_end 127\r
+\r
+/******************************/\r
+/* Database information items */\r
+/******************************/\r
+\r
+enum db_info_types\r
+ {\r
+ isc_info_db_id = 4,\r
+ isc_info_reads = 5,\r
+ isc_info_writes = 6,\r
+ isc_info_fetches = 7,\r
+ isc_info_marks = 8,\r
+\r
+ isc_info_implementation = 11,\r
+ isc_info_isc_version = 12,\r
+ isc_info_base_level = 13,\r
+ isc_info_page_size = 14,\r
+ isc_info_num_buffers = 15,\r
+ isc_info_limbo = 16,\r
+ isc_info_current_memory = 17,\r
+ isc_info_max_memory = 18,\r
+ isc_info_window_turns = 19,\r
+ isc_info_license = 20, \r
+\r
+ isc_info_allocation = 21,\r
+ isc_info_attachment_id = 22,\r
+ isc_info_read_seq_count = 23,\r
+ isc_info_read_idx_count = 24,\r
+ isc_info_insert_count = 25,\r
+ isc_info_update_count = 26,\r
+ isc_info_delete_count = 27,\r
+ isc_info_backout_count = 28,\r
+ isc_info_purge_count = 29,\r
+ isc_info_expunge_count = 30, \r
+\r
+ isc_info_sweep_interval = 31,\r
+ isc_info_ods_version = 32,\r
+ isc_info_ods_minor_version = 33,\r
+ isc_info_no_reserve = 34,\r
+ isc_info_logfile = 35,\r
+ isc_info_cur_logfile_name = 36,\r
+ isc_info_cur_log_part_offset = 37,\r
+ isc_info_num_wal_buffers = 38,\r
+ isc_info_wal_buffer_size = 39,\r
+ isc_info_wal_ckpt_length = 40, \r
+\r
+ isc_info_wal_cur_ckpt_interval = 41, \r
+ isc_info_wal_prv_ckpt_fname = 42,\r
+ isc_info_wal_prv_ckpt_poffset = 43,\r
+ isc_info_wal_recv_ckpt_fname = 44,\r
+ isc_info_wal_recv_ckpt_poffset = 45,\r
+ isc_info_wal_grpc_wait_usecs = 47,\r
+ isc_info_wal_num_io = 48,\r
+ isc_info_wal_avg_io_size = 49,\r
+ isc_info_wal_num_commits = 50, \r
+\r
+ isc_info_wal_avg_grpc_size = 51,\r
+ isc_info_forced_writes = 52,\r
+ isc_info_user_names = 53,\r
+ isc_info_page_errors = 54,\r
+ isc_info_record_errors = 55,\r
+ isc_info_bpage_errors = 56,\r
+ isc_info_dpage_errors = 57,\r
+ isc_info_ipage_errors = 58,\r
+ isc_info_ppage_errors = 59,\r
+ isc_info_tpage_errors = 60,\r
+\r
+ isc_info_set_page_buffers = 61,\r
+ isc_info_db_sql_dialect = 62, \r
+ isc_info_db_read_only = 63,\r
+ isc_info_db_size_in_pages = 64,\r
+\r
+ /* Values 65 -100 unused to avoid conflict with InterBase */\r
+ \r
+ frb_info_att_charset = 101,\r
+ isc_info_db_class = 102,\r
+ isc_info_firebird_version = 103,\r
+ isc_info_oldest_transaction = 104,\r
+ isc_info_oldest_active = 105,\r
+ isc_info_oldest_snapshot = 106,\r
+ isc_info_next_transaction = 107,\r
+ isc_info_db_provider = 108,\r
+ isc_info_active_transactions = 109,\r
+\r
+ isc_info_db_last_value /* Leave this LAST! */\r
+ };\r
+\r
+#define isc_info_version isc_info_isc_version\r
+\r
+\r
+/**************************************/\r
+/* Database information return values */\r
+/**************************************/\r
+\r
+enum info_db_implementations\r
+ {\r
+ isc_info_db_impl_rdb_vms = 1,\r
+ isc_info_db_impl_rdb_eln = 2,\r
+ isc_info_db_impl_rdb_eln_dev = 3,\r
+ isc_info_db_impl_rdb_vms_y = 4,\r
+ isc_info_db_impl_rdb_eln_y = 5,\r
+ isc_info_db_impl_jri = 6,\r
+ isc_info_db_impl_jsv = 7,\r
+\r
+ isc_info_db_impl_isc_apl_68K = 25,\r
+ isc_info_db_impl_isc_vax_ultr = 26,\r
+ isc_info_db_impl_isc_vms = 27,\r
+ isc_info_db_impl_isc_sun_68k = 28,\r
+ isc_info_db_impl_isc_os2 = 29,\r
+ isc_info_db_impl_isc_sun4 = 30, /* 30 */\r
+ \r
+ isc_info_db_impl_isc_hp_ux = 31,\r
+ isc_info_db_impl_isc_sun_386i = 32,\r
+ isc_info_db_impl_isc_vms_orcl = 33,\r
+ isc_info_db_impl_isc_mac_aux = 34,\r
+ isc_info_db_impl_isc_rt_aix = 35,\r
+ isc_info_db_impl_isc_mips_ult = 36,\r
+ isc_info_db_impl_isc_xenix = 37,\r
+ isc_info_db_impl_isc_dg = 38,\r
+ isc_info_db_impl_isc_hp_mpexl = 39,\r
+ isc_info_db_impl_isc_hp_ux68K = 40, /* 40 */\r
+\r
+ isc_info_db_impl_isc_sgi = 41,\r
+ isc_info_db_impl_isc_sco_unix = 42,\r
+ isc_info_db_impl_isc_cray = 43,\r
+ isc_info_db_impl_isc_imp = 44,\r
+ isc_info_db_impl_isc_delta = 45,\r
+ isc_info_db_impl_isc_next = 46,\r
+ isc_info_db_impl_isc_dos = 47,\r
+ isc_info_db_impl_m88K = 48,\r
+ isc_info_db_impl_unixware = 49,\r
+ isc_info_db_impl_isc_winnt_x86 = 50,\r
+\r
+ isc_info_db_impl_isc_epson = 51,\r
+ isc_info_db_impl_alpha_osf = 52,\r
+ isc_info_db_impl_alpha_vms = 53,\r
+ isc_info_db_impl_netware_386 = 54, \r
+ isc_info_db_impl_win_only = 55,\r
+ isc_info_db_impl_ncr_3000 = 56,\r
+ isc_info_db_impl_winnt_ppc = 57,\r
+ isc_info_db_impl_dg_x86 = 58,\r
+ isc_info_db_impl_sco_ev = 59,\r
+ isc_info_db_impl_i386 = 60,\r
+\r
+ isc_info_db_impl_freebsd = 61,\r
+ isc_info_db_impl_netbsd = 62,\r
+ isc_info_db_impl_darwin = 63,\r
+ isc_info_db_impl_sinixz = 64,\r
+\r
+ isc_info_db_impl_linux_sparc = 65,\r
+ isc_info_db_impl_linux_amd64 = 66,\r
+\r
+ isc_info_db_impl_last_value /* Leave this LAST! */\r
+ };\r
+\r
+#define isc_info_db_impl_isc_a isc_info_db_impl_isc_apl_68K\r
+#define isc_info_db_impl_isc_u isc_info_db_impl_isc_vax_ultr\r
+#define isc_info_db_impl_isc_v isc_info_db_impl_isc_vms\r
+#define isc_info_db_impl_isc_s isc_info_db_impl_isc_sun_68k\r
+\r
+\r
+enum info_db_class\r
+ {\r
+ isc_info_db_class_access = 1,\r
+ isc_info_db_class_y_valve = 2,\r
+ isc_info_db_class_rem_int = 3,\r
+ isc_info_db_class_rem_srvr = 4,\r
+ isc_info_db_class_pipe_int = 7,\r
+ isc_info_db_class_pipe_srvr = 8,\r
+ isc_info_db_class_sam_int = 9,\r
+ isc_info_db_class_sam_srvr = 10,\r
+ isc_info_db_class_gateway = 11,\r
+ isc_info_db_class_cache = 12,\r
+ isc_info_db_class_classic_access = 13,\r
+ isc_info_db_class_server_access = 14,\r
+\r
+ isc_info_db_class_last_value /* Leave this LAST! */\r
+ };\r
+\r
+enum info_db_provider\r
+ {\r
+ isc_info_db_code_rdb_eln = 1,\r
+ isc_info_db_code_rdb_vms = 2,\r
+ isc_info_db_code_interbase = 3,\r
+ isc_info_db_code_firebird = 4,\r
+\r
+ isc_info_db_code_last_value /* Leave this LAST! */\r
+ };\r
+\r
+\r
+/*****************************/\r
+/* Request information items */\r
+/*****************************/\r
+\r
+#define isc_info_number_messages 4\r
+#define isc_info_max_message 5\r
+#define isc_info_max_send 6\r
+#define isc_info_max_receive 7\r
+#define isc_info_state 8\r
+#define isc_info_message_number 9\r
+#define isc_info_message_size 10\r
+#define isc_info_request_cost 11\r
+#define isc_info_access_path 12\r
+#define isc_info_req_select_count 13\r
+#define isc_info_req_insert_count 14\r
+#define isc_info_req_update_count 15\r
+#define isc_info_req_delete_count 16\r
+\r
+\r
+/*********************/\r
+/* Access path items */\r
+/*********************/\r
+\r
+#define isc_info_rsb_end 0\r
+#define isc_info_rsb_begin 1\r
+#define isc_info_rsb_type 2\r
+#define isc_info_rsb_relation 3\r
+#define isc_info_rsb_plan 4\r
+\r
+/*************/\r
+/* Rsb types */\r
+/*************/\r
+\r
+#define isc_info_rsb_unknown 1\r
+#define isc_info_rsb_indexed 2\r
+#define isc_info_rsb_navigate 3\r
+#define isc_info_rsb_sequential 4\r
+#define isc_info_rsb_cross 5\r
+#define isc_info_rsb_sort 6\r
+#define isc_info_rsb_first 7\r
+#define isc_info_rsb_boolean 8\r
+#define isc_info_rsb_union 9\r
+#define isc_info_rsb_aggregate 10\r
+#define isc_info_rsb_merge 11\r
+#define isc_info_rsb_ext_sequential 12\r
+#define isc_info_rsb_ext_indexed 13\r
+#define isc_info_rsb_ext_dbkey 14\r
+#define isc_info_rsb_left_cross 15\r
+#define isc_info_rsb_select 16\r
+#define isc_info_rsb_sql_join 17\r
+#define isc_info_rsb_simulate 18\r
+#define isc_info_rsb_sim_cross 19\r
+#define isc_info_rsb_once 20\r
+#define isc_info_rsb_procedure 21\r
+\r
+/**********************/\r
+/* Bitmap expressions */\r
+/**********************/\r
+\r
+#define isc_info_rsb_and 1\r
+#define isc_info_rsb_or 2\r
+#define isc_info_rsb_dbkey 3\r
+#define isc_info_rsb_index 4\r
+\r
+#define isc_info_req_active 2\r
+#define isc_info_req_inactive 3\r
+#define isc_info_req_send 4\r
+#define isc_info_req_receive 5\r
+#define isc_info_req_select 6\r
+#define isc_info_req_sql_stall 7\r
+\r
+/**************************/\r
+/* Blob information items */\r
+/**************************/\r
+\r
+#define isc_info_blob_num_segments 4\r
+#define isc_info_blob_max_segment 5\r
+#define isc_info_blob_total_length 6\r
+#define isc_info_blob_type 7\r
+\r
+/*********************************/\r
+/* Transaction information items */\r
+/*********************************/\r
+\r
+#define isc_info_tra_id 4\r
+\r
+/*****************************\r
+ * Service action items *\r
+ *****************************/\r
+\r
+#define isc_action_svc_backup 1 /* Starts database backup process on the server */\r
+#define isc_action_svc_restore 2 /* Starts database restore process on the server */\r
+#define isc_action_svc_repair 3 /* Starts database repair process on the server */\r
+#define isc_action_svc_add_user 4 /* Adds a new user to the security database */\r
+#define isc_action_svc_delete_user 5 /* Deletes a user record from the security database */\r
+#define isc_action_svc_modify_user 6 /* Modifies a user record in the security database */\r
+#define isc_action_svc_display_user 7 /* Displays a user record from the security database */\r
+#define isc_action_svc_properties 8 /* Sets database properties */\r
+#define isc_action_svc_add_license 9 /* Adds a license to the license file */\r
+#define isc_action_svc_remove_license 10 /* Removes a license from the license file */\r
+#define isc_action_svc_db_stats 11 /* Retrieves database statistics */\r
+#define isc_action_svc_get_ib_log 12 /* Retrieves the InterBase log file from the server */\r
+\r
+/*****************************\r
+ * Service information items *\r
+ *****************************/\r
+\r
+#define isc_info_svc_svr_db_info 50 /* Retrieves the number of attachments and databases */\r
+#define isc_info_svc_get_license 51 /* Retrieves all license keys and IDs from the license file */\r
+#define isc_info_svc_get_license_mask 52 /* Retrieves a bitmask representing licensed options on the server */\r
+#define isc_info_svc_get_config 53 /* Retrieves the parameters and values for IB_CONFIG */\r
+#define isc_info_svc_version 54 /* Retrieves the version of the services manager */\r
+#define isc_info_svc_server_version 55 /* Retrieves the version of the InterBase server */\r
+#define isc_info_svc_implementation 56 /* Retrieves the implementation of the InterBase server */\r
+#define isc_info_svc_capabilities 57 /* Retrieves a bitmask representing the server's capabilities */\r
+#define isc_info_svc_user_dbpath 58 /* Retrieves the path to the security database in use by the server */\r
+#define isc_info_svc_get_env 59 /* Retrieves the setting of $INTERBASE */\r
+#define isc_info_svc_get_env_lock 60 /* Retrieves the setting of $INTERBASE_LCK */\r
+#define isc_info_svc_get_env_msg 61 /* Retrieves the setting of $INTERBASE_MSG */\r
+#define isc_info_svc_line 62 /* Retrieves 1 line of service output per call */\r
+#define isc_info_svc_to_eof 63 /* Retrieves as much of the server output as will fit in the supplied buffer */\r
+#define isc_info_svc_timeout 64 /* Sets / signifies a timeout value for reading service information */\r
+#define isc_info_svc_get_licensed_users 65 /* Retrieves the number of users licensed for accessing the server */\r
+#define isc_info_svc_limbo_trans 66 /* Retrieve the limbo transactions */\r
+#define isc_info_svc_running 67 /* Checks to see if a service is running on an attachment */\r
+#define isc_info_svc_get_users 68 /* Returns the user information from isc_action_svc_display_users */\r
+\r
+/******************************************************\r
+ * Parameters for isc_action_{add|delete|modify)_user *\r
+ ******************************************************/\r
+\r
+#define isc_spb_sec_userid 5\r
+#define isc_spb_sec_groupid 6\r
+#define isc_spb_sec_username 7\r
+#define isc_spb_sec_password 8\r
+#define isc_spb_sec_groupname 9\r
+#define isc_spb_sec_firstname 10\r
+#define isc_spb_sec_middlename 11\r
+#define isc_spb_sec_lastname 12\r
+\r
+/*******************************************************\r
+ * Parameters for isc_action_svc_(add|remove)_license, *\r
+ * isc_info_svc_get_license *\r
+ *******************************************************/\r
+\r
+#define isc_spb_lic_key 5\r
+#define isc_spb_lic_id 6\r
+#define isc_spb_lic_desc 7\r
+\r
+\r
+/*****************************************\r
+ * Parameters for isc_action_svc_backup *\r
+ *****************************************/\r
+\r
+#define isc_spb_bkp_file 5\r
+#define isc_spb_bkp_factor 6\r
+#define isc_spb_bkp_length 7\r
+#define isc_spb_bkp_ignore_checksums 0x01\r
+#define isc_spb_bkp_ignore_limbo 0x02\r
+#define isc_spb_bkp_metadata_only 0x04\r
+#define isc_spb_bkp_no_garbage_collect 0x08\r
+#define isc_spb_bkp_old_descriptions 0x10\r
+#define isc_spb_bkp_non_transportable 0x20\r
+#define isc_spb_bkp_convert 0x40\r
+#define isc_spb_bkp_expand 0x80\r
+\r
+/********************************************\r
+ * Parameters for isc_action_svc_properties *\r
+ ********************************************/\r
+\r
+#define isc_spb_prp_page_buffers 5\r
+#define isc_spb_prp_sweep_interval 6\r
+#define isc_spb_prp_shutdown_db 7\r
+#define isc_spb_prp_deny_new_attachments 9\r
+#define isc_spb_prp_deny_new_transactions 10\r
+#define isc_spb_prp_reserve_space 11\r
+#define isc_spb_prp_write_mode 12\r
+#define isc_spb_prp_access_mode 13\r
+#define isc_spb_prp_set_sql_dialect 14\r
+#define isc_spb_prp_activate 0x0100\r
+#define isc_spb_prp_db_online 0x0200\r
+\r
+/********************************************\r
+ * Parameters for isc_spb_prp_reserve_space *\r
+ ********************************************/\r
+\r
+#define isc_spb_prp_res_use_full 35\r
+#define isc_spb_prp_res 36\r
+\r
+/******************************************\r
+ * Parameters for isc_spb_prp_write_mode *\r
+ ******************************************/\r
+\r
+#define isc_spb_prp_wm_async 37\r
+#define isc_spb_prp_wm_sync 38\r
+\r
+/******************************************\r
+ * Parameters for isc_spb_prp_access_mode *\r
+ ******************************************/\r
+\r
+#define isc_spb_prp_am_readonly 39\r
+#define isc_spb_prp_am_readwrite 40\r
+\r
+/*****************************************\r
+ * Parameters for isc_action_svc_repair *\r
+ *****************************************/\r
+\r
+#define isc_spb_rpr_commit_trans 15\r
+#define isc_spb_rpr_rollback_trans 34\r
+#define isc_spb_rpr_recover_two_phase 17\r
+#define isc_spb_tra_id 18\r
+#define isc_spb_single_tra_id 19\r
+#define isc_spb_multi_tra_id 20\r
+#define isc_spb_tra_state 21\r
+#define isc_spb_tra_state_limbo 22\r
+#define isc_spb_tra_state_commit 23\r
+#define isc_spb_tra_state_rollback 24\r
+#define isc_spb_tra_state_unknown 25\r
+#define isc_spb_tra_host_site 26\r
+#define isc_spb_tra_remote_site 27\r
+#define isc_spb_tra_db_path 28\r
+#define isc_spb_tra_advise 29\r
+#define isc_spb_tra_advise_commit 30\r
+#define isc_spb_tra_advise_rollback 31\r
+#define isc_spb_tra_advise_unknown 33\r
+\r
+#define isc_spb_rpr_validate_db 0x01\r
+#define isc_spb_rpr_sweep_db 0x02\r
+#define isc_spb_rpr_mend_db 0x04\r
+#define isc_spb_rpr_list_limbo_trans 0x08\r
+#define isc_spb_rpr_check_db 0x10\r
+#define isc_spb_rpr_ignore_checksum 0x20\r
+#define isc_spb_rpr_kill_shadows 0x40\r
+#define isc_spb_rpr_full 0x80\r
+\r
+/*****************************************\r
+ * Parameters for isc_action_svc_restore *\r
+ *****************************************/\r
+\r
+#define isc_spb_res_buffers 9\r
+#define isc_spb_res_page_size 10\r
+#define isc_spb_res_length 11\r
+#define isc_spb_res_access_mode 12\r
+#define isc_spb_res_deactivate_idx 0x0100\r
+#define isc_spb_res_no_shadow 0x0200\r
+#define isc_spb_res_no_validity 0x0400\r
+#define isc_spb_res_one_at_a_time 0x0800\r
+#define isc_spb_res_replace 0x1000\r
+#define isc_spb_res_create 0x2000\r
+#define isc_spb_res_use_all_space 0x4000\r
+\r
+/******************************************\r
+ * Parameters for isc_spb_res_access_mode *\r
+ ******************************************/\r
+\r
+#define isc_spb_res_am_readonly isc_spb_prp_am_readonly\r
+#define isc_spb_res_am_readwrite isc_spb_prp_am_readwrite\r
+\r
+/*******************************************\r
+ * Parameters for isc_info_svc_svr_db_info *\r
+ *******************************************/\r
+\r
+#define isc_spb_num_att 5\r
+#define isc_spb_num_db 6\r
+\r
+/*****************************************\r
+ * Parameters for isc_info_svc_db_stats *\r
+ *****************************************/\r
+\r
+#define isc_spb_sts_data_pages 0x01\r
+#define isc_spb_sts_db_log 0x02\r
+#define isc_spb_sts_hdr_pages 0x04\r
+#define isc_spb_sts_idx_pages 0x08\r
+#define isc_spb_sts_sys_relations 0x10\r
+#define isc_spb_sts_record_versions 0x20\r
+#define isc_spb_sts_table 0x40\r
+\r
+/*************************/\r
+/* SQL information items */\r
+/*************************/\r
+\r
+#define isc_info_sql_select 4\r
+#define isc_info_sql_bind 5\r
+#define isc_info_sql_num_variables 6\r
+#define isc_info_sql_describe_vars 7\r
+#define isc_info_sql_describe_end 8\r
+#define isc_info_sql_sqlda_seq 9\r
+#define isc_info_sql_message_seq 10\r
+#define isc_info_sql_type 11\r
+#define isc_info_sql_sub_type 12\r
+#define isc_info_sql_scale 13\r
+#define isc_info_sql_length 14\r
+#define isc_info_sql_null_ind 15\r
+#define isc_info_sql_field 16\r
+#define isc_info_sql_relation 17\r
+#define isc_info_sql_owner 18\r
+#define isc_info_sql_alias 19\r
+#define isc_info_sql_sqlda_start 20\r
+#define isc_info_sql_stmt_type 21\r
+#define isc_info_sql_get_plan 22\r
+#define isc_info_sql_records 23\r
+#define isc_info_sql_batch_fetch 24\r
+\r
+/*********************************/\r
+/* SQL information return values */\r
+/*********************************/\r
+\r
+#define isc_info_sql_stmt_select 1\r
+#define isc_info_sql_stmt_insert 2\r
+#define isc_info_sql_stmt_update 3\r
+#define isc_info_sql_stmt_delete 4\r
+#define isc_info_sql_stmt_ddl 5\r
+#define isc_info_sql_stmt_get_segment 6\r
+#define isc_info_sql_stmt_put_segment 7\r
+#define isc_info_sql_stmt_exec_procedure 8\r
+#define isc_info_sql_stmt_start_trans 9\r
+#define isc_info_sql_stmt_commit 10\r
+#define isc_info_sql_stmt_rollback 11\r
+#define isc_info_sql_stmt_select_for_upd 12\r
+#define isc_info_sql_stmt_set_generator 13\r
+#define isc_info_sql_stmt_savepoint 14\r
+\r
+\r
+/***********************************/\r
+/* Server configuration key values */\r
+/***********************************/\r
+\r
+/* Not available in Firebird 1.5 */\r
+\r
+\r
+/**********************************************/\r
+/* Dynamic Data Definition Language operators */\r
+/**********************************************/\r
+\r
+/******************/\r
+/* Version number */\r
+/******************/\r
+\r
+#define isc_dyn_version_1 1\r
+#define isc_dyn_eoc 255\r
+\r
+/******************************/\r
+/* Operations (may be nested) */\r
+/******************************/\r
+\r
+#define isc_dyn_begin 2\r
+#define isc_dyn_end 3\r
+#define isc_dyn_if 4\r
+#define isc_dyn_def_database 5\r
+#define isc_dyn_def_global_fld 6\r
+#define isc_dyn_def_local_fld 7\r
+#define isc_dyn_def_idx 8\r
+#define isc_dyn_def_rel 9\r
+#define isc_dyn_def_sql_fld 10\r
+#define isc_dyn_def_view 12\r
+#define isc_dyn_def_trigger 15\r
+#define isc_dyn_def_security_class 120\r
+#define isc_dyn_def_dimension 140\r
+#define isc_dyn_def_generator 24\r
+#define isc_dyn_def_function 25\r
+#define isc_dyn_def_filter 26\r
+#define isc_dyn_def_function_arg 27\r
+#define isc_dyn_def_shadow 34\r
+#define isc_dyn_def_trigger_msg 17\r
+#define isc_dyn_def_file 36\r
+#define isc_dyn_mod_database 39\r
+#define isc_dyn_mod_rel 11\r
+#define isc_dyn_mod_global_fld 13\r
+#define isc_dyn_mod_idx 102\r
+#define isc_dyn_mod_local_fld 14\r
+#define isc_dyn_mod_sql_fld 216\r
+#define isc_dyn_mod_view 16\r
+#define isc_dyn_mod_security_class 122\r
+#define isc_dyn_mod_trigger 113\r
+#define isc_dyn_mod_trigger_msg 28\r
+#define isc_dyn_delete_database 18\r
+#define isc_dyn_delete_rel 19\r
+#define isc_dyn_delete_global_fld 20\r
+#define isc_dyn_delete_local_fld 21\r
+#define isc_dyn_delete_idx 22\r
+#define isc_dyn_delete_security_class 123\r
+#define isc_dyn_delete_dimensions 143\r
+#define isc_dyn_delete_trigger 23\r
+#define isc_dyn_delete_trigger_msg 29\r
+#define isc_dyn_delete_filter 32\r
+#define isc_dyn_delete_function 33\r
+#define isc_dyn_delete_shadow 35\r
+#define isc_dyn_grant 30\r
+#define isc_dyn_revoke 31\r
+#define isc_dyn_def_primary_key 37\r
+#define isc_dyn_def_foreign_key 38\r
+#define isc_dyn_def_unique 40\r
+#define isc_dyn_def_procedure 164\r
+#define isc_dyn_delete_procedure 165\r
+#define isc_dyn_def_parameter 135\r
+#define isc_dyn_delete_parameter 136\r
+#define isc_dyn_mod_procedure 175\r
+#define isc_dyn_def_log_file 176\r
+#define isc_dyn_def_cache_file 180\r
+#define isc_dyn_def_exception 181\r
+#define isc_dyn_mod_exception 182\r
+#define isc_dyn_del_exception 183\r
+#define isc_dyn_drop_log 194\r
+#define isc_dyn_drop_cache 195\r
+#define isc_dyn_def_default_log 202\r
+\r
+/***********************/\r
+/* View specific stuff */\r
+/***********************/\r
+\r
+#define isc_dyn_view_blr 43\r
+#define isc_dyn_view_source 44\r
+#define isc_dyn_view_relation 45\r
+#define isc_dyn_view_context 46\r
+#define isc_dyn_view_context_name 47\r
+\r
+/**********************/\r
+/* Generic attributes */\r
+/**********************/\r
+\r
+#define isc_dyn_rel_name 50\r
+#define isc_dyn_fld_name 51\r
+#define isc_dyn_new_fld_name 215\r
+#define isc_dyn_idx_name 52\r
+#define isc_dyn_description 53\r
+#define isc_dyn_security_class 54\r
+#define isc_dyn_system_flag 55\r
+#define isc_dyn_update_flag 56\r
+#define isc_dyn_prc_name 166\r
+#define isc_dyn_prm_name 137\r
+#define isc_dyn_sql_object 196\r
+#define isc_dyn_fld_character_set_name 174\r
+\r
+/********************************/\r
+/* Relation specific attributes */\r
+/********************************/\r
+\r
+#define isc_dyn_rel_dbkey_length 61\r
+#define isc_dyn_rel_store_trig 62\r
+#define isc_dyn_rel_modify_trig 63\r
+#define isc_dyn_rel_erase_trig 64\r
+#define isc_dyn_rel_store_trig_source 65\r
+#define isc_dyn_rel_modify_trig_source 66\r
+#define isc_dyn_rel_erase_trig_source 67\r
+#define isc_dyn_rel_ext_file 68\r
+#define isc_dyn_rel_sql_protection 69\r
+#define isc_dyn_rel_constraint 162\r
+#define isc_dyn_delete_rel_constraint 163\r
+\r
+/************************************/\r
+/* Global field specific attributes */\r
+/************************************/\r
+\r
+#define isc_dyn_fld_type 70\r
+#define isc_dyn_fld_length 71\r
+#define isc_dyn_fld_scale 72\r
+#define isc_dyn_fld_sub_type 73\r
+#define isc_dyn_fld_segment_length 74\r
+#define isc_dyn_fld_query_header 75\r
+#define isc_dyn_fld_edit_string 76\r
+#define isc_dyn_fld_validation_blr 77\r
+#define isc_dyn_fld_validation_source 78\r
+#define isc_dyn_fld_computed_blr 79\r
+#define isc_dyn_fld_computed_source 80\r
+#define isc_dyn_fld_missing_value 81\r
+#define isc_dyn_fld_default_value 82\r
+#define isc_dyn_fld_query_name 83\r
+#define isc_dyn_fld_dimensions 84\r
+#define isc_dyn_fld_not_null 85\r
+#define isc_dyn_fld_precision 86\r
+#define isc_dyn_fld_char_length 172\r
+#define isc_dyn_fld_collation 173\r
+#define isc_dyn_fld_default_source 193\r
+#define isc_dyn_del_default 197\r
+#define isc_dyn_del_validation 198\r
+#define isc_dyn_single_validation 199\r
+#define isc_dyn_fld_character_set 203\r
+\r
+/***********************************/\r
+/* Local field specific attributes */\r
+/***********************************/\r
+\r
+#define isc_dyn_fld_source 90\r
+#define isc_dyn_fld_base_fld 91\r
+#define isc_dyn_fld_position 92\r
+#define isc_dyn_fld_update_flag 93\r
+\r
+/*****************************/\r
+/* Index specific attributes */\r
+/*****************************/\r
+\r
+#define isc_dyn_idx_unique 100\r
+#define isc_dyn_idx_inactive 101\r
+#define isc_dyn_idx_type 103\r
+#define isc_dyn_idx_foreign_key 104\r
+#define isc_dyn_idx_ref_column 105\r
+#define isc_dyn_idx_statistic 204\r
+\r
+/*******************************/\r
+/* Trigger specific attributes */\r
+/*******************************/\r
+\r
+#define isc_dyn_trg_type 110\r
+#define isc_dyn_trg_blr 111\r
+#define isc_dyn_trg_source 112\r
+#define isc_dyn_trg_name 114\r
+#define isc_dyn_trg_sequence 115\r
+#define isc_dyn_trg_inactive 116\r
+#define isc_dyn_trg_msg_number 117\r
+#define isc_dyn_trg_msg 118\r
+\r
+/**************************************/\r
+/* Security Class specific attributes */\r
+/**************************************/\r
+\r
+#define isc_dyn_scl_acl 121\r
+#define isc_dyn_grant_user 130\r
+#define isc_dyn_grant_user_explicit 219\r
+#define isc_dyn_grant_proc 186\r
+#define isc_dyn_grant_trig 187\r
+#define isc_dyn_grant_view 188\r
+#define isc_dyn_grant_options 132\r
+#define isc_dyn_grant_user_group 205\r
+#define isc_dyn_grant_role 218\r
+\r
+\r
+/**********************************/\r
+/* Dimension specific information */\r
+/**********************************/\r
+\r
+#define isc_dyn_dim_lower 141\r
+#define isc_dyn_dim_upper 142\r
+\r
+/****************************/\r
+/* File specific attributes */\r
+/****************************/\r
+\r
+#define isc_dyn_file_name 125\r
+#define isc_dyn_file_start 126\r
+#define isc_dyn_file_length 127\r
+#define isc_dyn_shadow_number 128\r
+#define isc_dyn_shadow_man_auto 129\r
+#define isc_dyn_shadow_conditional 130\r
+\r
+/********************************/\r
+/* Log file specific attributes */\r
+/********************************/\r
+\r
+#define isc_dyn_log_file_sequence 177\r
+#define isc_dyn_log_file_partitions 178\r
+#define isc_dyn_log_file_serial 179\r
+#define isc_dyn_log_file_overflow 200\r
+#define isc_dyn_log_file_raw 201\r
+\r
+/***************************/\r
+/* Log specific attributes */\r
+/***************************/\r
+\r
+#define isc_dyn_log_group_commit_wait 189\r
+#define isc_dyn_log_buffer_size 190\r
+#define isc_dyn_log_check_point_length 191\r
+#define isc_dyn_log_num_of_buffers 192\r
+\r
+/********************************/\r
+/* Function specific attributes */\r
+/********************************/\r
+\r
+#define isc_dyn_function_name 145\r
+#define isc_dyn_function_type 146\r
+#define isc_dyn_func_module_name 147\r
+#define isc_dyn_func_entry_point 148\r
+#define isc_dyn_func_return_argument 149\r
+#define isc_dyn_func_arg_position 150\r
+#define isc_dyn_func_mechanism 151\r
+#define isc_dyn_filter_in_subtype 152\r
+#define isc_dyn_filter_out_subtype 153\r
+\r
+\r
+#define isc_dyn_description2 154\r
+#define isc_dyn_fld_computed_source2 155\r
+#define isc_dyn_fld_edit_string2 156\r
+#define isc_dyn_fld_query_header2 157\r
+#define isc_dyn_fld_validation_source2 158\r
+#define isc_dyn_trg_msg2 159\r
+#define isc_dyn_trg_source2 160\r
+#define isc_dyn_view_source2 161\r
+#define isc_dyn_xcp_msg2 184\r
+\r
+/*********************************/\r
+/* Generator specific attributes */\r
+/*********************************/\r
+\r
+#define isc_dyn_generator_name 95\r
+#define isc_dyn_generator_id 96\r
+\r
+/*********************************/\r
+/* Procedure specific attributes */\r
+/*********************************/\r
+\r
+#define isc_dyn_prc_inputs 167\r
+#define isc_dyn_prc_outputs 168\r
+#define isc_dyn_prc_source 169\r
+#define isc_dyn_prc_blr 170\r
+#define isc_dyn_prc_source2 171\r
+\r
+/*********************************/\r
+/* Parameter specific attributes */\r
+/*********************************/\r
+\r
+#define isc_dyn_prm_number 138\r
+#define isc_dyn_prm_type 139\r
+\r
+/********************************/\r
+/* Relation specific attributes */\r
+/********************************/\r
+\r
+#define isc_dyn_xcp_msg 185\r
+\r
+/**********************************************/\r
+/* Cascading referential integrity values */\r
+/**********************************************/\r
+#define isc_dyn_foreign_key_update 205\r
+#define isc_dyn_foreign_key_delete 206\r
+#define isc_dyn_foreign_key_cascade 207\r
+#define isc_dyn_foreign_key_default 208\r
+#define isc_dyn_foreign_key_null 209\r
+#define isc_dyn_foreign_key_none 210\r
+\r
+/***********************/\r
+/* SQL role values */\r
+/***********************/\r
+#define isc_dyn_def_sql_role 211\r
+#define isc_dyn_sql_role_name 212\r
+#define isc_dyn_grant_admin_options 213\r
+#define isc_dyn_del_sql_role 214\r
+/* 215 & 216 are used some lines above. */\r
+\r
+/**********************************************/\r
+/* Generators again */\r
+/**********************************************/\r
+\r
+#ifndef __cplusplus /* c definitions */\r
+#define gds_dyn_delete_generator 217\r
+#else /* c++ definitions */\r
+const unsigned char gds_dyn_delete_generator = 217;\r
+#endif\r
+\r
+/****************************/\r
+/* Last $dyn value assigned */\r
+/****************************/\r
+\r
+#define isc_dyn_last_dyn_value 219\r
+\r
+/******************************************/\r
+/* Array slice description language (SDL) */\r
+/******************************************/\r
+\r
+#define isc_sdl_version1 1\r
+#define isc_sdl_eoc 255\r
+#define isc_sdl_relation 2\r
+#define isc_sdl_rid 3\r
+#define isc_sdl_field 4\r
+#define isc_sdl_fid 5\r
+#define isc_sdl_struct 6\r
+#define isc_sdl_variable 7\r
+#define isc_sdl_scalar 8\r
+#define isc_sdl_tiny_integer 9\r
+#define isc_sdl_short_integer 10\r
+#define isc_sdl_long_integer 11\r
+#define isc_sdl_literal 12\r
+#define isc_sdl_add 13\r
+#define isc_sdl_subtract 14\r
+#define isc_sdl_multiply 15\r
+#define isc_sdl_divide 16\r
+#define isc_sdl_negate 17\r
+#define isc_sdl_eql 18\r
+#define isc_sdl_neq 19\r
+#define isc_sdl_gtr 20\r
+#define isc_sdl_geq 21\r
+#define isc_sdl_lss 22\r
+#define isc_sdl_leq 23\r
+#define isc_sdl_and 24\r
+#define isc_sdl_or 25\r
+#define isc_sdl_not 26\r
+#define isc_sdl_while 27\r
+#define isc_sdl_assignment 28\r
+#define isc_sdl_label 29\r
+#define isc_sdl_leave 30\r
+#define isc_sdl_begin 31\r
+#define isc_sdl_end 32\r
+#define isc_sdl_do3 33\r
+#define isc_sdl_do2 34\r
+#define isc_sdl_do1 35\r
+#define isc_sdl_element 36\r
+\r
+/********************************************/\r
+/* International text interpretation values */\r
+/********************************************/\r
+\r
+#define isc_interp_eng_ascii 0\r
+#define isc_interp_jpn_sjis 5\r
+#define isc_interp_jpn_euc 6\r
+\r
+/*******************/\r
+/* SQL definitions */\r
+/*******************/\r
+\r
+#define SQL_TEXT 452\r
+#define SQL_VARYING 448\r
+#define SQL_SHORT 500\r
+#define SQL_LONG 496\r
+#define SQL_FLOAT 482\r
+#define SQL_DOUBLE 480\r
+#define SQL_D_FLOAT 530\r
+#define SQL_TIMESTAMP 510\r
+#define SQL_BLOB 520\r
+#define SQL_ARRAY 540\r
+#define SQL_QUAD 550\r
+#define SQL_TYPE_TIME 560\r
+#define SQL_TYPE_DATE 570\r
+#define SQL_INT64 580\r
+\r
+/* Historical alias for pre V6 applications */\r
+#define SQL_DATE SQL_TIMESTAMP\r
+\r
+/*****************/\r
+/* Blob Subtypes */\r
+/*****************/\r
+\r
+/* types less than zero are reserved for customer use */\r
+\r
+#define isc_blob_untyped 0\r
+\r
+/* internal subtypes */\r
+\r
+#define isc_blob_text 1\r
+#define isc_blob_blr 2\r
+#define isc_blob_acl 3\r
+#define isc_blob_ranges 4\r
+#define isc_blob_summary 5\r
+#define isc_blob_format 6\r
+#define isc_blob_tra 7\r
+#define isc_blob_extfile 8\r
+\r
+/* the range 20-30 is reserved for dBASE and Paradox types */\r
+\r
+#define isc_blob_formatted_memo 20\r
+#define isc_blob_paradox_ole 21\r
+#define isc_blob_graphic 22\r
+#define isc_blob_dbase_ole 23\r
+#define isc_blob_typed_binary 24\r
+\r
+/* Deprecated definitions maintained for compatibility only */\r
+\r
+#define isc_info_db_SQL_dialect 62\r
+#define isc_dpb_SQL_dialect 63\r
+#define isc_dpb_set_db_SQL_dialect 65\r
+\r
+\r
+#include "iberror.h"\r
+\r
+#endif /* JRD_IBASE_H */\r
+\r
--- /dev/null
+\r
+#ifndef _JRD_GEN_IBERROR_H\r
+#define _JRD_GEN_IBERROR_H\r
+/*\r
+ * The contents of this file are subject to the Interbase Public\r
+ * License Version 1.0 (the "License"); you may not use this file\r
+ * except in compliance with the License. You may obtain a copy\r
+ * of the License at http://www.Inprise.com/IPL.html\r
+ * \r
+ * Software distributed under the License is distributed on an\r
+ * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express\r
+ * or implied. See the License for the specific language governing\r
+ * rights and limitations under the License.\r
+ * \r
+ * The content of this file was generated by the Firebird project\r
+ * using the program jrd/codes.epp\r
+ */\r
+/*\r
+ * \r
+ * *** WARNING *** - This file is automatically generated by codes.e - do not edit!\r
+ * \r
+ */\r
+/*\r
+ * MODULE: iberror.h\r
+ * DESCRIPTION: ISC error codes\r
+ *\r
+ */\r
+\r
+\r
+\r
+/***********************/\r
+/* ISC Error Codes */\r
+/***********************/\r
+\r
+#define isc_facility 20\r
+#define isc_base 335544320L\r
+#define isc_factor 1\r
+\r
+#define isc_arg_end 0 /* end of argument list */\r
+#define isc_arg_gds 1 /* generic DSRI status value */\r
+#define isc_arg_string 2 /* string argument */\r
+#define isc_arg_cstring 3 /* count & string argument */\r
+#define isc_arg_number 4 /* numeric argument (long) */\r
+#define isc_arg_interpreted 5 /* interpreted status code (string) */\r
+#define isc_arg_vms 6 /* VAX/VMS status code (long) */\r
+#define isc_arg_unix 7 /* UNIX error code */\r
+#define isc_arg_domain 8 /* Apollo/Domain error code */\r
+#define isc_arg_dos 9 /* MSDOS/OS2 error code */\r
+#define isc_arg_mpexl 10 /* HP MPE/XL error code */\r
+#define isc_arg_mpexl_ipc 11 /* HP MPE/XL IPC error code */\r
+#define isc_arg_next_mach 15 /* NeXT/Mach error code */\r
+#define isc_arg_netware 16 /* NetWare error code */\r
+#define isc_arg_win32 17 /* Win32 error code */\r
+#define isc_arg_warning 18 /* warning argument */\r
+\r
+#define isc_arith_except 335544321L\r
+#define isc_bad_dbkey 335544322L\r
+#define isc_bad_db_format 335544323L\r
+#define isc_bad_db_handle 335544324L\r
+#define isc_bad_dpb_content 335544325L\r
+#define isc_bad_dpb_form 335544326L\r
+#define isc_bad_req_handle 335544327L\r
+#define isc_bad_segstr_handle 335544328L\r
+#define isc_bad_segstr_id 335544329L\r
+#define isc_bad_tpb_content 335544330L\r
+#define isc_bad_tpb_form 335544331L\r
+#define isc_bad_trans_handle 335544332L\r
+#define isc_bug_check 335544333L\r
+#define isc_convert_error 335544334L\r
+#define isc_db_corrupt 335544335L\r
+#define isc_deadlock 335544336L\r
+#define isc_excess_trans 335544337L\r
+#define isc_from_no_match 335544338L\r
+#define isc_infinap 335544339L\r
+#define isc_infona 335544340L\r
+#define isc_infunk 335544341L\r
+#define isc_integ_fail 335544342L\r
+#define isc_invalid_blr 335544343L\r
+#define isc_io_error 335544344L\r
+#define isc_lock_conflict 335544345L\r
+#define isc_metadata_corrupt 335544346L\r
+#define isc_not_valid 335544347L\r
+#define isc_no_cur_rec 335544348L\r
+#define isc_no_dup 335544349L\r
+#define isc_no_finish 335544350L\r
+#define isc_no_meta_update 335544351L\r
+#define isc_no_priv 335544352L\r
+#define isc_no_recon 335544353L\r
+#define isc_no_record 335544354L\r
+#define isc_no_segstr_close 335544355L\r
+#define isc_obsolete_metadata 335544356L\r
+#define isc_open_trans 335544357L\r
+#define isc_port_len 335544358L\r
+#define isc_read_only_field 335544359L\r
+#define isc_read_only_rel 335544360L\r
+#define isc_read_only_trans 335544361L\r
+#define isc_read_only_view 335544362L\r
+#define isc_req_no_trans 335544363L\r
+#define isc_req_sync 335544364L\r
+#define isc_req_wrong_db 335544365L\r
+#define isc_segment 335544366L\r
+#define isc_segstr_eof 335544367L\r
+#define isc_segstr_no_op 335544368L\r
+#define isc_segstr_no_read 335544369L\r
+#define isc_segstr_no_trans 335544370L\r
+#define isc_segstr_no_write 335544371L\r
+#define isc_segstr_wrong_db 335544372L\r
+#define isc_sys_request 335544373L\r
+#define isc_stream_eof 335544374L\r
+#define isc_unavailable 335544375L\r
+#define isc_unres_rel 335544376L\r
+#define isc_uns_ext 335544377L\r
+#define isc_wish_list 335544378L\r
+#define isc_wrong_ods 335544379L\r
+#define isc_wronumarg 335544380L\r
+#define isc_imp_exc 335544381L\r
+#define isc_random 335544382L\r
+#define isc_fatal_conflict 335544383L\r
+#define isc_badblk 335544384L\r
+#define isc_invpoolcl 335544385L\r
+#define isc_nopoolids 335544386L\r
+#define isc_relbadblk 335544387L\r
+#define isc_blktoobig 335544388L\r
+#define isc_bufexh 335544389L\r
+#define isc_syntaxerr 335544390L\r
+#define isc_bufinuse 335544391L\r
+#define isc_bdbincon 335544392L\r
+#define isc_reqinuse 335544393L\r
+#define isc_badodsver 335544394L\r
+#define isc_relnotdef 335544395L\r
+#define isc_fldnotdef 335544396L\r
+#define isc_dirtypage 335544397L\r
+#define isc_waifortra 335544398L\r
+#define isc_doubleloc 335544399L\r
+#define isc_nodnotfnd 335544400L\r
+#define isc_dupnodfnd 335544401L\r
+#define isc_locnotmar 335544402L\r
+#define isc_badpagtyp 335544403L\r
+#define isc_corrupt 335544404L\r
+#define isc_badpage 335544405L\r
+#define isc_badindex 335544406L\r
+#define isc_dbbnotzer 335544407L\r
+#define isc_tranotzer 335544408L\r
+#define isc_trareqmis 335544409L\r
+#define isc_badhndcnt 335544410L\r
+#define isc_wrotpbver 335544411L\r
+#define isc_wroblrver 335544412L\r
+#define isc_wrodpbver 335544413L\r
+#define isc_blobnotsup 335544414L\r
+#define isc_badrelation 335544415L\r
+#define isc_nodetach 335544416L\r
+#define isc_notremote 335544417L\r
+#define isc_trainlim 335544418L\r
+#define isc_notinlim 335544419L\r
+#define isc_traoutsta 335544420L\r
+#define isc_connect_reject 335544421L\r
+#define isc_dbfile 335544422L\r
+#define isc_orphan 335544423L\r
+#define isc_no_lock_mgr 335544424L\r
+#define isc_ctxinuse 335544425L\r
+#define isc_ctxnotdef 335544426L\r
+#define isc_datnotsup 335544427L\r
+#define isc_badmsgnum 335544428L\r
+#define isc_badparnum 335544429L\r
+#define isc_virmemexh 335544430L\r
+#define isc_blocking_signal 335544431L\r
+#define isc_lockmanerr 335544432L\r
+#define isc_journerr 335544433L\r
+#define isc_keytoobig 335544434L\r
+#define isc_nullsegkey 335544435L\r
+#define isc_sqlerr 335544436L\r
+#define isc_wrodynver 335544437L\r
+#define isc_funnotdef 335544438L\r
+#define isc_funmismat 335544439L\r
+#define isc_bad_msg_vec 335544440L\r
+#define isc_bad_detach 335544441L\r
+#define isc_noargacc_read 335544442L\r
+#define isc_noargacc_write 335544443L\r
+#define isc_read_only 335544444L\r
+#define isc_ext_err 335544445L\r
+#define isc_non_updatable 335544446L\r
+#define isc_no_rollback 335544447L\r
+#define isc_bad_sec_info 335544448L\r
+#define isc_invalid_sec_info 335544449L\r
+#define isc_misc_interpreted 335544450L\r
+#define isc_update_conflict 335544451L\r
+#define isc_unlicensed 335544452L\r
+#define isc_obj_in_use 335544453L\r
+#define isc_nofilter 335544454L\r
+#define isc_shadow_accessed 335544455L\r
+#define isc_invalid_sdl 335544456L\r
+#define isc_out_of_bounds 335544457L\r
+#define isc_invalid_dimension 335544458L\r
+#define isc_rec_in_limbo 335544459L\r
+#define isc_shadow_missing 335544460L\r
+#define isc_cant_validate 335544461L\r
+#define isc_cant_start_journal 335544462L\r
+#define isc_gennotdef 335544463L\r
+#define isc_cant_start_logging 335544464L\r
+#define isc_bad_segstr_type 335544465L\r
+#define isc_foreign_key 335544466L\r
+#define isc_high_minor 335544467L\r
+#define isc_tra_state 335544468L\r
+#define isc_trans_invalid 335544469L\r
+#define isc_buf_invalid 335544470L\r
+#define isc_indexnotdefined 335544471L\r
+#define isc_login 335544472L\r
+#define isc_invalid_bookmark 335544473L\r
+#define isc_bad_lock_level 335544474L\r
+#define isc_relation_lock 335544475L\r
+#define isc_record_lock 335544476L\r
+#define isc_max_idx 335544477L\r
+#define isc_jrn_enable 335544478L\r
+#define isc_old_failure 335544479L\r
+#define isc_old_in_progress 335544480L\r
+#define isc_old_no_space 335544481L\r
+#define isc_no_wal_no_jrn 335544482L\r
+#define isc_num_old_files 335544483L\r
+#define isc_wal_file_open 335544484L\r
+#define isc_bad_stmt_handle 335544485L\r
+#define isc_wal_failure 335544486L\r
+#define isc_walw_err 335544487L\r
+#define isc_logh_small 335544488L\r
+#define isc_logh_inv_version 335544489L\r
+#define isc_logh_open_flag 335544490L\r
+#define isc_logh_open_flag2 335544491L\r
+#define isc_logh_diff_dbname 335544492L\r
+#define isc_logf_unexpected_eof 335544493L\r
+#define isc_logr_incomplete 335544494L\r
+#define isc_logr_header_small 335544495L\r
+#define isc_logb_small 335544496L\r
+#define isc_wal_illegal_attach 335544497L\r
+#define isc_wal_invalid_wpb 335544498L\r
+#define isc_wal_err_rollover 335544499L\r
+#define isc_no_wal 335544500L\r
+#define isc_drop_wal 335544501L\r
+#define isc_stream_not_defined 335544502L\r
+#define isc_wal_subsys_error 335544503L\r
+#define isc_wal_subsys_corrupt 335544504L\r
+#define isc_no_archive 335544505L\r
+#define isc_shutinprog 335544506L\r
+#define isc_range_in_use 335544507L\r
+#define isc_range_not_found 335544508L\r
+#define isc_charset_not_found 335544509L\r
+#define isc_lock_timeout 335544510L\r
+#define isc_prcnotdef 335544511L\r
+#define isc_prcmismat 335544512L\r
+#define isc_wal_bugcheck 335544513L\r
+#define isc_wal_cant_expand 335544514L\r
+#define isc_codnotdef 335544515L\r
+#define isc_xcpnotdef 335544516L\r
+#define isc_except 335544517L\r
+#define isc_cache_restart 335544518L\r
+#define isc_bad_lock_handle 335544519L\r
+#define isc_jrn_present 335544520L\r
+#define isc_wal_err_rollover2 335544521L\r
+#define isc_wal_err_logwrite 335544522L\r
+#define isc_wal_err_jrn_comm 335544523L\r
+#define isc_wal_err_expansion 335544524L\r
+#define isc_wal_err_setup 335544525L\r
+#define isc_wal_err_ww_sync 335544526L\r
+#define isc_wal_err_ww_start 335544527L\r
+#define isc_shutdown 335544528L\r
+#define isc_existing_priv_mod 335544529L\r
+#define isc_primary_key_ref 335544530L\r
+#define isc_primary_key_notnull 335544531L\r
+#define isc_ref_cnstrnt_notfound 335544532L\r
+#define isc_foreign_key_notfound 335544533L\r
+#define isc_ref_cnstrnt_update 335544534L\r
+#define isc_check_cnstrnt_update 335544535L\r
+#define isc_check_cnstrnt_del 335544536L\r
+#define isc_integ_index_seg_del 335544537L\r
+#define isc_integ_index_seg_mod 335544538L\r
+#define isc_integ_index_del 335544539L\r
+#define isc_integ_index_mod 335544540L\r
+#define isc_check_trig_del 335544541L\r
+#define isc_check_trig_update 335544542L\r
+#define isc_cnstrnt_fld_del 335544543L\r
+#define isc_cnstrnt_fld_rename 335544544L\r
+#define isc_rel_cnstrnt_update 335544545L\r
+#define isc_constaint_on_view 335544546L\r
+#define isc_invld_cnstrnt_type 335544547L\r
+#define isc_primary_key_exists 335544548L\r
+#define isc_systrig_update 335544549L\r
+#define isc_not_rel_owner 335544550L\r
+#define isc_grant_obj_notfound 335544551L\r
+#define isc_grant_fld_notfound 335544552L\r
+#define isc_grant_nopriv 335544553L\r
+#define isc_nonsql_security_rel 335544554L\r
+#define isc_nonsql_security_fld 335544555L\r
+#define isc_wal_cache_err 335544556L\r
+#define isc_shutfail 335544557L\r
+#define isc_check_constraint 335544558L\r
+#define isc_bad_svc_handle 335544559L\r
+#define isc_shutwarn 335544560L\r
+#define isc_wrospbver 335544561L\r
+#define isc_bad_spb_form 335544562L\r
+#define isc_svcnotdef 335544563L\r
+#define isc_no_jrn 335544564L\r
+#define isc_transliteration_failed 335544565L\r
+#define isc_start_cm_for_wal 335544566L\r
+#define isc_wal_ovflow_log_required 335544567L\r
+#define isc_text_subtype 335544568L\r
+#define isc_dsql_error 335544569L\r
+#define isc_dsql_command_err 335544570L\r
+#define isc_dsql_constant_err 335544571L\r
+#define isc_dsql_cursor_err 335544572L\r
+#define isc_dsql_datatype_err 335544573L\r
+#define isc_dsql_decl_err 335544574L\r
+#define isc_dsql_cursor_update_err 335544575L\r
+#define isc_dsql_cursor_open_err 335544576L\r
+#define isc_dsql_cursor_close_err 335544577L\r
+#define isc_dsql_field_err 335544578L\r
+#define isc_dsql_internal_err 335544579L\r
+#define isc_dsql_relation_err 335544580L\r
+#define isc_dsql_procedure_err 335544581L\r
+#define isc_dsql_request_err 335544582L\r
+#define isc_dsql_sqlda_err 335544583L\r
+#define isc_dsql_var_count_err 335544584L\r
+#define isc_dsql_stmt_handle 335544585L\r
+#define isc_dsql_function_err 335544586L\r
+#define isc_dsql_blob_err 335544587L\r
+#define isc_collation_not_found 335544588L\r
+#define isc_collation_not_for_charset 335544589L\r
+#define isc_dsql_dup_option 335544590L\r
+#define isc_dsql_tran_err 335544591L\r
+#define isc_dsql_invalid_array 335544592L\r
+#define isc_dsql_max_arr_dim_exceeded 335544593L\r
+#define isc_dsql_arr_range_error 335544594L\r
+#define isc_dsql_trigger_err 335544595L\r
+#define isc_dsql_subselect_err 335544596L\r
+#define isc_dsql_crdb_prepare_err 335544597L\r
+#define isc_specify_field_err 335544598L\r
+#define isc_num_field_err 335544599L\r
+#define isc_col_name_err 335544600L\r
+#define isc_where_err 335544601L\r
+#define isc_table_view_err 335544602L\r
+#define isc_distinct_err 335544603L\r
+#define isc_key_field_count_err 335544604L\r
+#define isc_subquery_err 335544605L\r
+#define isc_expression_eval_err 335544606L\r
+#define isc_node_err 335544607L\r
+#define isc_command_end_err 335544608L\r
+#define isc_index_name 335544609L\r
+#define isc_exception_name 335544610L\r
+#define isc_field_name 335544611L\r
+#define isc_token_err 335544612L\r
+#define isc_union_err 335544613L\r
+#define isc_dsql_construct_err 335544614L\r
+#define isc_field_aggregate_err 335544615L\r
+#define isc_field_ref_err 335544616L\r
+#define isc_order_by_err 335544617L\r
+#define isc_return_mode_err 335544618L\r
+#define isc_extern_func_err 335544619L\r
+#define isc_alias_conflict_err 335544620L\r
+#define isc_procedure_conflict_error 335544621L\r
+#define isc_relation_conflict_err 335544622L\r
+#define isc_dsql_domain_err 335544623L\r
+#define isc_idx_seg_err 335544624L\r
+#define isc_node_name_err 335544625L\r
+#define isc_table_name 335544626L\r
+#define isc_proc_name 335544627L\r
+#define isc_idx_create_err 335544628L\r
+#define isc_wal_shadow_err 335544629L\r
+#define isc_dependency 335544630L\r
+#define isc_idx_key_err 335544631L\r
+#define isc_dsql_file_length_err 335544632L\r
+#define isc_dsql_shadow_number_err 335544633L\r
+#define isc_dsql_token_unk_err 335544634L\r
+#define isc_dsql_no_relation_alias 335544635L\r
+#define isc_indexname 335544636L\r
+#define isc_no_stream_plan 335544637L\r
+#define isc_stream_twice 335544638L\r
+#define isc_stream_not_found 335544639L\r
+#define isc_collation_requires_text 335544640L\r
+#define isc_dsql_domain_not_found 335544641L\r
+#define isc_index_unused 335544642L\r
+#define isc_dsql_self_join 335544643L\r
+#define isc_stream_bof 335544644L\r
+#define isc_stream_crack 335544645L\r
+#define isc_db_or_file_exists 335544646L\r
+#define isc_invalid_operator 335544647L\r
+#define isc_conn_lost 335544648L\r
+#define isc_bad_checksum 335544649L\r
+#define isc_page_type_err 335544650L\r
+#define isc_ext_readonly_err 335544651L\r
+#define isc_sing_select_err 335544652L\r
+#define isc_psw_attach 335544653L\r
+#define isc_psw_start_trans 335544654L\r
+#define isc_invalid_direction 335544655L\r
+#define isc_dsql_var_conflict 335544656L\r
+#define isc_dsql_no_blob_array 335544657L\r
+#define isc_dsql_base_table 335544658L\r
+#define isc_duplicate_base_table 335544659L\r
+#define isc_view_alias 335544660L\r
+#define isc_index_root_page_full 335544661L\r
+#define isc_dsql_blob_type_unknown 335544662L\r
+#define isc_req_max_clones_exceeded 335544663L\r
+#define isc_dsql_duplicate_spec 335544664L\r
+#define isc_unique_key_violation 335544665L\r
+#define isc_srvr_version_too_old 335544666L\r
+#define isc_drdb_completed_with_errs 335544667L\r
+#define isc_dsql_procedure_use_err 335544668L\r
+#define isc_dsql_count_mismatch 335544669L\r
+#define isc_blob_idx_err 335544670L\r
+#define isc_array_idx_err 335544671L\r
+#define isc_key_field_err 335544672L\r
+#define isc_no_delete 335544673L\r
+#define isc_del_last_field 335544674L\r
+#define isc_sort_err 335544675L\r
+#define isc_sort_mem_err 335544676L\r
+#define isc_version_err 335544677L\r
+#define isc_inval_key_posn 335544678L\r
+#define isc_no_segments_err 335544679L\r
+#define isc_crrp_data_err 335544680L\r
+#define isc_rec_size_err 335544681L\r
+#define isc_dsql_field_ref 335544682L\r
+#define isc_req_depth_exceeded 335544683L\r
+#define isc_no_field_access 335544684L\r
+#define isc_no_dbkey 335544685L\r
+#define isc_jrn_format_err 335544686L\r
+#define isc_jrn_file_full 335544687L\r
+#define isc_dsql_open_cursor_request 335544688L\r
+#define isc_ib_error 335544689L\r
+#define isc_cache_redef 335544690L\r
+#define isc_cache_too_small 335544691L\r
+#define isc_log_redef 335544692L\r
+#define isc_log_too_small 335544693L\r
+#define isc_partition_too_small 335544694L\r
+#define isc_partition_not_supp 335544695L\r
+#define isc_log_length_spec 335544696L\r
+#define isc_precision_err 335544697L\r
+#define isc_scale_nogt 335544698L\r
+#define isc_expec_short 335544699L\r
+#define isc_expec_long 335544700L\r
+#define isc_expec_ushort 335544701L\r
+#define isc_like_escape_invalid 335544702L\r
+#define isc_svcnoexe 335544703L\r
+#define isc_net_lookup_err 335544704L\r
+#define isc_service_unknown 335544705L\r
+#define isc_host_unknown 335544706L\r
+#define isc_grant_nopriv_on_base 335544707L\r
+#define isc_dyn_fld_ambiguous 335544708L\r
+#define isc_dsql_agg_ref_err 335544709L\r
+#define isc_complex_view 335544710L\r
+#define isc_unprepared_stmt 335544711L\r
+#define isc_expec_positive 335544712L\r
+#define isc_dsql_sqlda_value_err 335544713L\r
+#define isc_invalid_array_id 335544714L\r
+#define isc_extfile_uns_op 335544715L\r
+#define isc_svc_in_use 335544716L\r
+#define isc_err_stack_limit 335544717L\r
+#define isc_invalid_key 335544718L\r
+#define isc_net_init_error 335544719L\r
+#define isc_loadlib_failure 335544720L\r
+#define isc_network_error 335544721L\r
+#define isc_net_connect_err 335544722L\r
+#define isc_net_connect_listen_err 335544723L\r
+#define isc_net_event_connect_err 335544724L\r
+#define isc_net_event_listen_err 335544725L\r
+#define isc_net_read_err 335544726L\r
+#define isc_net_write_err 335544727L\r
+#define isc_integ_index_deactivate 335544728L\r
+#define isc_integ_deactivate_primary 335544729L\r
+#define isc_cse_not_supported 335544730L\r
+#define isc_tra_must_sweep 335544731L\r
+#define isc_unsupported_network_drive 335544732L\r
+#define isc_io_create_err 335544733L\r
+#define isc_io_open_err 335544734L\r
+#define isc_io_close_err 335544735L\r
+#define isc_io_read_err 335544736L\r
+#define isc_io_write_err 335544737L\r
+#define isc_io_delete_err 335544738L\r
+#define isc_io_access_err 335544739L\r
+#define isc_udf_exception 335544740L\r
+#define isc_lost_db_connection 335544741L\r
+#define isc_no_write_user_priv 335544742L\r
+#define isc_token_too_long 335544743L\r
+#define isc_max_att_exceeded 335544744L\r
+#define isc_login_same_as_role_name 335544745L\r
+#define isc_reftable_requires_pk 335544746L\r
+#define isc_usrname_too_long 335544747L\r
+#define isc_password_too_long 335544748L\r
+#define isc_usrname_required 335544749L\r
+#define isc_password_required 335544750L\r
+#define isc_bad_protocol 335544751L\r
+#define isc_dup_usrname_found 335544752L\r
+#define isc_usrname_not_found 335544753L\r
+#define isc_error_adding_sec_record 335544754L\r
+#define isc_error_modifying_sec_record 335544755L\r
+#define isc_error_deleting_sec_record 335544756L\r
+#define isc_error_updating_sec_db 335544757L\r
+#define isc_sort_rec_size_err 335544758L\r
+#define isc_bad_default_value 335544759L\r
+#define isc_invalid_clause 335544760L\r
+#define isc_too_many_handles 335544761L\r
+#define isc_optimizer_blk_exc 335544762L\r
+#define isc_invalid_string_constant 335544763L\r
+#define isc_transitional_date 335544764L\r
+#define isc_read_only_database 335544765L\r
+#define isc_must_be_dialect_2_and_up 335544766L\r
+#define isc_blob_filter_exception 335544767L\r
+#define isc_exception_access_violation 335544768L\r
+#define isc_exception_datatype_missalignment 335544769L\r
+#define isc_exception_array_bounds_exceeded 335544770L\r
+#define isc_exception_float_denormal_operand 335544771L\r
+#define isc_exception_float_divide_by_zero 335544772L\r
+#define isc_exception_float_inexact_result 335544773L\r
+#define isc_exception_float_invalid_operand 335544774L\r
+#define isc_exception_float_overflow 335544775L\r
+#define isc_exception_float_stack_check 335544776L\r
+#define isc_exception_float_underflow 335544777L\r
+#define isc_exception_integer_divide_by_zero 335544778L\r
+#define isc_exception_integer_overflow 335544779L\r
+#define isc_exception_unknown 335544780L\r
+#define isc_exception_stack_overflow 335544781L\r
+#define isc_exception_sigsegv 335544782L\r
+#define isc_exception_sigill 335544783L\r
+#define isc_exception_sigbus 335544784L\r
+#define isc_exception_sigfpe 335544785L\r
+#define isc_ext_file_delete 335544786L\r
+#define isc_ext_file_modify 335544787L\r
+#define isc_adm_task_denied 335544788L\r
+#define isc_extract_input_mismatch 335544789L\r
+#define isc_insufficient_svc_privileges 335544790L\r
+#define isc_file_in_use 335544791L\r
+#define isc_service_att_err 335544792L\r
+#define isc_ddl_not_allowed_by_db_sql_dial 335544793L\r
+#define isc_cancelled 335544794L\r
+#define isc_unexp_spb_form 335544795L\r
+#define isc_sql_dialect_datatype_unsupport 335544796L\r
+#define isc_svcnouser 335544797L\r
+#define isc_depend_on_uncommitted_rel 335544798L\r
+#define isc_svc_name_missing 335544799L\r
+#define isc_too_many_contexts 335544800L\r
+#define isc_datype_notsup 335544801L\r
+#define isc_dialect_reset_warning 335544802L\r
+#define isc_dialect_not_changed 335544803L\r
+#define isc_database_create_failed 335544804L\r
+#define isc_inv_dialect_specified 335544805L\r
+#define isc_valid_db_dialects 335544806L\r
+#define isc_sqlwarn 335544807L\r
+#define isc_dtype_renamed 335544808L\r
+#define isc_extern_func_dir_error 335544809L\r
+#define isc_date_range_exceeded 335544810L\r
+#define isc_inv_client_dialect_specified 335544811L\r
+#define isc_valid_client_dialects 335544812L\r
+#define isc_optimizer_between_err 335544813L\r
+#define isc_service_not_supported 335544814L\r
+#define isc_generator_name 335544815L\r
+#define isc_udf_name 335544816L\r
+#define isc_bad_limit_param 335544817L\r
+#define isc_bad_skip_param 335544818L\r
+#define isc_io_32bit_exceeded_err 335544819L\r
+#define isc_invalid_savepoint 335544820L\r
+#define isc_dsql_column_pos_err 335544821L\r
+#define isc_dsql_agg_where_err 335544822L\r
+#define isc_dsql_agg_group_err 335544823L\r
+#define isc_dsql_agg_column_err 335544824L\r
+#define isc_dsql_agg_having_err 335544825L\r
+#define isc_dsql_agg_nested_err 335544826L\r
+#define isc_exec_sql_invalid_arg 335544827L\r
+#define isc_exec_sql_invalid_req 335544828L\r
+#define isc_exec_sql_invalid_var 335544829L\r
+#define isc_exec_sql_max_call_exceeded 335544830L\r
+#define isc_conf_access_denied 335544831L\r
+#define isc_gfix_db_name 335740929L\r
+#define isc_gfix_invalid_sw 335740930L\r
+#define isc_gfix_incmp_sw 335740932L\r
+#define isc_gfix_replay_req 335740933L\r
+#define isc_gfix_pgbuf_req 335740934L\r
+#define isc_gfix_val_req 335740935L\r
+#define isc_gfix_pval_req 335740936L\r
+#define isc_gfix_trn_req 335740937L\r
+#define isc_gfix_full_req 335740940L\r
+#define isc_gfix_usrname_req 335740941L\r
+#define isc_gfix_pass_req 335740942L\r
+#define isc_gfix_subs_name 335740943L\r
+#define isc_gfix_wal_req 335740944L\r
+#define isc_gfix_sec_req 335740945L\r
+#define isc_gfix_nval_req 335740946L\r
+#define isc_gfix_type_shut 335740947L\r
+#define isc_gfix_retry 335740948L\r
+#define isc_gfix_retry_db 335740951L\r
+#define isc_gfix_exceed_max 335740991L\r
+#define isc_gfix_corrupt_pool 335740992L\r
+#define isc_gfix_mem_exhausted 335740993L\r
+#define isc_gfix_bad_pool 335740994L\r
+#define isc_gfix_trn_not_valid 335740995L\r
+#define isc_gfix_unexp_eoi 335741012L\r
+#define isc_gfix_recon_fail 335741018L\r
+#define isc_gfix_trn_unknown 335741036L\r
+#define isc_gfix_mode_req 335741038L\r
+#define isc_gfix_opt_SQL_dialect 335741039L\r
+#define isc_dsql_dbkey_from_non_table 336003074L\r
+#define isc_dsql_transitional_numeric 336003075L\r
+#define isc_dsql_dialect_warning_expr 336003076L\r
+#define isc_sql_db_dialect_dtype_unsupport 336003077L\r
+#define isc_isc_sql_dialect_conflict_num 336003079L\r
+#define isc_dsql_warning_number_ambiguous 336003080L\r
+#define isc_dsql_warning_number_ambiguous1 336003081L\r
+#define isc_dsql_warn_precision_ambiguous 336003082L\r
+#define isc_dsql_warn_precision_ambiguous1 336003083L\r
+#define isc_dsql_warn_precision_ambiguous2 336003084L\r
+#define isc_dsql_ambiguous_field_name 336003085L\r
+#define isc_dsql_udf_return_pos_err 336003086L\r
+#define isc_dsql_invalid_label 336003087L\r
+#define isc_dsql_datatypes_not_comparable 336003088L\r
+#define isc_dyn_role_does_not_exist 336068796L\r
+#define isc_dyn_no_grant_admin_opt 336068797L\r
+#define isc_dyn_user_not_role_member 336068798L\r
+#define isc_dyn_delete_role_failed 336068799L\r
+#define isc_dyn_grant_role_to_user 336068800L\r
+#define isc_dyn_inv_sql_role_name 336068801L\r
+#define isc_dyn_dup_sql_role 336068802L\r
+#define isc_dyn_kywd_spec_for_role 336068803L\r
+#define isc_dyn_roles_not_supported 336068804L\r
+#define isc_dyn_domain_name_exists 336068812L\r
+#define isc_dyn_field_name_exists 336068813L\r
+#define isc_dyn_dependency_exists 336068814L\r
+#define isc_dyn_dtype_invalid 336068815L\r
+#define isc_dyn_char_fld_too_small 336068816L\r
+#define isc_dyn_invalid_dtype_conversion 336068817L\r
+#define isc_dyn_dtype_conv_invalid 336068818L\r
+#define isc_dyn_zero_len_id 336068820L\r
+#define isc_gbak_unknown_switch 336330753L\r
+#define isc_gbak_page_size_missing 336330754L\r
+#define isc_gbak_page_size_toobig 336330755L\r
+#define isc_gbak_redir_ouput_missing 336330756L\r
+#define isc_gbak_switches_conflict 336330757L\r
+#define isc_gbak_unknown_device 336330758L\r
+#define isc_gbak_no_protection 336330759L\r
+#define isc_gbak_page_size_not_allowed 336330760L\r
+#define isc_gbak_multi_source_dest 336330761L\r
+#define isc_gbak_filename_missing 336330762L\r
+#define isc_gbak_dup_inout_names 336330763L\r
+#define isc_gbak_inv_page_size 336330764L\r
+#define isc_gbak_db_specified 336330765L\r
+#define isc_gbak_db_exists 336330766L\r
+#define isc_gbak_unk_device 336330767L\r
+#define isc_gbak_blob_info_failed 336330772L\r
+#define isc_gbak_unk_blob_item 336330773L\r
+#define isc_gbak_get_seg_failed 336330774L\r
+#define isc_gbak_close_blob_failed 336330775L\r
+#define isc_gbak_open_blob_failed 336330776L\r
+#define isc_gbak_put_blr_gen_id_failed 336330777L\r
+#define isc_gbak_unk_type 336330778L\r
+#define isc_gbak_comp_req_failed 336330779L\r
+#define isc_gbak_start_req_failed 336330780L\r
+#define isc_gbak_rec_failed 336330781L\r
+#define isc_gbak_rel_req_failed 336330782L\r
+#define isc_gbak_db_info_failed 336330783L\r
+#define isc_gbak_no_db_desc 336330784L\r
+#define isc_gbak_db_create_failed 336330785L\r
+#define isc_gbak_decomp_len_error 336330786L\r
+#define isc_gbak_tbl_missing 336330787L\r
+#define isc_gbak_blob_col_missing 336330788L\r
+#define isc_gbak_create_blob_failed 336330789L\r
+#define isc_gbak_put_seg_failed 336330790L\r
+#define isc_gbak_rec_len_exp 336330791L\r
+#define isc_gbak_inv_rec_len 336330792L\r
+#define isc_gbak_exp_data_type 336330793L\r
+#define isc_gbak_gen_id_failed 336330794L\r
+#define isc_gbak_unk_rec_type 336330795L\r
+#define isc_gbak_inv_bkup_ver 336330796L\r
+#define isc_gbak_missing_bkup_desc 336330797L\r
+#define isc_gbak_string_trunc 336330798L\r
+#define isc_gbak_cant_rest_record 336330799L\r
+#define isc_gbak_send_failed 336330800L\r
+#define isc_gbak_no_tbl_name 336330801L\r
+#define isc_gbak_unexp_eof 336330802L\r
+#define isc_gbak_db_format_too_old 336330803L\r
+#define isc_gbak_inv_array_dim 336330804L\r
+#define isc_gbak_xdr_len_expected 336330807L\r
+#define isc_gbak_open_bkup_error 336330817L\r
+#define isc_gbak_open_error 336330818L\r
+#define isc_gbak_missing_block_fac 336330934L\r
+#define isc_gbak_inv_block_fac 336330935L\r
+#define isc_gbak_block_fac_specified 336330936L\r
+#define isc_gbak_missing_username 336330940L\r
+#define isc_gbak_missing_password 336330941L\r
+#define isc_gbak_missing_skipped_bytes 336330952L\r
+#define isc_gbak_inv_skipped_bytes 336330953L\r
+#define isc_gbak_err_restore_charset 336330965L\r
+#define isc_gbak_err_restore_collation 336330967L\r
+#define isc_gbak_read_error 336330972L\r
+#define isc_gbak_write_error 336330973L\r
+#define isc_gbak_db_in_use 336330985L\r
+#define isc_gbak_sysmemex 336330990L\r
+#define isc_gbak_restore_role_failed 336331002L\r
+#define isc_gbak_role_op_missing 336331005L\r
+#define isc_gbak_page_buffers_missing 336331010L\r
+#define isc_gbak_page_buffers_wrong_param 336331011L\r
+#define isc_gbak_page_buffers_restore 336331012L\r
+#define isc_gbak_inv_size 336331014L\r
+#define isc_gbak_file_outof_sequence 336331015L\r
+#define isc_gbak_join_file_missing 336331016L\r
+#define isc_gbak_stdin_not_supptd 336331017L\r
+#define isc_gbak_stdout_not_supptd 336331018L\r
+#define isc_gbak_bkup_corrupt 336331019L\r
+#define isc_gbak_unk_db_file_spec 336331020L\r
+#define isc_gbak_hdr_write_failed 336331021L\r
+#define isc_gbak_disk_space_ex 336331022L\r
+#define isc_gbak_size_lt_min 336331023L\r
+#define isc_gbak_svc_name_missing 336331025L\r
+#define isc_gbak_not_ownr 336331026L\r
+#define isc_gbak_mode_req 336331031L\r
+#define isc_gbak_just_data 336331033L\r
+#define isc_gbak_data_only 336331034L\r
+#define isc_gsec_cant_open_db 336723983L\r
+#define isc_gsec_switches_error 336723984L\r
+#define isc_gsec_no_op_spec 336723985L\r
+#define isc_gsec_no_usr_name 336723986L\r
+#define isc_gsec_err_add 336723987L\r
+#define isc_gsec_err_modify 336723988L\r
+#define isc_gsec_err_find_mod 336723989L\r
+#define isc_gsec_err_rec_not_found 336723990L\r
+#define isc_gsec_err_delete 336723991L\r
+#define isc_gsec_err_find_del 336723992L\r
+#define isc_gsec_err_find_disp 336723996L\r
+#define isc_gsec_inv_param 336723997L\r
+#define isc_gsec_op_specified 336723998L\r
+#define isc_gsec_pw_specified 336723999L\r
+#define isc_gsec_uid_specified 336724000L\r
+#define isc_gsec_gid_specified 336724001L\r
+#define isc_gsec_proj_specified 336724002L\r
+#define isc_gsec_org_specified 336724003L\r
+#define isc_gsec_fname_specified 336724004L\r
+#define isc_gsec_mname_specified 336724005L\r
+#define isc_gsec_lname_specified 336724006L\r
+#define isc_gsec_inv_switch 336724008L\r
+#define isc_gsec_amb_switch 336724009L\r
+#define isc_gsec_no_op_specified 336724010L\r
+#define isc_gsec_params_not_allowed 336724011L\r
+#define isc_gsec_incompat_switch 336724012L\r
+#define isc_gsec_inv_username 336724044L\r
+#define isc_gsec_inv_pw_length 336724045L\r
+#define isc_gsec_db_specified 336724046L\r
+#define isc_gsec_db_admin_specified 336724047L\r
+#define isc_gsec_db_admin_pw_specified 336724048L\r
+#define isc_gsec_sql_role_specified 336724049L\r
+#define isc_license_no_file 336789504L\r
+#define isc_license_op_specified 336789523L\r
+#define isc_license_op_missing 336789524L\r
+#define isc_license_inv_switch 336789525L\r
+#define isc_license_inv_switch_combo 336789526L\r
+#define isc_license_inv_op_combo 336789527L\r
+#define isc_license_amb_switch 336789528L\r
+#define isc_license_inv_parameter 336789529L\r
+#define isc_license_param_specified 336789530L\r
+#define isc_license_param_req 336789531L\r
+#define isc_license_syntx_error 336789532L\r
+#define isc_license_dup_id 336789534L\r
+#define isc_license_inv_id_key 336789535L\r
+#define isc_license_err_remove 336789536L\r
+#define isc_license_err_update 336789537L\r
+#define isc_license_err_convert 336789538L\r
+#define isc_license_err_unk 336789539L\r
+#define isc_license_svc_err_add 336789540L\r
+#define isc_license_svc_err_remove 336789541L\r
+#define isc_license_eval_exists 336789563L\r
+#define isc_gstat_unknown_switch 336920577L\r
+#define isc_gstat_retry 336920578L\r
+#define isc_gstat_wrong_ods 336920579L\r
+#define isc_gstat_unexpected_eof 336920580L\r
+#define isc_gstat_open_err 336920605L\r
+#define isc_gstat_read_err 336920606L\r
+#define isc_gstat_sysmemex 336920607L\r
+#define isc_err_max 713\r
+\r
+#endif /* JRD_GEN_IBERROR_H */\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: ibpp.h,v 1.3 2007/10/28 11:17:44 nobunaga Exp $\r
+// Subject : IBPP public header file. This is _the_ only file you include in\r
+// your application files when developing with IBPP.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+// Contributor(s):\r
+//\r
+// Olivier Mascia, main coding\r
+// Matt Hortman, initial linux port\r
+// Mark Jordan, design contributions\r
+// Maxim Abrashkin, enhancement patches\r
+// Torsten Martinsen, enhancement patches\r
+// Michael Hieke, darwin (OS X) port, enhancement patches\r
+// Val Samko, enhancement patches and debugging\r
+// Mike Nordell, invaluable C++ advices\r
+// Claudio Valderrama, help with not-so-well documented IB/FB features\r
+// Many others, excellent suggestions, bug finding, and support\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// Tabulations should be set every four characters when editing this file.\r
+//\r
+// When compiling a project using IBPP, the following defines should be made\r
+// on the command-line (or in makefiles) according to the OS platform and\r
+// compiler used.\r
+//\r
+// Select the platform: IBPP_WINDOWS | IBPP_LINUX | IBPP_DARWIN\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifndef __IBPP_H__\r
+#define __IBPP_H__\r
+\r
+#if !defined(IBPP_WINDOWS) && !defined(IBPP_LINUX) && !defined(IBPP_DARWIN)\r
+#error Please define IBPP_WINDOWS/IBPP_LINUX/IBPP_DARWIN before compiling !\r
+#endif\r
+\r
+#if !defined(__BCPLUSPLUS__) && !defined(__GNUC__) && !defined(_MSC_VER) && !defined(__DMC__)
+#error Your compiler is not recognized.\r
+#endif\r
+\r
+#if defined(IBPP_LINUX) || defined(IBPP_DARWIN)\r
+#define IBPP_UNIX // IBPP_UNIX stands as a common denominator to *NIX flavours\r
+#endif\r
+\r
+// IBPP is written for 32 bits systems or higher.\r
+// The standard type 'int' is assumed to be at least 32 bits.\r
+// And the standard type 'short' is assumed to be exactly 16 bits.\r
+// Everywhere possible, where the exact size of an integer does not matter,\r
+// the standard type 'int' is used. And where an exact integer size is required\r
+// the standard exact precision types definitions of C 99 standard are used.\r
+\r
+#if defined(_MSC_VER) || defined(__DMC__) || defined(__BCPLUSPLUS__)\r
+// C99 §7.18.1.1 Exact-width integer types (only those used by IBPP)\r
+#if defined(_MSC_VER) && (_MSC_VER < 1300) // MSVC 6 should be < 1300\r
+ typedef short int16_t;\r
+ typedef int int32_t;\r
+ typedef unsigned int uint32_t;\r
+#else\r
+ typedef __int16 int16_t;\r
+ typedef __int32 int32_t;\r
+ typedef unsigned __int32 uint32_t;\r
+#endif\r
+ typedef __int64 int64_t;\r
+#else\r
+ #include <os_int.h> // C99 (§7.18) integer types definitions\r
+#endif\r
+\r
+#if !defined(_)\r
+#define _(s) s\r
+#endif\r
+\r
+#include <exception>\r
+#include <string>\r
+#include <vector>\r
+\r
+namespace IBPP\r
+{\r
+ // Typically you use this constant in a call IBPP::CheckVersion as in:\r
+ // if (! IBPP::CheckVersion(IBPP::Version)) { throw .... ; }\r
+ const uint32_t Version = (2<<24) + (5<<16) + (3<<8) + 0; // Version == 2.5.3.0\r
+\r
+ // Dates range checking\r
+ const int MinDate = -693594; // 1 JAN 0001\r
+ const int MaxDate = 2958464; // 31 DEC 9999\r
+ \r
+ // Transaction Access Modes\r
+ enum TAM {amWrite, amRead};\r
+\r
+ // Transaction Isolation Levels\r
+ enum TIL {ilConcurrency, ilReadDirty, ilReadCommitted, ilConsistency};\r
+\r
+ // Transaction Lock Resolution\r
+ enum TLR {lrWait, lrNoWait};\r
+\r
+ // Transaction Table Reservation\r
+ enum TTR {trSharedWrite, trSharedRead, trProtectedWrite, trProtectedRead};\r
+\r
+ // Prepared Statement Types\r
+ enum STT {stUnknown, stUnsupported,\r
+ stSelect, stInsert, stUpdate, stDelete, stDDL, stExecProcedure,\r
+ stSelectUpdate, stSetGenerator, stSavePoint};\r
+\r
+ // SQL Data Types\r
+ enum SDT {sdArray, sdBlob, sdDate, sdTime, sdTimestamp, sdString,\r
+ sdSmallint, sdInteger, sdLargeint, sdFloat, sdDouble};\r
+\r
+ // Array Data Types\r
+ enum ADT {adDate, adTime, adTimestamp, adString,\r
+ adBool, adInt16, adInt32, adInt64, adFloat, adDouble};\r
+\r
+ // Database::Shutdown Modes\r
+ enum DSM {dsForce, dsDenyTrans, dsDenyAttach};\r
+\r
+ // Service::StartBackup && Service::StartRestore Flags\r
+ enum BRF {\r
+ brVerbose = 0x1,\r
+ // Backup flags\r
+ brIgnoreChecksums = 0x100, brIgnoreLimbo = 0x200,\r
+ brMetadataOnly = 0x400, brNoGarbageCollect = 0x800,\r
+ brNonTransportable = 0x1000, brConvertExtTables = 0x2000,\r
+ // Restore flags\r
+ brReplace = 0x10000, brDeactivateIdx = 0x20000,\r
+ brNoShadow = 0x40000, brNoValidity = 0x80000,\r
+ brPerTableCommit = 0x100000, brUseAllSpace = 0x200000\r
+ };\r
+\r
+ // Service::Repair Flags\r
+ enum RPF\r
+ {\r
+ // Mandatory and mutually exclusives\r
+ rpMendRecords = 0x1, rpValidatePages = 0x2, rpValidateFull = 0x4,\r
+ // Options\r
+ rpReadOnly = 0x100, rpIgnoreChecksums = 0x200, rpKillShadows = 0x400\r
+ };\r
+\r
+ // TransactionFactory Flags\r
+ enum TFF {tfIgnoreLimbo = 0x1, tfAutoCommit = 0x2, tfNoAutoUndo = 0x4};\r
+\r
+ /* IBPP never return any error codes. It throws exceptions.\r
+ * On database engine reported errors, an IBPP::SQLException is thrown.\r
+ * In all other cases, IBPP throws IBPP::LogicException.\r
+ * Also note that the runtime and the language might also throw exceptions\r
+ * while executing some IBPP methods. A failing new operator will throw\r
+ * std::bad_alloc, IBPP does nothing to alter the standard behaviour.\r
+ *\r
+ * std::exception\r
+ * |\r
+ * IBPP::Exception\r
+ * / \\r
+ * IBPP::LogicException IBPP::SQLException\r
+ * |\r
+ * IBPP::WrongType\r
+ */\r
+\r
+ class Exception : public std::exception\r
+ {\r
+ public:\r
+ virtual const char* Origin() const throw() = 0;\r
+ virtual const char* ErrorMessage() const throw() = 0; // Deprecated, use what()\r
+ virtual const char* what() const throw() = 0;\r
+ virtual ~Exception() throw();\r
+ };\r
+\r
+ class LogicException : public Exception\r
+ {\r
+ public:\r
+ virtual ~LogicException() throw();\r
+ };\r
+\r
+ class SQLException : public Exception\r
+ {\r
+ public:\r
+ virtual int SqlCode() const throw() = 0;\r
+ virtual int EngineCode() const throw() = 0;\r
+ \r
+ virtual ~SQLException() throw();\r
+ };\r
+\r
+ class WrongType : public LogicException\r
+ {\r
+ public:\r
+ virtual ~WrongType() throw();\r
+ };\r
+ \r
+ /* Classes Date, Time, Timestamp and DBKey are 'helper' classes. They help\r
+ * in retrieving or setting some special SQL types. Dates, times and dbkeys\r
+ * are often read and written as strings in SQL scripts. When programming\r
+ * with IBPP, we handle those data with these specific classes, which\r
+ * enhance their usefullness and free us of format problems (M/D/Y, D/M/Y,\r
+ * Y-M-D ?, and so on...). */\r
+\r
+ /* Class Date represent purely a Date (no time part specified). It is\r
+ * usefull in interactions with the SQL DATE type of Interbase. You can add\r
+ * or substract a number from a Date, that will modify it to represent the\r
+ * correct date, X days later or sooner. All the Y2K details taken into\r
+ * account.\r
+ * The full range goes from integer values IBPP::MinDate to IBPP::MaxDate\r
+ * which means from 01 Jan 0001 to 31 Dec 9999. ( Which is inherently\r
+ * incorrect as this assumes Gregorian calendar. ) */\r
+ \r
+ class Timestamp; // Cross-reference between Timestamp, Date and Time\r
+ \r
+ class Date\r
+ {\r
+ protected:\r
+ int mDate; // The date : 1 == 1 Jan 1900\r
+\r
+ public:\r
+ void Clear() { mDate = MinDate - 1; };\r
+ void Today();\r
+ void SetDate(int year, int month, int day);\r
+ void SetDate(int dt);\r
+ void GetDate(int& year, int& month, int& day) const;\r
+ int GetDate() const { return mDate; }\r
+ int Year() const;\r
+ int Month() const;\r
+ int Day() const;\r
+ void Add(int days);\r
+ void StartOfMonth();\r
+ void EndOfMonth();\r
+ \r
+ Date() { Clear(); };\r
+ Date(int dt) { SetDate(dt); }\r
+ Date(int year, int month, int day);\r
+ Date(const Date&); // Copy Constructor\r
+ Date& operator=(const Timestamp&); // Timestamp Assignment operator\r
+ Date& operator=(const Date&); // Date Assignment operator\r
+\r
+ bool operator==(const Date& rv) const { return mDate == rv.GetDate(); }\r
+ bool operator!=(const Date& rv) const { return mDate != rv.GetDate(); }\r
+ bool operator<(const Date& rv) const { return mDate < rv.GetDate(); }\r
+ bool operator>(const Date& rv) const { return mDate > rv.GetDate(); }\r
+\r
+ virtual ~Date() { };\r
+ };\r
+\r
+ /* Class Time represent purely a Time. It is usefull in interactions\r
+ * with the SQL TIME type of Interbase. */\r
+\r
+ class Time\r
+ {\r
+ protected:\r
+ int mTime; // The time, in ten-thousandths of seconds since midnight\r
+\r
+ public:\r
+ void Clear() { mTime = 0; }\r
+ void Now();\r
+ void SetTime(int hour, int minute, int second, int tenthousandths = 0);\r
+ void SetTime(int tm);\r
+ void GetTime(int& hour, int& minute, int& second) const;\r
+ void GetTime(int& hour, int& minute, int& second, int& tenthousandths) const;\r
+ int GetTime() const { return mTime; }\r
+ int Hours() const;\r
+ int Minutes() const;\r
+ int Seconds() const;\r
+ int SubSeconds() const; // Actually tenthousandths of seconds\r
+ Time() { Clear(); }\r
+ Time(int tm) { SetTime(tm); }\r
+ Time(int hour, int minute, int second, int tenthousandths = 0);\r
+ Time(const Time&); // Copy Constructor\r
+ Time& operator=(const Timestamp&); // Timestamp Assignment operator\r
+ Time& operator=(const Time&); // Time Assignment operator\r
+\r
+ bool operator==(const Time& rv) const { return mTime == rv.GetTime(); }\r
+ bool operator!=(const Time& rv) const { return mTime != rv.GetTime(); }\r
+ bool operator<(const Time& rv) const { return mTime < rv.GetTime(); }\r
+ bool operator>(const Time& rv) const { return mTime > rv.GetTime(); }\r
+\r
+ virtual ~Time() { };\r
+ };\r
+\r
+ /* Class Timestamp represent a date AND a time. It is usefull in\r
+ * interactions with the SQL TIMESTAMP type of Interbase. This class\r
+ * inherits from Date and Time and completely inline implements its small\r
+ * specific details. */\r
+\r
+ class Timestamp : public Date, public Time\r
+ {\r
+ public:\r
+ void Clear() { Date::Clear(); Time::Clear(); }\r
+ void Today() { Date::Today(); Time::Clear(); }\r
+ void Now() { Date::Today(); Time::Now(); }\r
+\r
+ Timestamp() { Clear(); }\r
+\r
+ Timestamp(int y, int m, int d)\r
+ { Date::SetDate(y, m, d); Time::Clear(); }\r
+\r
+ Timestamp(int y, int mo, int d, int h, int mi, int s, int t = 0)\r
+ { Date::SetDate(y, mo, d); Time::SetTime(h, mi, s, t); }\r
+\r
+ Timestamp(const Timestamp& rv)\r
+ : Date(rv.mDate), Time(rv.mTime) {} // Copy Constructor\r
+\r
+ Timestamp(const Date& rv)\r
+ { mDate = rv.GetDate(); mTime = 0; }\r
+\r
+ Timestamp(const Time& rv)\r
+ { mDate = 0; mTime = rv.GetTime(); }\r
+\r
+ Timestamp& operator=(const Timestamp& rv) // Timestamp Assignment operator\r
+ { mDate = rv.mDate; mTime = rv.mTime; return *this; }\r
+\r
+ Timestamp& operator=(const Date& rv) // Date Assignment operator\r
+ { mDate = rv.GetDate(); return *this; }\r
+\r
+ Timestamp& operator=(const Time& rv) // Time Assignment operator\r
+ { mTime = rv.GetTime(); return *this; }\r
+\r
+ bool operator==(const Timestamp& rv) const\r
+ { return (mDate == rv.GetDate()) && (mTime == rv.GetTime()); }\r
+\r
+ bool operator!=(const Timestamp& rv) const\r
+ { return (mDate != rv.GetDate()) || (mTime != rv.GetTime()); }\r
+\r
+ bool operator<(const Timestamp& rv) const\r
+ { return (mDate < rv.GetDate()) ||\r
+ (mDate == rv.GetDate() && mTime < rv.GetTime()); }\r
+\r
+ bool operator>(const Timestamp& rv) const\r
+ { return (mDate > rv.GetDate()) ||\r
+ (mDate == rv.GetDate() && mTime > rv.GetTime()); }\r
+\r
+ ~Timestamp() { }\r
+ };\r
+\r
+ /* Class DBKey can store a DBKEY, that special value which the hidden\r
+ * RDB$DBKEY can give you from a select statement. A DBKey is nothing\r
+ * specific to IBPP. It's a feature of the Firebird database engine. See its\r
+ * documentation for more information. */\r
+\r
+ class DBKey\r
+ {\r
+ private:\r
+ std::string mDBKey; // Stores the binary DBKey\r
+ mutable std::string mString;// String (temporary) representation of it\r
+\r
+ public:\r
+ void Clear();\r
+ int Size() const { return (int)mDBKey.size(); }\r
+ void SetKey(const void*, int size);\r
+ void GetKey(void*, int size) const;\r
+ const char* AsString() const;\r
+\r
+ DBKey& operator=(const DBKey&); // Assignment operator\r
+ DBKey(const DBKey&); // Copy Constructor\r
+ DBKey() { }\r
+ ~DBKey() { }\r
+ };\r
+\r
+ /* Class User wraps all the information about a user that the engine can manage. */\r
+\r
+ class User\r
+ {\r
+ public:\r
+ std::string username;\r
+ std::string password;\r
+ std::string firstname;\r
+ std::string middlename;\r
+ std::string lastname;\r
+ uint32_t userid; // Only relevant on unixes\r
+ uint32_t groupid; // Only relevant on unixes\r
+\r
+ private:\r
+ void copyfrom(const User& r);\r
+\r
+ public:\r
+ void clear();\r
+ User& operator=(const User& r) { copyfrom(r); return *this; }\r
+ User(const User& r) { copyfrom(r); }\r
+ User() : userid(0), groupid(0) { }\r
+ ~User() { };\r
+ };\r
+\r
+ // Interface Wrapper\r
+ template <class T>\r
+ class Ptr\r
+ {\r
+ private:\r
+ T* mObject;\r
+\r
+ public:\r
+ void clear()\r
+ {\r
+ if (mObject != 0) { mObject->Release(); mObject = 0; }\r
+ }\r
+\r
+ T* intf() const { return mObject; }\r
+ T* operator->() const { return mObject; }\r
+\r
+ bool operator==(const T* p) const { return mObject == p; }\r
+ bool operator==(const Ptr& r) const { return mObject == r.mObject; }\r
+ bool operator!=(const T* p) const { return mObject != p; }\r
+ bool operator!=(const Ptr& r) const { return mObject != r.mObject; }\r
+\r
+ Ptr& operator=(T* p)\r
+ {\r
+ // AddRef _before_ Release gives correct behaviour on self-assigns\r
+ T* tmp = (p == 0 ? 0 : p->AddRef()); // Take care of 0\r
+ if (mObject != 0) mObject->Release();\r
+ mObject = tmp; return *this;\r
+ }\r
+\r
+ Ptr& operator=(const Ptr& r)\r
+ {\r
+ // AddRef _before_ Release gives correct behaviour on self-assigns\r
+ T* tmp = (r.intf() == 0 ? 0 : r->AddRef());// Take care of 0\r
+ if (mObject != 0) mObject->Release();\r
+ mObject = tmp; return *this;\r
+ }\r
+\r
+ Ptr(T* p) : mObject(p == 0 ? 0 : p->AddRef()) { }\r
+ Ptr(const Ptr& r) : mObject(r.intf() == 0 ? 0 : r->AddRef()) { }\r
+\r
+ Ptr() : mObject(0) { }\r
+ ~Ptr() { clear(); }\r
+ };\r
+\r
+ // --- Interface Classes --- //\r
+\r
+ /* Interfaces IBlob, IArray, IService, IDatabase, ITransaction and\r
+ * IStatement are at the core of IBPP. Though it is possible to program your\r
+ * applications by using theses interfaces directly (as was the case with\r
+ * IBPP 1.x), you should refrain from using them and prefer the new IBPP\r
+ * Objects Blob, Array, ... (without the I in front). Those new objects are\r
+ * typedef'd right after each interface class definition as you can read\r
+ * below. If you program using the Blob (instead of the IBlob interface\r
+ * itself), you'll never have to care about AddRef/Release and you'll never\r
+ * have to care about deleting your objects. */\r
+\r
+ class IBlob; typedef Ptr<IBlob> Blob;\r
+ class IArray; typedef Ptr<IArray> Array;\r
+ class IService; typedef Ptr<IService> Service;\r
+ class IDatabase; typedef Ptr<IDatabase> Database;\r
+ class ITransaction; typedef Ptr<ITransaction> Transaction;\r
+ class IStatement; typedef Ptr<IStatement> Statement;\r
+ class IEvents; typedef Ptr<IEvents> Events;\r
+ class IRow; typedef Ptr<IRow> Row;\r
+\r
+ /* IBlob is the interface to the blob capabilities of IBPP. Blob is the\r
+ * object class you actually use in your programming. In Firebird, at the\r
+ * row level, a blob is merely a handle to a blob, stored elsewhere in the\r
+ * database. Blob allows you to retrieve such a handle and then read from or\r
+ * write to the blob, much in the same manner than you would do with a file. */\r
+\r
+ class IBlob\r
+ {\r
+ public:\r
+ virtual void Create() = 0;\r
+ virtual void Open() = 0;\r
+ virtual void Close() = 0;\r
+ virtual void Cancel() = 0;\r
+ virtual int Read(void*, int size) = 0;\r
+ virtual void Write(const void*, int size) = 0;\r
+ virtual void Info(int* Size, int* Largest, int* Segments) = 0;\r
+ \r
+ virtual void Save(const std::string& data) = 0;\r
+ virtual void Load(std::string& data) = 0;\r
+\r
+ virtual Database DatabasePtr() const = 0;\r
+ virtual Transaction TransactionPtr() const = 0;\r
+\r
+ virtual IBlob* AddRef() = 0;\r
+ virtual void Release() = 0;\r
+\r
+ virtual ~IBlob() { };\r
+ };\r
+\r
+ /* IArray is the interface to the array capabilities of IBPP. Array is the\r
+ * object class you actually use in your programming. With an Array object, you\r
+ * can create, read and write Interbase Arrays, as a whole or in slices. */\r
+\r
+ class IArray\r
+ {\r
+ public:\r
+ virtual void Describe(const std::string& table, const std::string& column) = 0;\r
+ virtual void ReadTo(ADT, void* buffer, int elemcount) = 0;\r
+ virtual void WriteFrom(ADT, const void* buffer, int elemcount) = 0;\r
+ virtual SDT ElementType() = 0;\r
+ virtual int ElementSize() = 0;\r
+ virtual int ElementScale() = 0;\r
+ virtual int Dimensions() = 0;\r
+ virtual void Bounds(int dim, int* low, int* high) = 0;\r
+ virtual void SetBounds(int dim, int low, int high) = 0;\r
+\r
+ virtual Database DatabasePtr() const = 0;\r
+ virtual Transaction TransactionPtr() const = 0;\r
+\r
+ virtual IArray* AddRef() = 0;\r
+ virtual void Release() = 0;\r
+\r
+ virtual ~IArray() { };\r
+ };\r
+\r
+ /* IService is the interface to the service capabilities of IBPP. Service is\r
+ * the object class you actually use in your programming. With a Service\r
+ * object, you can do some maintenance work of databases and servers\r
+ * (backup, restore, create/update users, ...) */\r
+\r
+ class IService\r
+ {\r
+ public:\r
+ virtual void Connect() = 0;\r
+ virtual bool Connected() = 0;\r
+ virtual void Disconnect() = 0;\r
+\r
+ virtual void GetVersion(std::string& version) = 0;\r
+\r
+ virtual void AddUser(const User&) = 0;\r
+ virtual void GetUser(User&) = 0;\r
+ virtual void GetUsers(std::vector<User>&) = 0;\r
+ virtual void ModifyUser(const User&) = 0;\r
+ virtual void RemoveUser(const std::string& username) = 0;\r
+\r
+ virtual void SetPageBuffers(const std::string& dbfile, int buffers) = 0;\r
+ virtual void SetSweepInterval(const std::string& dbfile, int sweep) = 0;\r
+ virtual void SetSyncWrite(const std::string& dbfile, bool) = 0;\r
+ virtual void SetReadOnly(const std::string& dbfile, bool) = 0;\r
+ virtual void SetReserveSpace(const std::string& dbfile, bool) = 0;\r
+\r
+ virtual void Shutdown(const std::string& dbfile, DSM mode, int sectimeout) = 0;\r
+ virtual void Restart(const std::string& dbfile) = 0;\r
+ virtual void Sweep(const std::string& dbfile) = 0;\r
+ virtual void Repair(const std::string& dbfile, RPF flags) = 0;\r
+\r
+ virtual void StartBackup(const std::string& dbfile,\r
+ const std::string& bkfile, BRF flags = BRF(0)) = 0;\r
+ virtual void StartRestore(const std::string& bkfile, const std::string& dbfile,\r
+ int pagesize = 0, BRF flags = BRF(0)) = 0;\r
+\r
+ virtual const char* WaitMsg() = 0; // With reporting (does not block)\r
+ virtual void Wait() = 0; // Without reporting (does block)\r
+\r
+ virtual IService* AddRef() = 0;\r
+ virtual void Release() = 0;\r
+\r
+ virtual ~IService() { };\r
+ };\r
+\r
+ /* IDatabase is the interface to the database connections in IBPP. Database\r
+ * is the object class you actually use in your programming. With a Database\r
+ * object, you can create/drop/connect databases. */\r
+\r
+ class EventInterface; // Cross-reference between EventInterface and IDatabase\r
+ \r
+ class IDatabase\r
+ {\r
+ public:\r
+ virtual const char* ServerName() const = 0;\r
+ virtual const char* DatabaseName() const = 0;\r
+ virtual const char* Username() const = 0;\r
+ virtual const char* UserPassword() const = 0;\r
+ virtual const char* RoleName() const = 0;\r
+ virtual const char* CharSet() const = 0;\r
+ virtual const char* CreateParams() const = 0;\r
+\r
+ virtual void Info(int* ODS, int* ODSMinor, int* PageSize,\r
+ int* Pages, int* Buffers, int* Sweep, bool* Sync,\r
+ bool* Reserve) = 0;\r
+ virtual void Statistics(int* Fetches, int* Marks,\r
+ int* Reads, int* Writes) = 0;\r
+ virtual void Counts(int* Insert, int* Update, int* Delete, \r
+ int* ReadIdx, int* ReadSeq) = 0;\r
+ virtual void Users(std::vector<std::string>& users) = 0;\r
+ virtual int Dialect() = 0;\r
+\r
+ virtual void Create(int dialect) = 0;\r
+ virtual void Connect() = 0;\r
+ virtual bool Connected() = 0;\r
+ virtual void Inactivate() = 0;\r
+ virtual void Disconnect() = 0;\r
+ virtual void Drop() = 0;\r
+\r
+ virtual IDatabase* AddRef() = 0;\r
+ virtual void Release() = 0;\r
+\r
+ virtual ~IDatabase() { };\r
+ };\r
+\r
+ /* ITransaction is the interface to the transaction connections in IBPP.\r
+ * Transaction is the object class you actually use in your programming. A\r
+ * Transaction object can be associated with more than one Database,\r
+ * allowing for distributed transactions spanning multiple databases,\r
+ * possibly located on different servers. IBPP is one among the few\r
+ * programming interfaces to Firebird that allows you to support distributed\r
+ * transactions. */\r
+\r
+ class ITransaction\r
+ {\r
+ public:\r
+ virtual void AttachDatabase(Database db, TAM am = amWrite,\r
+ TIL il = ilConcurrency, TLR lr = lrWait, TFF flags = TFF(0)) = 0;\r
+ virtual void DetachDatabase(Database db) = 0;\r
+ virtual void AddReservation(Database db,\r
+ const std::string& table, TTR tr) = 0;\r
+\r
+ virtual void Start() = 0;\r
+ virtual bool Started() = 0;\r
+ virtual void Commit() = 0;\r
+ virtual void Rollback() = 0;\r
+ virtual void CommitRetain() = 0;\r
+ virtual void RollbackRetain() = 0;\r
+\r
+ virtual ITransaction* AddRef() = 0;\r
+ virtual void Release() = 0;\r
+\r
+ virtual ~ITransaction() { };\r
+ };\r
+\r
+ /*\r
+ * Class Row can hold all the values of a row (from a SELECT for instance).\r
+ */\r
+\r
+ class IRow\r
+ {\r
+ public:\r
+ virtual void SetNull(int) = 0;\r
+ virtual void Set(int, bool) = 0;\r
+ virtual void Set(int, const void*, int) = 0; // byte buffers\r
+ virtual void Set(int, const char*) = 0; // c-string\r
+ virtual void Set(int, const std::string&) = 0;\r
+ virtual void Set(int, int16_t) = 0;\r
+ virtual void Set(int, int32_t) = 0;\r
+ virtual void Set(int, int64_t) = 0;\r
+ virtual void Set(int, float) = 0;\r
+ virtual void Set(int, double) = 0;\r
+ virtual void Set(int, const Timestamp&) = 0;\r
+ virtual void Set(int, const Date&) = 0;\r
+ virtual void Set(int, const Time&) = 0;\r
+ virtual void Set(int, const DBKey&) = 0;\r
+ virtual void Set(int, const Blob&) = 0;\r
+ virtual void Set(int, const Array&) = 0;\r
+\r
+ virtual bool IsNull(int) = 0;\r
+ virtual bool Get(int, bool&) = 0;\r
+ virtual bool Get(int, void*, int&) = 0; // byte buffers\r
+ virtual bool Get(int, std::string&) = 0;\r
+ virtual bool Get(int, int16_t&) = 0;\r
+ virtual bool Get(int, int32_t&) = 0;\r
+ virtual bool Get(int, int64_t&) = 0;\r
+ virtual bool Get(int, float&) = 0;\r
+ virtual bool Get(int, double&) = 0;\r
+ virtual bool Get(int, Timestamp&) = 0;\r
+ virtual bool Get(int, Date&) = 0;\r
+ virtual bool Get(int, Time&) = 0;\r
+ virtual bool Get(int, DBKey&) = 0;\r
+ virtual bool Get(int, Blob&) = 0;\r
+ virtual bool Get(int, Array&) = 0;\r
+\r
+ virtual bool IsNull(const std::string&) = 0;\r
+ virtual bool Get(const std::string&, bool&) = 0;\r
+ virtual bool Get(const std::string&, void*, int&) = 0; // byte buffers\r
+ virtual bool Get(const std::string&, std::string&) = 0;\r
+ virtual bool Get(const std::string&, int16_t&) = 0;\r
+ virtual bool Get(const std::string&, int32_t&) = 0;\r
+ virtual bool Get(const std::string&, int64_t&) = 0;\r
+ virtual bool Get(const std::string&, float&) = 0;\r
+ virtual bool Get(const std::string&, double&) = 0;\r
+ virtual bool Get(const std::string&, Timestamp&) = 0;\r
+ virtual bool Get(const std::string&, Date&) = 0;\r
+ virtual bool Get(const std::string&, Time&) = 0;\r
+ virtual bool Get(const std::string&, DBKey&) = 0;\r
+ virtual bool Get(const std::string&, Blob&) = 0;\r
+ virtual bool Get(const std::string&, Array&) = 0;\r
+\r
+ virtual int ColumnNum(const std::string&) = 0;\r
+ virtual const char* ColumnName(int) = 0;\r
+ virtual const char* ColumnAlias(int) = 0;\r
+ virtual const char* ColumnTable(int) = 0;\r
+ virtual SDT ColumnType(int) = 0;\r
+ virtual int ColumnSubtype(int) = 0;\r
+ virtual int ColumnSize(int) = 0;\r
+ virtual int ColumnScale(int) = 0;\r
+ virtual int Columns() = 0;\r
+ \r
+ virtual bool ColumnUpdated(int) = 0;\r
+ virtual bool Updated() = 0;\r
+\r
+ virtual Database DatabasePtr() const = 0;\r
+ virtual Transaction TransactionPtr() const = 0;\r
+\r
+ virtual IRow* Clone() = 0;\r
+ virtual IRow* AddRef() = 0;\r
+ virtual void Release() = 0;\r
+\r
+ virtual ~IRow() {};\r
+ };\r
+\r
+ /* IStatement is the interface to the statements execution in IBPP.\r
+ * Statement is the object class you actually use in your programming. A\r
+ * Statement object is the work horse of IBPP. All your data manipulation\r
+ * statements will be done through it. It is also used to access the result\r
+ * set of a query (when the statement is such), one row at a time and in\r
+ * strict forward direction. */\r
+\r
+ class IStatement\r
+ {\r
+ public:\r
+ virtual void Prepare(const std::string&) = 0;\r
+ virtual void Execute() = 0;\r
+ virtual void Execute(const std::string&) = 0;\r
+ virtual void ExecuteImmediate(const std::string&) = 0;\r
+ virtual void CursorExecute(const std::string& cursor) = 0;\r
+ virtual void CursorExecute(const std::string& cursor, const std::string&) = 0;\r
+ virtual bool Fetch() = 0;\r
+ virtual bool Fetch(Row&) = 0;\r
+ virtual int AffectedRows() = 0;\r
+ virtual void Close() = 0;\r
+ virtual std::string& Sql() = 0;\r
+ virtual STT Type() = 0;\r
+\r
+ virtual void SetNull(int) = 0;\r
+ virtual void Set(int, bool) = 0;\r
+ virtual void Set(int, const void*, int) = 0; // byte buffers\r
+ virtual void Set(int, const char*) = 0; // c-string\r
+ virtual void Set(int, const std::string&) = 0;\r
+ virtual void Set(int, int16_t value) = 0;\r
+ virtual void Set(int, int32_t value) = 0;\r
+ virtual void Set(int, int64_t value) = 0;\r
+ virtual void Set(int, float value) = 0;\r
+ virtual void Set(int, double value) = 0;\r
+ virtual void Set(int, const Timestamp& value) = 0;\r
+ virtual void Set(int, const Date& value) = 0;\r
+ virtual void Set(int, const Time& value) = 0;\r
+ virtual void Set(int, const DBKey& value) = 0;\r
+ virtual void Set(int, const Blob& value) = 0;\r
+ virtual void Set(int, const Array& value) = 0;\r
+\r
+ virtual bool IsNull(int) = 0;\r
+ virtual bool Get(int, bool&) = 0;\r
+ virtual bool Get(int, void*, int&) = 0; // byte buffers\r
+ virtual bool Get(int, std::string&) = 0;\r
+ virtual bool Get(int, int16_t&) = 0;\r
+ virtual bool Get(int, int32_t&) = 0;\r
+ virtual bool Get(int, int64_t&) = 0;\r
+ virtual bool Get(int, float&) = 0;\r
+ virtual bool Get(int, double&) = 0;\r
+ virtual bool Get(int, Timestamp& value) = 0;\r
+ virtual bool Get(int, Date& value) = 0;\r
+ virtual bool Get(int, Time& value) = 0;\r
+ virtual bool Get(int, DBKey& value) = 0;\r
+ virtual bool Get(int, Blob& value) = 0;\r
+ virtual bool Get(int, Array& value) = 0;\r
+\r
+ virtual bool IsNull(const std::string&) = 0;\r
+ virtual bool Get(const std::string&, bool&) = 0;\r
+ virtual bool Get(const std::string&, void*, int&) = 0; // byte buffers\r
+ virtual bool Get(const std::string&, std::string&) = 0;\r
+ virtual bool Get(const std::string&, int16_t&) = 0;\r
+ virtual bool Get(const std::string&, int32_t&) = 0;\r
+ virtual bool Get(const std::string&, int64_t&) = 0;\r
+ virtual bool Get(const std::string&, float&) = 0;\r
+ virtual bool Get(const std::string&, double&) = 0;\r
+ virtual bool Get(const std::string&, Timestamp& value) = 0;\r
+ virtual bool Get(const std::string&, Date& value) = 0;\r
+ virtual bool Get(const std::string&, Time& value) = 0;\r
+ virtual bool Get(const std::string&, DBKey& value) = 0;\r
+ virtual bool Get(const std::string&, Blob& value) = 0;\r
+ virtual bool Get(const std::string&, Array& value) = 0;\r
+\r
+ virtual int ColumnNum(const std::string&) = 0;\r
+ virtual const char* ColumnName(int) = 0;\r
+ virtual const char* ColumnAlias(int) = 0;\r
+ virtual const char* ColumnTable(int) = 0;\r
+ virtual SDT ColumnType(int) = 0;\r
+ virtual int ColumnSubtype(int) = 0;\r
+ virtual int ColumnSize(int) = 0;\r
+ virtual int ColumnScale(int) = 0;\r
+ virtual int Columns() = 0;\r
+\r
+ virtual SDT ParameterType(int) = 0;\r
+ virtual int ParameterSubtype(int) = 0;\r
+ virtual int ParameterSize(int) = 0;\r
+ virtual int ParameterScale(int) = 0;\r
+ virtual int Parameters() = 0;\r
+\r
+ virtual void Plan(std::string&) = 0;\r
+\r
+ virtual Database DatabasePtr() const = 0;\r
+ virtual Transaction TransactionPtr() const = 0;\r
+\r
+ virtual IStatement* AddRef() = 0;\r
+ virtual void Release() = 0;\r
+\r
+ virtual ~IStatement() { };\r
+\r
+ // DEPRECATED METHODS (WON'T BE AVAILABLE IN VERSIONS 3.x)\r
+ virtual bool Get(int, char*) = 0; // DEPRECATED\r
+ virtual bool Get(const std::string&, char*) = 0; // DEPRECATED\r
+ virtual bool Get(int, bool*) = 0; // DEPRECATED\r
+ virtual bool Get(const std::string&, bool*) = 0; // DEPRECATED\r
+ virtual bool Get(int, int16_t*) = 0; // DEPRECATED\r
+ virtual bool Get(const std::string&, int16_t*) = 0; // DEPRECATED\r
+ virtual bool Get(int, int32_t*) = 0; // DEPRECATED\r
+ virtual bool Get(const std::string&, int32_t*) = 0; // DEPRECATED\r
+ virtual bool Get(int, int64_t*) = 0; // DEPRECATED\r
+ virtual bool Get(const std::string&, int64_t*) = 0; // DEPRECATED\r
+ virtual bool Get(int, float*) = 0; // DEPRECATED\r
+ virtual bool Get(const std::string&, float*) = 0; // DEPRECATED\r
+ virtual bool Get(int, double*) = 0; // DEPRECATED\r
+ virtual bool Get(const std::string&, double*) = 0; // DEPRECATED\r
+ };\r
+ \r
+ class IEvents\r
+ {\r
+ public:\r
+ virtual void Add(const std::string&, EventInterface*) = 0;\r
+ virtual void Drop(const std::string&) = 0;\r
+ virtual void List(std::vector<std::string>&) = 0;\r
+ virtual void Clear() = 0; // Drop all events\r
+ virtual void Dispatch() = 0; // Dispatch events (calls handlers)\r
+\r
+ virtual Database DatabasePtr() const = 0;\r
+\r
+ virtual IEvents* AddRef() = 0;\r
+ virtual void Release() = 0;\r
+\r
+ virtual ~IEvents() { };\r
+ };\r
+ \r
+ /* Class EventInterface is merely a pure interface.\r
+ * It is _not_ implemented by IBPP. It is only a base class definition from\r
+ * which your own event interface classes have to derive from.\r
+ * Please read the reference guide at http://www.ibpp.org for more info. */\r
+\r
+ class EventInterface\r
+ {\r
+ public:\r
+ virtual void ibppEventHandler(Events, const std::string&, int) = 0;\r
+ virtual ~EventInterface() { };\r
+ };\r
+\r
+ // --- Factories ---\r
+ // These methods are the only way to get one of the above\r
+ // Interfaces. They are at the heart of how you program using IBPP. For\r
+ // instance, to get access to a database, you'll write code similar to this:\r
+ // {\r
+ // Database db = DatabaseFactory("server", "databasename",\r
+ // "user", "password");\r
+ // db->Connect();\r
+ // ...\r
+ // db->Disconnect();\r
+ // }\r
+\r
+ Service ServiceFactory(const std::string& ServerName,\r
+ const std::string& UserName, const std::string& UserPassword);\r
+\r
+ Database DatabaseFactory(const std::string& ServerName,\r
+ const std::string& DatabaseName, const std::string& UserName,\r
+ const std::string& UserPassword, const std::string& RoleName,\r
+ const std::string& CharSet, const std::string& CreateParams);\r
+\r
+ inline Database DatabaseFactory(const std::string& ServerName,\r
+ const std::string& DatabaseName, const std::string& UserName,\r
+ const std::string& UserPassword)\r
+ { return DatabaseFactory(ServerName, DatabaseName, UserName, UserPassword, "", "", ""); }\r
+\r
+ Transaction TransactionFactory(Database db, TAM am = amWrite,\r
+ TIL il = ilConcurrency, TLR lr = lrWait, TFF flags = TFF(0));\r
+\r
+ Statement StatementFactory(Database db, Transaction tr,\r
+ const std::string& sql);\r
+\r
+ inline Statement StatementFactory(Database db, Transaction tr)\r
+ { return StatementFactory(db, tr, ""); }\r
+\r
+ Blob BlobFactory(Database db, Transaction tr);\r
+ \r
+ Array ArrayFactory(Database db, Transaction tr);\r
+ \r
+ Events EventsFactory(Database db);\r
+\r
+ /* IBPP uses a self initialization system. Each time an object that may\r
+ * require the usage of the Interbase client C-API library is used, the\r
+ * library internal handling details are automatically initialized, if not\r
+ * already done. You can kick this initialization at the start of an\r
+ * application by calling IBPP::CheckVersion(). This is recommended, because\r
+ * IBPP::CheckVersion will assure you that YOUR code has been compiled\r
+ * against a compatible version of the library. */\r
+\r
+ bool CheckVersion(uint32_t);\r
+ int GDSVersion();\r
+ \r
+ /* On Win32 platform, ClientLibSearchPaths() allows to setup\r
+ * one or multiple additional paths (separated with a ';') where IBPP\r
+ * will look for the client library (before the default implicit search\r
+ * locations). This is usefull for applications distributed with a 'private'\r
+ * copy of Firebird, when the registry is useless to identify the location\r
+ * from where to attempt loading the fbclient.dll / gds32.dll.\r
+ * If called, this function must be called *early* by the application,\r
+ * before *any* other function or object methods of IBPP.\r
+ * Currently, this is a NO-OP on platforms other than Win32. */\r
+ \r
+ void ClientLibSearchPaths(const std::string&);\r
+\r
+ /* Finally, here are some date and time conversion routines used by IBPP and\r
+ * that may be helpful at the application level. They do not depend on\r
+ * anything related to Firebird/Interbase. Just a bonus. dtoi and itod\r
+ * return false on invalid parameters or out of range conversions. */\r
+\r
+ bool dtoi(int date, int* py, int* pm, int* pd);\r
+ bool itod(int* pdate, int year, int month, int day);\r
+ void ttoi(int itime, int* phour, int* pminute, int* psecond, int* ptt);\r
+ void itot(int* ptime, int hour, int minute, int second = 0, int tenthousandths = 0);\r
+\r
+}\r
+\r
+#endif\r
+\r
+//\r
+// EOF\r
+//\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: row.cpp,v 1.2 2009/03/19 20:00:28 faust Exp $\r
+// Subject : IBPP, Row class implementation\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning(disable: 4786 4996)\r
+#ifndef _DEBUG\r
+#pragma warning(disable: 4702)\r
+#endif\r
+#endif\r
+\r
+#include "_ibpp.h"\r
+\r
+#ifdef HAS_HDRSTOP\r
+#pragma hdrstop\r
+#endif\r
+\r
+#include <math.h>\r
+#include <time.h>\r
+#include <cstring>\r
+\r
+using namespace ibpp_internals;\r
+\r
+// (((((((( OBJECT INTERFACE IMPLEMENTATION ))))))))\r
+\r
+void RowImpl::SetNull(int param)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::SetNull", _("The row is not initialized."));\r
+ if (param < 1 || param > mDescrArea->sqld)\r
+ throw LogicExceptionImpl("Row::SetNull", _("Variable index out of range."));\r
+\r
+ XSQLVAR* var = &(mDescrArea->sqlvar[param-1]);\r
+ if (! (var->sqltype & 1))\r
+ throw LogicExceptionImpl("Row::SetNull", _("This column can't be null."));\r
+\r
+ *var->sqlind = -1; // Set the column to SQL NULL\r
+ mUpdated[param-1] = true;\r
+}\r
+\r
+void RowImpl::Set(int param, bool value)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Set[bool]", _("The row is not initialized."));\r
+\r
+ SetValue(param, ivBool, &value);\r
+ mUpdated[param-1] = true;\r
+}\r
+\r
+void RowImpl::Set(int param, const char* cstring)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Set[char*]", _("The row is not initialized."));\r
+ if (cstring == 0)\r
+ throw LogicExceptionImpl("Row::Set[char*]", _("null char* pointer detected."));\r
+\r
+ SetValue(param, ivByte, cstring, (int)strlen(cstring));\r
+ mUpdated[param-1] = true;\r
+}\r
+\r
+void RowImpl::Set(int param, const void* bindata, int len)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Set[void*]", _("The row is not initialized."));\r
+ if (bindata == 0)\r
+ throw LogicExceptionImpl("Row::Set[void*]", _("null char* pointer detected."));\r
+ if (len < 0)\r
+ throw LogicExceptionImpl("Row::Set[void*]", _("Length must be >= 0"));\r
+ \r
+ SetValue(param, ivByte, bindata, len);\r
+ mUpdated[param-1] = true;\r
+}\r
+\r
+void RowImpl::Set(int param, const std::string& s)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Set[string]", _("The row is not initialized."));\r
+\r
+ SetValue(param, ivString, (void*)&s);\r
+ mUpdated[param-1] = true;\r
+}\r
+\r
+void RowImpl::Set(int param, int16_t value)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Set[int16_t]", _("The row is not initialized."));\r
+ \r
+ SetValue(param, ivInt16, &value);\r
+ mUpdated[param-1] = true;\r
+}\r
+\r
+void RowImpl::Set(int param, int32_t value)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Set[int32_t]", _("The row is not initialized."));\r
+\r
+ SetValue(param, ivInt32, &value);\r
+ mUpdated[param-1] = true;\r
+}\r
+\r
+void RowImpl::Set(int param, int64_t value)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Set[int64_t]", _("The row is not initialized."));\r
+\r
+ SetValue(param, ivInt64, &value);\r
+ mUpdated[param-1] = true;\r
+}\r
+\r
+void RowImpl::Set(int param, float value)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Set[float]", _("The row is not initialized."));\r
+\r
+ SetValue(param, ivFloat, &value);\r
+ mUpdated[param-1] = true;\r
+}\r
+\r
+void RowImpl::Set(int param, double value)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Set[double]", _("The row is not initialized."));\r
+\r
+ SetValue(param, ivDouble, &value);\r
+ mUpdated[param-1] = true;\r
+}\r
+\r
+void RowImpl::Set(int param, const IBPP::Timestamp& value)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Set[Timestamp]", _("The row is not initialized."));\r
+\r
+ SetValue(param, ivTimestamp, &value);\r
+ mUpdated[param-1] = true;\r
+}\r
+\r
+void RowImpl::Set(int param, const IBPP::Date& value)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Set[Date]", _("The row is not initialized."));\r
+\r
+ if (mDialect == 1)\r
+ {\r
+ // In dialect 1, IBPP::Date is supposed to work with old 'DATE'\r
+ // fields which are actually ISC_TIMESTAMP.\r
+ IBPP::Timestamp timestamp(value);\r
+ SetValue(param, ivTimestamp, ×tamp);\r
+ }\r
+ else\r
+ {\r
+ // Dialect 3\r
+ SetValue(param, ivDate, (void*)&value);\r
+ }\r
+\r
+ mUpdated[param-1] = true;\r
+}\r
+\r
+void RowImpl::Set(int param, const IBPP::Time& value)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Set[Time]", _("The row is not initialized."));\r
+ if (mDialect == 1)\r
+ throw LogicExceptionImpl("Row::Set[Time]", _("Requires use of a dialect 3 database."));\r
+\r
+ SetValue(param, ivTime, &value);\r
+ mUpdated[param-1] = true;\r
+}\r
+\r
+void RowImpl::Set(int param, const IBPP::Blob& blob)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Set[Blob]", _("The row is not initialized."));\r
+ if (mDatabase != 0 && blob->DatabasePtr() != mDatabase)\r
+ throw LogicExceptionImpl("Row::Set[Blob]",\r
+ _("IBlob and Row attached to different databases"));\r
+ if (mTransaction != 0 && blob->TransactionPtr() != mTransaction)\r
+ throw LogicExceptionImpl("Row::Set[Blob]",\r
+ _("IBlob and Row attached to different transactions"));\r
+\r
+ SetValue(param, ivBlob, blob.intf());\r
+ mUpdated[param-1] = true;\r
+}\r
+\r
+void RowImpl::Set(int param, const IBPP::Array& array)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Set[Array]", _("The row is not initialized."));\r
+ if (mDatabase != 0 && array->DatabasePtr() != mDatabase)\r
+ throw LogicExceptionImpl("Row::Set[Array]",\r
+ _("IArray and Row attached to different databases"));\r
+ if (mTransaction != 0 && array->TransactionPtr() != mTransaction)\r
+ throw LogicExceptionImpl("Row::Set[Array]",\r
+ _("IArray and Row attached to different transactions"));\r
+\r
+ SetValue(param, ivArray, (void*)array.intf());\r
+ mUpdated[param-1] = true;\r
+}\r
+\r
+void RowImpl::Set(int param, const IBPP::DBKey& key)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Set[DBKey]", _("The row is not initialized."));\r
+\r
+ SetValue(param, ivDBKey, (void*)&key);\r
+ mUpdated[param-1] = true;\r
+}\r
+\r
+/*\r
+void RowImpl::Set(int param, const IBPP::Value& value)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Set[Value]", _("The row is not initialized."));\r
+\r
+ //SetValue(param, ivDBKey, (void*)&key);\r
+ //mUpdated[param-1] = true;\r
+}\r
+*/\r
+\r
+bool RowImpl::IsNull(int column)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::IsNull", _("The row is not initialized."));\r
+ if (column < 1 || column > mDescrArea->sqld)\r
+ throw LogicExceptionImpl("Row::IsNull", _("Variable index out of range."));\r
+\r
+ XSQLVAR* var = &(mDescrArea->sqlvar[column-1]);\r
+ return ((var->sqltype & 1) && *(var->sqlind) != 0) ? true : false;\r
+}\r
+\r
+bool RowImpl::Get(int column, bool& retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ void* pvalue = GetValue(column, ivBool);\r
+ if (pvalue != 0)\r
+ retvalue = (*(char*)pvalue == 0 ? false : true);\r
+ return pvalue == 0 ? true : false;\r
+}\r
+\r
+bool RowImpl::Get(int column, char* retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+ if (retvalue == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("Null pointer detected"));\r
+\r
+ int sqllen;\r
+ void* pvalue = GetValue(column, ivByte, &sqllen);\r
+ if (pvalue != 0)\r
+ {\r
+ memcpy(retvalue, pvalue, sqllen);\r
+ retvalue[sqllen] = '\0';\r
+ }\r
+ return pvalue == 0 ? true : false;\r
+}\r
+\r
+bool RowImpl::Get(int column, void* bindata, int& userlen)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+ if (bindata == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("Null pointer detected"));\r
+ if (userlen < 0)\r
+ throw LogicExceptionImpl("Row::Get", _("Length must be >= 0"));\r
+\r
+ int sqllen;\r
+ void* pvalue = GetValue(column, ivByte, &sqllen);\r
+ if (pvalue != 0)\r
+ {\r
+ // userlen says how much bytes the user can accept\r
+ // let's shorten it, if there is less bytes available\r
+ if (sqllen < userlen) userlen = sqllen;\r
+ memcpy(bindata, pvalue, userlen);\r
+ }\r
+ return pvalue == 0 ? true : false;\r
+}\r
+\r
+bool RowImpl::Get(int column, std::string& retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ void* pvalue = GetValue(column, ivString, &retvalue);\r
+ return pvalue == 0 ? true : false;\r
+}\r
+\r
+bool RowImpl::Get(int column, int16_t& retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ void* pvalue = GetValue(column, ivInt16);\r
+ if (pvalue != 0)\r
+ retvalue = *(int16_t*)pvalue;\r
+ return pvalue == 0 ? true : false;\r
+}\r
+\r
+bool RowImpl::Get(int column, int32_t& retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ void* pvalue = GetValue(column, ivInt32);\r
+ if (pvalue != 0)\r
+ retvalue = *(int32_t*)pvalue;\r
+ return pvalue == 0 ? true : false;\r
+}\r
+\r
+bool RowImpl::Get(int column, int64_t& retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ void* pvalue = GetValue(column, ivInt64);\r
+ if (pvalue != 0)\r
+ retvalue = *(int64_t*)pvalue;\r
+ return pvalue == 0 ? true : false;\r
+}\r
+\r
+bool RowImpl::Get(int column, float& retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ void* pvalue = GetValue(column, ivFloat);\r
+ if (pvalue != 0)\r
+ retvalue = *(float*)pvalue;\r
+ return pvalue == 0 ? true : false;\r
+}\r
+\r
+bool RowImpl::Get(int column, double& retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ void* pvalue = GetValue(column, ivDouble);\r
+ if (pvalue != 0)\r
+ retvalue = *(double*)pvalue;\r
+ return pvalue == 0 ? true : false;\r
+}\r
+\r
+bool RowImpl::Get(int column, IBPP::Timestamp& timestamp)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ void* pvalue = GetValue(column, ivTimestamp, (void*)×tamp);\r
+ return pvalue == 0 ? true : false;\r
+}\r
+\r
+bool RowImpl::Get(int column, IBPP::Date& date)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ if (mDialect == 1)\r
+ {\r
+ // Dialect 1. IBPP::Date is supposed to work with old 'DATE'\r
+ // fields which are actually ISC_TIMESTAMP.\r
+ IBPP::Timestamp timestamp;\r
+ void* pvalue = GetValue(column, ivTimestamp, (void*)×tamp);\r
+ if (pvalue != 0) date = timestamp;\r
+ return pvalue == 0 ? true : false;\r
+ }\r
+ else\r
+ {\r
+ void* pvalue = GetValue(column, ivDate, (void*)&date);\r
+ return pvalue == 0 ? true : false;\r
+ }\r
+}\r
+\r
+bool RowImpl::Get(int column, IBPP::Time& time)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ void* pvalue = GetValue(column, ivTime, (void*)&time);\r
+ return pvalue == 0 ? true : false;\r
+}\r
+\r
+bool RowImpl::Get(int column, IBPP::Blob& retblob)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ void* pvalue = GetValue(column, ivBlob, (void*)retblob.intf());\r
+ return pvalue == 0 ? true : false;\r
+}\r
+\r
+bool RowImpl::Get(int column, IBPP::DBKey& retkey)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ void* pvalue = GetValue(column, ivDBKey, (void*)&retkey);\r
+ return pvalue == 0 ? true : false;\r
+}\r
+\r
+bool RowImpl::Get(int column, IBPP::Array& retarray)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ void* pvalue = GetValue(column, ivArray, (void*)retarray.intf());\r
+ return pvalue == 0 ? true : false;\r
+}\r
+\r
+/*\r
+const IBPP::Value RowImpl::Get(int column)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ //void* value = GetValue(column, ivArray, (void*)retarray.intf());\r
+ //return value == 0 ? true : false;\r
+ return IBPP::Value();\r
+}\r
+*/\r
+\r
+bool RowImpl::IsNull(const std::string& name)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::IsNull", _("The row is not initialized."));\r
+\r
+ return IsNull(ColumnNum(name));\r
+}\r
+\r
+bool RowImpl::Get(const std::string& name, bool& retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ return Get(ColumnNum(name), retvalue);\r
+}\r
+\r
+bool RowImpl::Get(const std::string& name, char* retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get[char*]", _("The row is not initialized."));\r
+\r
+ return Get(ColumnNum(name), retvalue);\r
+}\r
+\r
+bool RowImpl::Get(const std::string& name, void* retvalue, int& count)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get[void*,int]", _("The row is not initialized."));\r
+\r
+ return Get(ColumnNum(name), retvalue, count);\r
+}\r
+\r
+bool RowImpl::Get(const std::string& name, std::string& retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::GetString", _("The row is not initialized."));\r
+\r
+ return Get(ColumnNum(name), retvalue);\r
+}\r
+\r
+bool RowImpl::Get(const std::string& name, int16_t& retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ return Get(ColumnNum(name), retvalue);\r
+}\r
+\r
+bool RowImpl::Get(const std::string& name, int32_t& retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ return Get(ColumnNum(name), retvalue);\r
+}\r
+\r
+bool RowImpl::Get(const std::string& name, int64_t& retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ return Get(ColumnNum(name), retvalue);\r
+}\r
+\r
+bool RowImpl::Get(const std::string& name, float& retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ return Get(ColumnNum(name), retvalue);\r
+}\r
+\r
+bool RowImpl::Get(const std::string& name, double& retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ return Get(ColumnNum(name), retvalue);\r
+}\r
+\r
+bool RowImpl::Get(const std::string& name, IBPP::Timestamp& retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ return Get(ColumnNum(name), retvalue);\r
+}\r
+\r
+bool RowImpl::Get(const std::string& name, IBPP::Date& retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ return Get(ColumnNum(name), retvalue);\r
+}\r
+\r
+bool RowImpl::Get(const std::string& name, IBPP::Time& retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ return Get(ColumnNum(name), retvalue);\r
+}\r
+\r
+bool RowImpl::Get(const std::string&name, IBPP::Blob& retblob)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ return Get(ColumnNum(name), retblob);\r
+}\r
+\r
+bool RowImpl::Get(const std::string& name, IBPP::DBKey& retvalue)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ return Get(ColumnNum(name), retvalue);\r
+}\r
+\r
+bool RowImpl::Get(const std::string& name, IBPP::Array& retarray)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ return Get(ColumnNum(name), retarray);\r
+}\r
+\r
+/*\r
+const IBPP::Value RowImpl::Get(const std::string& name)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
+\r
+ return Get(ColumnNum(name));\r
+}\r
+*/\r
+\r
+int RowImpl::Columns()\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::Columns", _("The row is not initialized."));\r
+\r
+ return mDescrArea->sqld;\r
+}\r
+\r
+int RowImpl::ColumnNum(const std::string& name)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::ColumnNum", _("The row is not initialized."));\r
+ if (name.empty())\r
+ throw LogicExceptionImpl("Row::ColumnNum", _("Column name <empty> not found."));\r
+\r
+ XSQLVAR* var;\r
+ char Uname[sizeof(var->sqlname)+1]; // Max size of sqlname + '\0'\r
+\r
+ // Local upper case copy of the column name\r
+ size_t len = name.length();\r
+ if (len > sizeof(var->sqlname)) len = sizeof(var->sqlname);\r
+ strncpy(Uname, name.c_str(), len);\r
+ Uname[len] = '\0';\r
+ char* p = Uname;\r
+ while (*p != '\0') { *p = char(toupper(*p)); ++p; }\r
+\r
+ // Loop through the columns of the descriptor\r
+ for (int i = 0; i < mDescrArea->sqld; i++)\r
+ {\r
+ var = &(mDescrArea->sqlvar[i]);\r
+ if (var->sqlname_length != (int16_t)len) continue;\r
+ if (strncmp(Uname, var->sqlname, len) == 0) return i+1;\r
+ }\r
+\r
+ // Failed finding the column name, let's retry using the aliases\r
+ char Ualias[sizeof(var->aliasname)+1]; // Max size of aliasname + '\0'\r
+\r
+ // Local upper case copy of the column name\r
+ len = name.length();\r
+ if (len > sizeof(var->aliasname)) len = sizeof(var->aliasname);\r
+ strncpy(Ualias, name.c_str(), len);\r
+ Ualias[len] = '\0';\r
+ p = Ualias;\r
+ while (*p != '\0') { *p = char(toupper(*p)); ++p; }\r
+\r
+ // Loop through the columns of the descriptor\r
+ for (int i = 0; i < mDescrArea->sqld; i++)\r
+ {\r
+ var = &(mDescrArea->sqlvar[i]);\r
+ if (var->aliasname_length != (int16_t)len) continue;\r
+ if (strncmp(Ualias, var->aliasname, len) == 0) return i+1;\r
+ }\r
+\r
+ throw LogicExceptionImpl("Row::ColumnNum", _("Could not find matching column."));\r
+#ifdef __DMC__\r
+ return 0; // DMC errronously warns here about a missing return\r
+#endif\r
+}\r
+\r
+/*\r
+ColumnName, ColumnAlias, ColumnTable : all these 3 have a mistake.\r
+Ideally, the strings should be stored elsewhere (like _Numerics and so on) to\r
+take into account the final '\0' which needs to be added. For now, we insert\r
+the '\0' in the original data, which will cut the 32th character. Not terribly\r
+bad, but should be cleanly rewritten.\r
+*/\r
+\r
+const char* RowImpl::ColumnName(int varnum)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::ColumnName", _("The row is not initialized."));\r
+ if (varnum < 1 || varnum > mDescrArea->sqld)\r
+ throw LogicExceptionImpl("Row::ColumName", _("Variable index out of range."));\r
+\r
+ XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);\r
+ if (var->sqlname_length >= 31) var->sqlname_length = 31;\r
+ var->sqlname[var->sqlname_length] = '\0';\r
+ return var->sqlname;\r
+}\r
+\r
+const char* RowImpl::ColumnAlias(int varnum)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::ColumnAlias", _("The row is not initialized."));\r
+ if (varnum < 1 || varnum > mDescrArea->sqld)\r
+ throw LogicExceptionImpl("Row::ColumnAlias", _("Variable index out of range."));\r
+\r
+ XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);\r
+ if (var->aliasname_length >= 31) var->aliasname_length = 31;\r
+ var->aliasname[var->aliasname_length] = '\0';\r
+ return var->aliasname;\r
+}\r
+\r
+const char* RowImpl::ColumnTable(int varnum)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::ColumnTable", _("The row is not initialized."));\r
+ if (varnum < 1 || varnum > mDescrArea->sqld)\r
+ throw LogicExceptionImpl("Row::ColumnTable", _("Variable index out of range."));\r
+\r
+ XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);\r
+ if (var->relname_length >= 31) var->relname_length = 31;\r
+ var->relname[var->relname_length] = '\0';\r
+ return var->relname;\r
+}\r
+\r
+IBPP::SDT RowImpl::ColumnType(int varnum)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::ColumnType", _("The row is not initialized."));\r
+ if (varnum < 1 || varnum > mDescrArea->sqld)\r
+ throw LogicExceptionImpl("Row::ColumnType", _("Variable index out of range."));\r
+\r
+ IBPP::SDT value;\r
+ XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);\r
+\r
+ switch (var->sqltype & ~1)\r
+ {\r
+ case SQL_TEXT : value = IBPP::sdString; break;\r
+ case SQL_VARYING : value = IBPP::sdString; break;\r
+ case SQL_SHORT : value = IBPP::sdSmallint; break;\r
+ case SQL_LONG : value = IBPP::sdInteger; break;\r
+ case SQL_INT64 : value = IBPP::sdLargeint; break;\r
+ case SQL_FLOAT : value = IBPP::sdFloat; break;\r
+ case SQL_DOUBLE : value = IBPP::sdDouble; break;\r
+ case SQL_TIMESTAMP : value = IBPP::sdTimestamp; break;\r
+ case SQL_TYPE_DATE : value = IBPP::sdDate; break;\r
+ case SQL_TYPE_TIME : value = IBPP::sdTime; break;\r
+ case SQL_BLOB : value = IBPP::sdBlob; break;\r
+ case SQL_ARRAY : value = IBPP::sdArray; break;\r
+ default : throw LogicExceptionImpl("Row::ColumnType",\r
+ _("Found an unknown sqltype !"));\r
+ }\r
+\r
+ return value;\r
+}\r
+\r
+int RowImpl::ColumnSubtype(int varnum)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::ColumnSubtype", _("The row is not initialized."));\r
+ if (varnum < 1 || varnum > mDescrArea->sqld)\r
+ throw LogicExceptionImpl("Row::ColumnSubtype", _("Variable index out of range."));\r
+\r
+ XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);\r
+ return (int)var->sqlsubtype;\r
+}\r
+\r
+int RowImpl::ColumnSize(int varnum)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::ColumnSize", _("The row is not initialized."));\r
+ if (varnum < 1 || varnum > mDescrArea->sqld)\r
+ throw LogicExceptionImpl("Row::ColumnSize", _("Variable index out of range."));\r
+\r
+ XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);\r
+ return var->sqllen;\r
+}\r
+\r
+int RowImpl::ColumnScale(int varnum)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::ColumnScale", _("The row is not initialized."));\r
+ if (varnum < 1 || varnum > mDescrArea->sqld)\r
+ throw LogicExceptionImpl("Row::ColumnScale", _("Variable index out of range."));\r
+\r
+ XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);\r
+ return -var->sqlscale;\r
+}\r
+\r
+bool RowImpl::ColumnUpdated(int varnum)\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::ColumnUpdated", _("The row is not initialized."));\r
+ if (varnum < 1 || varnum > mDescrArea->sqld)\r
+ throw LogicExceptionImpl("Row::ColumnUpdated", _("Variable index out of range."));\r
+\r
+ return mUpdated[varnum-1];\r
+}\r
+\r
+bool RowImpl::Updated()\r
+{\r
+ if (mDescrArea == 0)\r
+ throw LogicExceptionImpl("Row::ColumnUpdated", _("The row is not initialized."));\r
+\r
+ for (int i = 0; i < mDescrArea->sqld; i++)\r
+ if (mUpdated[i]) return true;\r
+ return false;\r
+}\r
+\r
+IBPP::Database RowImpl::DatabasePtr() const\r
+{\r
+ return mDatabase;\r
+}\r
+\r
+IBPP::Transaction RowImpl::TransactionPtr() const\r
+{\r
+ return mTransaction;\r
+}\r
+\r
+IBPP::IRow* RowImpl::Clone()\r
+{\r
+ // By definition the clone of an IBPP Row is a new row (so refcount=0).\r
+\r
+ RowImpl* clone = new RowImpl(*this);\r
+ return clone;\r
+}\r
+\r
+IBPP::IRow* RowImpl::AddRef()\r
+{\r
+ ASSERTION(mRefCount >= 0);\r
+ ++mRefCount;\r
+ return this;\r
+}\r
+\r
+void RowImpl::Release()\r
+{\r
+ // Release cannot throw, except in DEBUG builds on assertion\r
+ ASSERTION(mRefCount >= 0);\r
+ --mRefCount;\r
+ try { if (mRefCount <= 0) delete this; }\r
+ catch (...) { }\r
+}\r
+\r
+// (((((((( OBJECT INTERNAL METHODS ))))))))\r
+\r
+void RowImpl::SetValue(int varnum, IITYPE ivType, const void* value, int userlen)\r
+{\r
+ if (varnum < 1 || varnum > mDescrArea->sqld)\r
+ throw LogicExceptionImpl("RowImpl::SetValue", _("Variable index out of range."));\r
+ if (value == 0)\r
+ throw LogicExceptionImpl("RowImpl::SetValue", _("Unexpected null pointer detected."));\r
+\r
+ int16_t len;\r
+ XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);\r
+ switch (var->sqltype & ~1)\r
+ {\r
+ case SQL_TEXT :\r
+ if (ivType == ivString)\r
+ {\r
+ std::string* svalue = (std::string*)value;\r
+ len = (int16_t)svalue->length();\r
+ if (len > var->sqllen) len = var->sqllen;\r
+ strncpy(var->sqldata, svalue->c_str(), len);\r
+ while (len < var->sqllen) var->sqldata[len++] = ' ';\r
+ }\r
+ else if (ivType == ivByte)\r
+ {\r
+ if (userlen > var->sqllen) userlen = var->sqllen;\r
+ memcpy(var->sqldata, value, userlen);\r
+ while (userlen < var->sqllen) var->sqldata[userlen++] = ' ';\r
+ }\r
+ else if (ivType == ivDBKey)\r
+ {\r
+ IBPP::DBKey* key = (IBPP::DBKey*)value;\r
+ key->GetKey(var->sqldata, var->sqllen);\r
+ }\r
+ else if (ivType == ivBool)\r
+ {\r
+ var->sqldata[0] = *(bool*)value ? 'T' : 'F';\r
+ len = 1;\r
+ while (len < var->sqllen) var->sqldata[len++] = ' ';\r
+ }\r
+ else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ break;\r
+\r
+ case SQL_VARYING :\r
+ if (ivType == ivString)\r
+ {\r
+ std::string* svalue = (std::string*)value;\r
+ len = (int16_t)svalue->length();\r
+ if (len > var->sqllen) len = var->sqllen;\r
+ *(int16_t*)var->sqldata = (int16_t)len;\r
+ strncpy(var->sqldata+2, svalue->c_str(), len);\r
+ }\r
+ else if (ivType == ivByte)\r
+ {\r
+ if (userlen > var->sqllen) userlen = var->sqllen;\r
+ *(int16_t*)var->sqldata = (int16_t)userlen;\r
+ memcpy(var->sqldata+2, value, userlen);\r
+ }\r
+ else if (ivType == ivBool)\r
+ {\r
+ *(int16_t*)var->sqldata = (int16_t)1;\r
+ var->sqldata[2] = *(bool*)value ? 'T' : 'F';\r
+ }\r
+ else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ break;\r
+\r
+ case SQL_SHORT :\r
+ if (ivType == ivBool)\r
+ {\r
+ *(int16_t*)var->sqldata = int16_t(*(bool*)value ? 1 : 0);\r
+ }\r
+ else if (ivType == ivInt16)\r
+ {\r
+ *(int16_t*)var->sqldata = *(int16_t*)value;\r
+ }\r
+ else if (ivType == ivInt32)\r
+ {\r
+ if (*(int32_t*)value < consts::min16 || *(int32_t*)value > consts::max16)\r
+ throw LogicExceptionImpl("RowImpl::SetValue",\r
+ _("Out of range numeric conversion !"));\r
+ *(int16_t*)var->sqldata = (int16_t)*(int32_t*)value;\r
+ }\r
+ else if (ivType == ivInt64)\r
+ {\r
+ if (*(int64_t*)value < consts::min16 || *(int64_t*)value > consts::max16)\r
+ throw LogicExceptionImpl("RowImpl::SetValue",\r
+ _("Out of range numeric conversion !"));\r
+ *(int16_t*)var->sqldata = (int16_t)*(int64_t*)value;\r
+ }\r
+ else if (ivType == ivFloat)\r
+ {\r
+ // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
+ double multiplier = consts::dscales[-var->sqlscale];\r
+ *(int16_t*)var->sqldata =\r
+ (int16_t)floor(*(float*)value * multiplier + 0.5);\r
+ }\r
+ else if (ivType == ivDouble)\r
+ {\r
+ // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
+ double multiplier = consts::dscales[-var->sqlscale];\r
+ *(int16_t*)var->sqldata =\r
+ (int16_t)floor(*(double*)value * multiplier + 0.5);\r
+ }\r
+ else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ break;\r
+\r
+ case SQL_LONG :\r
+ if (ivType == ivBool)\r
+ {\r
+ *(ISC_LONG*)var->sqldata = *(bool*)value ? 1 : 0;\r
+ }\r
+ else if (ivType == ivInt16)\r
+ {\r
+ *(ISC_LONG*)var->sqldata = *(int16_t*)value;\r
+ }\r
+ else if (ivType == ivInt32)\r
+ {\r
+ *(ISC_LONG*)var->sqldata = *(ISC_LONG*)value;\r
+ }\r
+ else if (ivType == ivInt64)\r
+ {\r
+ if (*(int64_t*)value < consts::min32 || *(int64_t*)value > consts::max32)\r
+ throw LogicExceptionImpl("RowImpl::SetValue",\r
+ _("Out of range numeric conversion !"));\r
+ *(ISC_LONG*)var->sqldata = (ISC_LONG)*(int64_t*)value;\r
+ }\r
+ else if (ivType == ivFloat)\r
+ {\r
+ // This SQL_LONG is a NUMERIC(x,y), scale it !\r
+ double multiplier = consts::dscales[-var->sqlscale];\r
+ *(ISC_LONG*)var->sqldata =\r
+ (ISC_LONG)floor(*(float*)value * multiplier + 0.5);\r
+ }\r
+ else if (ivType == ivDouble)\r
+ {\r
+ // This SQL_LONG is a NUMERIC(x,y), scale it !\r
+ double multiplier = consts::dscales[-var->sqlscale];\r
+ *(ISC_LONG*)var->sqldata =\r
+ (ISC_LONG)floor(*(double*)value * multiplier + 0.5);\r
+ }\r
+ else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ break;\r
+\r
+ case SQL_INT64 :\r
+ if (ivType == ivBool)\r
+ {\r
+ *(int64_t*)var->sqldata = *(bool*)value ? 1 : 0;\r
+ }\r
+ else if (ivType == ivInt16)\r
+ {\r
+ *(int64_t*)var->sqldata = *(int16_t*)value;\r
+ }\r
+ else if (ivType == ivInt32)\r
+ {\r
+ *(int64_t*)var->sqldata = *(int32_t*)value;\r
+ }\r
+ else if (ivType == ivInt64)\r
+ {\r
+ *(int64_t*)var->sqldata = *(int64_t*)value;\r
+ }\r
+ else if (ivType == ivFloat)\r
+ {\r
+ // This SQL_INT64 is a NUMERIC(x,y), scale it !\r
+ double multiplier = consts::dscales[-var->sqlscale];\r
+ *(int64_t*)var->sqldata =\r
+ (int64_t)floor(*(float*)value * multiplier + 0.5);\r
+ }\r
+ else if (ivType == ivDouble)\r
+ {\r
+ // This SQL_INT64 is a NUMERIC(x,y), scale it !\r
+ double multiplier = consts::dscales[-var->sqlscale];\r
+ *(int64_t*)var->sqldata =\r
+ (int64_t)floor(*(double*)value * multiplier + 0.5);\r
+ }\r
+ else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ break;\r
+\r
+ case SQL_FLOAT :\r
+ if (ivType != ivFloat || var->sqlscale != 0)\r
+ throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ *(float*)var->sqldata = *(float*)value;\r
+ break;\r
+\r
+ case SQL_DOUBLE :\r
+ if (ivType != ivDouble)\r
+ throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ if (var->sqlscale != 0)\r
+ {\r
+ // Round to scale of NUMERIC(x,y)\r
+ double multiplier = consts::dscales[-var->sqlscale];\r
+ *(double*)var->sqldata =\r
+ floor(*(double*)value * multiplier + 0.5) / multiplier;\r
+ }\r
+ else *(double*)var->sqldata = *(double*)value;\r
+ break;\r
+\r
+ case SQL_TIMESTAMP :\r
+ if (ivType != ivTimestamp)\r
+ throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ encodeTimestamp(*(ISC_TIMESTAMP*)var->sqldata, *(IBPP::Timestamp*)value);\r
+ break;\r
+\r
+ case SQL_TYPE_DATE :\r
+ if (ivType != ivDate)\r
+ throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ encodeDate(*(ISC_DATE*)var->sqldata, *(IBPP::Date*)value);\r
+ break;\r
+\r
+ case SQL_TYPE_TIME :\r
+ if (ivType != ivTime)\r
+ throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ encodeTime(*(ISC_TIME*)var->sqldata, *(IBPP::Time*)value);\r
+ break;\r
+\r
+ case SQL_BLOB :\r
+ if (ivType == ivBlob)\r
+ {\r
+ BlobImpl* blob = (BlobImpl*)value;\r
+ blob->GetId((ISC_QUAD*)var->sqldata);\r
+ }\r
+ else if (ivType == ivString)\r
+ {\r
+ BlobImpl blob(mDatabase, mTransaction);\r
+ blob.Save(*(std::string*)value);\r
+ blob.GetId((ISC_QUAD*)var->sqldata);\r
+ }\r
+ else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ break;\r
+\r
+ case SQL_ARRAY :\r
+ if (ivType != ivArray)\r
+ throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ {\r
+ ArrayImpl* array = (ArrayImpl*)value;\r
+ array->GetId((ISC_QUAD*)var->sqldata);\r
+ // When an array has been affected to a column, we want to reset\r
+ // its ID. This way, the next WriteFrom() on the same Array object\r
+ // will allocate a new ID. This protects against storing the same\r
+ // array ID in multiple columns or rows.\r
+ array->ResetId();\r
+ }\r
+ break;\r
+\r
+ default : throw LogicExceptionImpl("RowImpl::SetValue",\r
+ _("The field uses an unsupported SQL type !"));\r
+ }\r
+\r
+ if (var->sqltype & 1) *var->sqlind = 0; // Remove the 0 flag\r
+}\r
+\r
+void* RowImpl::GetValue(int varnum, IITYPE ivType, void* retvalue)\r
+{\r
+ if (varnum < 1 || varnum > mDescrArea->sqld)\r
+ throw LogicExceptionImpl("RowImpl::GetValue", _("Variable index out of range."));\r
+\r
+ void* value;\r
+ int len;\r
+ XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);\r
+\r
+ // When there is no value (SQL NULL)\r
+ if ((var->sqltype & 1) && *(var->sqlind) != 0) return 0;\r
+\r
+ switch (var->sqltype & ~1)\r
+ {\r
+ case SQL_TEXT :\r
+ if (ivType == ivString)\r
+ {\r
+ // In case of ivString, 'void* retvalue' points to a std::string where we\r
+ // will directly store the data.\r
+ std::string* str = (std::string*)retvalue;\r
+ str->erase();\r
+ str->append(var->sqldata, var->sqllen);\r
+ value = retvalue; // value != 0 means 'not null'\r
+ }\r
+ else if (ivType == ivByte)\r
+ {\r
+ // In case of ivByte, void* retvalue points to an int where we\r
+ // will store the len of the available data\r
+ if (retvalue != 0) *(int*)retvalue = var->sqllen;\r
+ value = var->sqldata;\r
+ }\r
+ else if (ivType == ivDBKey)\r
+ {\r
+ IBPP::DBKey* key = (IBPP::DBKey*)retvalue;\r
+ key->SetKey(var->sqldata, var->sqllen);\r
+ value = retvalue;\r
+ }\r
+ else if (ivType == ivBool)\r
+ {\r
+ mBools[varnum-1] = 0;\r
+ if (var->sqllen >= 1)\r
+ {\r
+ char c = var->sqldata[0];\r
+ if (c == 't' || c == 'T' || c == 'y' || c == 'Y' || c == '1')\r
+ mBools[varnum-1] = 1;\r
+ }\r
+ value = &mBools[varnum-1];\r
+ }\r
+ else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ break;\r
+\r
+ case SQL_VARYING :\r
+ if (ivType == ivString)\r
+ {\r
+ // In case of ivString, 'void* retvalue' points to a std::string where we\r
+ // will directly store the data.\r
+ std::string* str = (std::string*)retvalue;\r
+ str->erase();\r
+ str->append(var->sqldata+2, (int32_t)*(int16_t*)var->sqldata);\r
+ value = retvalue;\r
+ }\r
+ else if (ivType == ivByte)\r
+ {\r
+ // In case of ivByte, void* retvalue points to an int where we\r
+ // will store the len of the available data\r
+ if (retvalue != 0) *(int*)retvalue = (int)*(int16_t*)var->sqldata;\r
+ value = var->sqldata+2;\r
+ }\r
+ else if (ivType == ivBool)\r
+ {\r
+ mBools[varnum-1] = 0;\r
+ len = *(int16_t*)var->sqldata;\r
+ if (len >= 1)\r
+ {\r
+ char c = var->sqldata[2];\r
+ if (c == 't' || c == 'T' || c == 'y' || c == 'Y' || c == '1')\r
+ mBools[varnum-1] = 1;\r
+ }\r
+ value = &mBools[varnum-1];\r
+ }\r
+ else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ break;\r
+\r
+ case SQL_SHORT :\r
+ if (ivType == ivInt16)\r
+ {\r
+ value = var->sqldata;\r
+ }\r
+ else if (ivType == ivBool)\r
+ {\r
+ if (*(int16_t*)var->sqldata == 0) mBools[varnum-1] = 0;\r
+ else mBools[varnum-1] = 1;\r
+ value = &mBools[varnum-1];\r
+ }\r
+ else if (ivType == ivInt32)\r
+ {\r
+ mInt32s[varnum-1] = *(int16_t*)var->sqldata;\r
+ value = &mInt32s[varnum-1];\r
+ }\r
+ else if (ivType == ivInt64)\r
+ {\r
+ mInt64s[varnum-1] = *(int16_t*)var->sqldata;\r
+ value = &mInt64s[varnum-1];\r
+ }\r
+ else if (ivType == ivFloat)\r
+ {\r
+ // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
+ double divisor = consts::dscales[-var->sqlscale];\r
+ mFloats[varnum-1] = (float)(*(int16_t*)var->sqldata / divisor);\r
+\r
+ value = &mFloats[varnum-1];\r
+ }\r
+ else if (ivType == ivDouble)\r
+ {\r
+ // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
+ double divisor = consts::dscales[-var->sqlscale];\r
+ mNumerics[varnum-1] = *(int16_t*)var->sqldata / divisor;\r
+ value = &mNumerics[varnum-1];\r
+ }\r
+ else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ break;\r
+\r
+ case SQL_LONG :\r
+ if (ivType == ivInt32)\r
+ {\r
+ value = var->sqldata;\r
+ }\r
+ else if (ivType == ivBool)\r
+ {\r
+ if (*(int32_t*)var->sqldata == 0) mBools[varnum-1] = 0;\r
+ else mBools[varnum-1] = 1;\r
+ value = &mBools[varnum-1];\r
+ }\r
+ else if (ivType == ivInt16)\r
+ {\r
+ int32_t tmp = *(int32_t*)var->sqldata;\r
+ if (tmp < consts::min16 || tmp > consts::max16)\r
+ throw LogicExceptionImpl("RowImpl::GetValue",\r
+ _("Out of range numeric conversion !"));\r
+ mInt16s[varnum-1] = (int16_t)tmp;\r
+ value = &mInt16s[varnum-1];\r
+ }\r
+ else if (ivType == ivInt64)\r
+ {\r
+ mInt64s[varnum-1] = *(int32_t*)var->sqldata;\r
+ value = &mInt64s[varnum-1];\r
+ }\r
+ else if (ivType == ivFloat)\r
+ {\r
+ // This SQL_LONG is a NUMERIC(x,y), scale it !\r
+ double divisor = consts::dscales[-var->sqlscale];\r
+ mFloats[varnum-1] = (float)(*(int32_t*)var->sqldata / divisor);\r
+ value = &mFloats[varnum-1];\r
+ }\r
+ else if (ivType == ivDouble)\r
+ {\r
+ // This SQL_LONG is a NUMERIC(x,y), scale it !\r
+ double divisor = consts::dscales[-var->sqlscale];\r
+ mNumerics[varnum-1] = *(int32_t*)var->sqldata / divisor;\r
+ value = &mNumerics[varnum-1];\r
+ }\r
+ else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ break;\r
+\r
+ case SQL_INT64 :\r
+ if (ivType == ivInt64)\r
+ {\r
+ value = var->sqldata;\r
+ }\r
+ else if (ivType == ivBool)\r
+ {\r
+ if (*(int64_t*)var->sqldata == 0) mBools[varnum-1] = 0;\r
+ else mBools[varnum-1] = 1;\r
+ value = &mBools[varnum-1];\r
+ }\r
+ else if (ivType == ivInt16)\r
+ {\r
+ int64_t tmp = *(int64_t*)var->sqldata;\r
+ if (tmp < consts::min16 || tmp > consts::max16)\r
+ throw LogicExceptionImpl("RowImpl::GetValue",\r
+ _("Out of range numeric conversion !"));\r
+ mInt16s[varnum-1] = (int16_t)tmp;\r
+ value = &mInt16s[varnum-1];\r
+ }\r
+ else if (ivType == ivInt32)\r
+ {\r
+ int64_t tmp = *(int64_t*)var->sqldata;\r
+ if (tmp < consts::min32 || tmp > consts::max32)\r
+ throw LogicExceptionImpl("RowImpl::GetValue",\r
+ _("Out of range numeric conversion !"));\r
+ mInt32s[varnum-1] = (int32_t)tmp;\r
+ value = &mInt32s[varnum-1];\r
+ }\r
+ else if (ivType == ivFloat)\r
+ {\r
+ // This SQL_INT64 is a NUMERIC(x,y), scale it !\r
+ double divisor = consts::dscales[-var->sqlscale];\r
+ mFloats[varnum-1] = (float)(*(int64_t*)var->sqldata / divisor);\r
+ value = &mFloats[varnum-1];\r
+ }\r
+ else if (ivType == ivDouble)\r
+ {\r
+ // This SQL_INT64 is a NUMERIC(x,y), scale it !\r
+ double divisor = consts::dscales[-var->sqlscale];\r
+ mNumerics[varnum-1] = *(int64_t*)var->sqldata / divisor;\r
+ value = &mNumerics[varnum-1];\r
+ }\r
+ else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ break;\r
+\r
+ case SQL_FLOAT :\r
+ if (ivType != ivFloat)\r
+ throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ value = var->sqldata;\r
+ break;\r
+\r
+ case SQL_DOUBLE :\r
+ if (ivType != ivDouble)\r
+ throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ if (var->sqlscale != 0)\r
+ {\r
+ // Round to scale y of NUMERIC(x,y)\r
+ double multiplier = consts::dscales[-var->sqlscale];\r
+ mNumerics[varnum-1] =\r
+ floor(*(double*)var->sqldata * multiplier + 0.5) / multiplier;\r
+ value = &mNumerics[varnum-1];\r
+ }\r
+ else value = var->sqldata;\r
+ break;\r
+\r
+ case SQL_TIMESTAMP :\r
+ if (ivType != ivTimestamp)\r
+ throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ decodeTimestamp(*(IBPP::Timestamp*)retvalue, *(ISC_TIMESTAMP*)var->sqldata);\r
+ value = retvalue;\r
+ break;\r
+\r
+ case SQL_TYPE_DATE :\r
+ if (ivType != ivDate)\r
+ throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ decodeDate(*(IBPP::Date*)retvalue, *(ISC_DATE*)var->sqldata);\r
+ value = retvalue;\r
+ break;\r
+\r
+ case SQL_TYPE_TIME :\r
+ if (ivType != ivTime)\r
+ throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ decodeTime(*(IBPP::Time*)retvalue, *(ISC_TIME*)var->sqldata);\r
+ value = retvalue;\r
+ break;\r
+\r
+ case SQL_BLOB :\r
+ if (ivType == ivBlob)\r
+ {\r
+ BlobImpl* blob = (BlobImpl*)retvalue;\r
+ blob->SetId((ISC_QUAD*)var->sqldata);\r
+ value = retvalue;\r
+ }\r
+ else if (ivType == ivString)\r
+ {\r
+ BlobImpl blob(mDatabase, mTransaction);\r
+ blob.SetId((ISC_QUAD*)var->sqldata);\r
+ std::string* str = (std::string*)retvalue;\r
+ blob.Load(*str);\r
+ value = retvalue;\r
+ }\r
+ else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ break;\r
+ \r
+ case SQL_ARRAY :\r
+ if (ivType != ivArray)\r
+ throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,\r
+ _("Incompatible types."));\r
+ {\r
+ ArrayImpl* array = (ArrayImpl*)retvalue;\r
+ array->SetId((ISC_QUAD*)var->sqldata);\r
+ value = retvalue;\r
+ }\r
+ break;\r
+\r
+ default : throw LogicExceptionImpl("RowImpl::GetValue",\r
+ _("Found an unknown sqltype !"));\r
+ }\r
+\r
+ return value;\r
+}\r
+\r
+void RowImpl::Free()\r
+{\r
+ if (mDescrArea != 0)\r
+ {\r
+ for (int i = 0; i < mDescrArea->sqln; i++)\r
+ {\r
+ XSQLVAR* var = &(mDescrArea->sqlvar[i]);\r
+ if (var->sqldata != 0)\r
+ {\r
+ switch (var->sqltype & ~1)\r
+ {\r
+ case SQL_ARRAY :\r
+ case SQL_BLOB : delete (ISC_QUAD*) var->sqldata; break;\r
+ case SQL_TIMESTAMP :delete (ISC_TIMESTAMP*) var->sqldata; break;\r
+ case SQL_TYPE_TIME :delete (ISC_TIME*) var->sqldata; break;\r
+ case SQL_TYPE_DATE :delete (ISC_DATE*) var->sqldata; break;\r
+ case SQL_TEXT :\r
+ case SQL_VARYING : delete [] var->sqldata; break;\r
+ case SQL_SHORT : delete (int16_t*) var->sqldata; break;\r
+ case SQL_LONG : delete (int32_t*) var->sqldata; break;\r
+ case SQL_INT64 : delete (int64_t*) var->sqldata; break;\r
+ case SQL_FLOAT : delete (float*) var->sqldata; break;\r
+ case SQL_DOUBLE : delete (double*) var->sqldata; break;\r
+ default : throw LogicExceptionImpl("RowImpl::Free",\r
+ _("Found an unknown sqltype !"));\r
+ }\r
+ }\r
+ if (var->sqlind != 0) delete var->sqlind;\r
+ }\r
+ delete [] (char*)mDescrArea;\r
+ mDescrArea = 0;\r
+ }\r
+\r
+ mNumerics.clear();\r
+ mFloats.clear();\r
+ mInt64s.clear();\r
+ mInt32s.clear();\r
+ mInt16s.clear();\r
+ mBools.clear();\r
+ mStrings.clear();\r
+ mUpdated.clear();\r
+\r
+ mDialect = 0;\r
+ mDatabase = 0;\r
+ mTransaction = 0;\r
+}\r
+\r
+void RowImpl::Resize(int n)\r
+{\r
+ const int size = XSQLDA_LENGTH(n);\r
+\r
+ Free();\r
+ mDescrArea = (XSQLDA*) new char[size];\r
+\r
+ memset(mDescrArea, 0, size);\r
+ mNumerics.resize(n);\r
+ mFloats.resize(n);\r
+ mInt64s.resize(n);\r
+ mInt32s.resize(n);\r
+ mInt16s.resize(n);\r
+ mBools.resize(n);\r
+ mStrings.resize(n);\r
+ mUpdated.resize(n);\r
+ for (int i = 0; i < n; i++)\r
+ {\r
+ mNumerics[i] = 0.0;\r
+ mFloats[i] = 0.0;\r
+ mInt64s[i] = 0;\r
+ mInt32s[i] = 0;\r
+ mInt16s[i] = 0;\r
+ mBools[i] = 0;\r
+ mStrings[i].erase();\r
+ mUpdated[i] = false;\r
+ }\r
+\r
+ mDescrArea->version = SQLDA_VERSION1;\r
+ mDescrArea->sqln = (int16_t)n;\r
+}\r
+\r
+void RowImpl::AllocVariables()\r
+{\r
+ int i;\r
+ for (i = 0; i < mDescrArea->sqld; i++)\r
+ {\r
+ XSQLVAR* var = &(mDescrArea->sqlvar[i]);\r
+ switch (var->sqltype & ~1)\r
+ {\r
+ case SQL_ARRAY :\r
+ case SQL_BLOB : var->sqldata = (char*) new ISC_QUAD;\r
+ memset(var->sqldata, 0, sizeof(ISC_QUAD));\r
+ break;\r
+ case SQL_TIMESTAMP :var->sqldata = (char*) new ISC_TIMESTAMP;\r
+ memset(var->sqldata, 0, sizeof(ISC_TIMESTAMP));\r
+ break;\r
+ case SQL_TYPE_TIME :var->sqldata = (char*) new ISC_TIME;\r
+ memset(var->sqldata, 0, sizeof(ISC_TIME));\r
+ break;\r
+ case SQL_TYPE_DATE :var->sqldata = (char*) new ISC_DATE;\r
+ memset(var->sqldata, 0, sizeof(ISC_DATE));\r
+ break;\r
+ case SQL_TEXT : var->sqldata = new char[var->sqllen+1];\r
+ memset(var->sqldata, ' ', var->sqllen);\r
+ var->sqldata[var->sqllen] = '\0';\r
+ break;\r
+ case SQL_VARYING : var->sqldata = new char[var->sqllen+3];\r
+ memset(var->sqldata, 0, 2);\r
+ memset(var->sqldata+2, ' ', var->sqllen);\r
+ var->sqldata[var->sqllen+2] = '\0';\r
+ break;\r
+ case SQL_SHORT : var->sqldata = (char*) new int16_t(0); break;\r
+ case SQL_LONG : var->sqldata = (char*) new int32_t(0); break;\r
+ case SQL_INT64 : var->sqldata = (char*) new int64_t(0); break;\r
+ case SQL_FLOAT : var->sqldata = (char*) new float(0.0); break;\r
+ case SQL_DOUBLE : var->sqldata = (char*) new double(0.0); break;\r
+ default : throw LogicExceptionImpl("RowImpl::AllocVariables",\r
+ _("Found an unknown sqltype !"));\r
+ }\r
+ if (var->sqltype & 1) var->sqlind = new short(-1); // 0 indicator\r
+ }\r
+}\r
+\r
+bool RowImpl::MissingValues()\r
+{\r
+ for (int i = 0; i < mDescrArea->sqld; i++)\r
+ if (! mUpdated[i]) return true;\r
+ return false;\r
+}\r
+\r
+RowImpl& RowImpl::operator=(const RowImpl& copied)\r
+{\r
+ Free();\r
+\r
+ const int n = copied.mDescrArea->sqln;\r
+ const int size = XSQLDA_LENGTH(n);\r
+\r
+ // Initial brute copy\r
+ mDescrArea = (XSQLDA*) new char[size];\r
+ memcpy(mDescrArea, copied.mDescrArea, size);\r
+\r
+ // Copy of the columns data\r
+ for (int i = 0; i < mDescrArea->sqld; i++)\r
+ {\r
+ XSQLVAR* var = &(mDescrArea->sqlvar[i]);\r
+ XSQLVAR* org = &(copied.mDescrArea->sqlvar[i]);\r
+ switch (var->sqltype & ~1)\r
+ {\r
+ case SQL_ARRAY :\r
+ case SQL_BLOB : var->sqldata = (char*) new ISC_QUAD;\r
+ memcpy(var->sqldata, org->sqldata, sizeof(ISC_QUAD));\r
+ break;\r
+ case SQL_TIMESTAMP :var->sqldata = (char*) new ISC_TIMESTAMP;\r
+ memcpy(var->sqldata, org->sqldata, sizeof(ISC_TIMESTAMP));\r
+ break;\r
+ case SQL_TYPE_TIME :var->sqldata = (char*) new ISC_TIME;\r
+ memcpy(var->sqldata, org->sqldata, sizeof(ISC_TIME));\r
+ break;\r
+ case SQL_TYPE_DATE :var->sqldata = (char*) new ISC_DATE;\r
+ memcpy(var->sqldata, org->sqldata, sizeof(ISC_DATE));\r
+ break;\r
+ case SQL_TEXT : var->sqldata = new char[var->sqllen+1];\r
+ memcpy(var->sqldata, org->sqldata, var->sqllen+1);\r
+ break;\r
+ case SQL_VARYING : var->sqldata = new char[var->sqllen+3];\r
+ memcpy(var->sqldata, org->sqldata, var->sqllen+3);\r
+ break;\r
+ case SQL_SHORT : var->sqldata = (char*) new int16_t(*(int16_t*)org->sqldata); break;\r
+ case SQL_LONG : var->sqldata = (char*) new int32_t(*(int32_t*)org->sqldata); break;\r
+ case SQL_INT64 : var->sqldata = (char*) new int64_t(*(int64_t*)org->sqldata); break;\r
+ case SQL_FLOAT : var->sqldata = (char*) new float(*(float*)org->sqldata); break;\r
+ case SQL_DOUBLE : var->sqldata = (char*) new double(*(double*)org->sqldata); break;\r
+ default : throw LogicExceptionImpl("RowImpl::Ctor",\r
+ _("Found an unknown sqltype !"));\r
+ }\r
+ if (var->sqltype & 1) var->sqlind = new short(*org->sqlind); // 0 indicator\r
+ }\r
+\r
+ // Pointers init, real data copy\r
+ mNumerics = copied.mNumerics;\r
+ mFloats = copied.mFloats;\r
+ mInt64s = copied.mInt64s;\r
+ mInt32s = copied.mInt32s;\r
+ mInt16s = copied.mInt16s;\r
+ mBools = copied.mBools;\r
+ mStrings = copied.mStrings;\r
+\r
+ mDialect = copied.mDialect;\r
+ mDatabase = copied.mDatabase;\r
+ mTransaction = copied.mTransaction;\r
+ \r
+ return *this;\r
+}\r
+\r
+RowImpl::RowImpl(const RowImpl& copied)\r
+ : IBPP::IRow(), mRefCount(0), mDescrArea(0)\r
+{\r
+ // mRefCount and mDescrArea are set to 0 before using the assignment operator\r
+ *this = copied; // The assignment operator does the real copy\r
+}\r
+\r
+RowImpl::RowImpl(int dialect, int n, DatabaseImpl* db, TransactionImpl* tr)\r
+ : mRefCount(0), mDescrArea(0)\r
+{\r
+ Resize(n);\r
+ mDialect = dialect;\r
+ mDatabase = db;\r
+ mTransaction = tr;\r
+}\r
+\r
+RowImpl::~RowImpl()\r
+{\r
+ try { Free(); }\r
+ catch (...) { }\r
+}\r
+\r
+//\r
+// EOF\r
+//\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: service.cpp,v 1.1 2007/05/05 17:00:43 faust Exp $\r
+// Subject : IBPP, Service class implementation\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning(disable: 4786 4996)\r
+#ifndef _DEBUG\r
+#pragma warning(disable: 4702)\r
+#endif\r
+#endif\r
+\r
+#include "_ibpp.h"\r
+\r
+#ifdef HAS_HDRSTOP\r
+#pragma hdrstop\r
+#endif\r
+\r
+using namespace ibpp_internals;\r
+\r
+#ifdef IBPP_UNIX\r
+#include <unistd.h>\r
+#define Sleep(x) usleep(x)\r
+#endif\r
+\r
+// (((((((( OBJECT INTERFACE IMPLEMENTATION ))))))))\r
+\r
+void ServiceImpl::Connect()\r
+{\r
+ if (mHandle != 0) return; // Already connected\r
+ \r
+ if (gds.Call()->mGDSVersion < 60)\r
+ throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
+ if (mUserName.empty())\r
+ throw LogicExceptionImpl("Service::Connect", _("Unspecified user name."));\r
+ if (mUserPassword.empty())\r
+ throw LogicExceptionImpl("Service::Connect", _("Unspecified user password."));\r
+\r
+ // Attach to the Service Manager\r
+ IBS status;\r
+ SPB spb;\r
+ std::string connect;\r
+\r
+ // Build a SPB based on the properties\r
+ spb.Insert(isc_spb_version);\r
+ spb.Insert(isc_spb_current_version);\r
+ spb.InsertString(isc_spb_user_name, 1, mUserName.c_str());\r
+ spb.InsertString(isc_spb_password, 1, mUserPassword.c_str());\r
+\r
+ if (! mServerName.empty())\r
+ {\r
+ connect = mServerName;\r
+ connect += ":";\r
+ }\r
+\r
+ connect += "service_mgr";\r
+\r
+ (*gds.Call()->m_service_attach)(status.Self(), (short)connect.size(), (char*)connect.c_str(),\r
+ &mHandle, spb.Size(), spb.Self());\r
+ if (status.Errors())\r
+ {\r
+ mHandle = 0; // Should be, but better be sure...\r
+ throw SQLExceptionImpl(status, "Service::Connect", _("isc_service_attach failed"));\r
+ }\r
+}\r
+\r
+void ServiceImpl::Disconnect()\r
+{\r
+ if (mHandle == 0) return; // Already disconnected\r
+ \r
+ if (gds.Call()->mGDSVersion < 60)\r
+ throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
+\r
+ IBS status;\r
+\r
+ // Detach from the service manager\r
+ (*gds.Call()->m_service_detach)(status.Self(), &mHandle);\r
+\r
+ // Set mHandle to 0 now, just in case we need to throw, because Disconnect()\r
+ // is called from Service destructor and we want to maintain a coherent state.\r
+ mHandle = 0;\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::Disconnect", _("isc_service_detach failed"));\r
+}\r
+\r
+void ServiceImpl::GetVersion(std::string& version)\r
+{\r
+ // Based on a patch provided by Torsten Martinsen (SourceForge 'bullestock')\r
+\r
+ if (gds.Call()->mGDSVersion < 60)\r
+ throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Service::GetVersion", _("Service is not connected."));\r
+\r
+ IBS status;\r
+ SPB spb;\r
+ RB result(250);\r
+\r
+ spb.Insert(isc_info_svc_server_version);\r
+\r
+ (*gds.Call()->m_service_query)(status.Self(), &mHandle, 0, 0, 0, spb.Size(), spb.Self(),\r
+ result.Size(), result.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::GetVersion", _("isc_service_query failed"));\r
+\r
+ result.GetString(isc_info_svc_server_version, version);\r
+}\r
+\r
+void ServiceImpl::AddUser(const IBPP::User& user)\r
+{\r
+ if (gds.Call()->mGDSVersion >= 60 && mHandle == 0)\r
+ throw LogicExceptionImpl("Service::AddUser", _("Service is not connected."));\r
+ if (user.username.empty())\r
+ throw LogicExceptionImpl("Service::AddUser", _("Username required."));\r
+ if (user.password.empty())\r
+ throw LogicExceptionImpl("Service::AddUser", _("Password required."));\r
+\r
+ IBS status;\r
+ SPB spb;\r
+ spb.Insert(isc_action_svc_add_user);\r
+ spb.InsertString(isc_spb_sec_username, 2, user.username.c_str());\r
+ spb.InsertString(isc_spb_sec_password, 2, user.password.c_str());\r
+ if (! user.firstname.empty())\r
+ spb.InsertString(isc_spb_sec_firstname, 2, user.firstname.c_str());\r
+ if (! user.middlename.empty())\r
+ spb.InsertString(isc_spb_sec_middlename, 2, user.middlename.c_str());\r
+ if (! user.lastname.empty())\r
+ spb.InsertString(isc_spb_sec_lastname, 2, user.lastname.c_str());\r
+ if (user.userid != 0)\r
+ spb.InsertQuad(isc_spb_sec_userid, (int32_t)user.userid);\r
+ if (user.groupid != 0)\r
+ spb.InsertQuad(isc_spb_sec_groupid, (int32_t)user.groupid);\r
+\r
+ (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::AddUser", _("isc_service_start failed"));\r
+\r
+ Wait();\r
+}\r
+\r
+void ServiceImpl::ModifyUser(const IBPP::User& user)\r
+{\r
+ if (gds.Call()->mGDSVersion >= 60 && mHandle == 0)\r
+ throw LogicExceptionImpl("Service::ModifyUser", _("Service is not connected."));\r
+ if (user.username.empty())\r
+ throw LogicExceptionImpl("Service::ModifyUser", _("Username required."));\r
+\r
+ IBS status;\r
+ SPB spb;\r
+\r
+ spb.Insert(isc_action_svc_modify_user);\r
+ spb.InsertString(isc_spb_sec_username, 2, user.username.c_str());\r
+ if (! user.password.empty())\r
+ spb.InsertString(isc_spb_sec_password, 2, user.password.c_str());\r
+ if (! user.firstname.empty())\r
+ spb.InsertString(isc_spb_sec_firstname, 2, user.firstname.c_str());\r
+ if (! user.middlename.empty())\r
+ spb.InsertString(isc_spb_sec_middlename, 2, user.middlename.c_str());\r
+ if (! user.lastname.empty())\r
+ spb.InsertString(isc_spb_sec_lastname, 2, user.lastname.c_str());\r
+ if (user.userid != 0)\r
+ spb.InsertQuad(isc_spb_sec_userid, (int32_t)user.userid);\r
+ if (user.groupid != 0)\r
+ spb.InsertQuad(isc_spb_sec_groupid, (int32_t)user.groupid);\r
+\r
+ (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::ModifyUser", _("isc_service_start failed"));\r
+\r
+ Wait();\r
+}\r
+\r
+void ServiceImpl::RemoveUser(const std::string& username)\r
+{\r
+\r
+ if (gds.Call()->mGDSVersion >= 60 && mHandle == 0)\r
+ throw LogicExceptionImpl("Service::RemoveUser", _("Service is not connected."));\r
+ if (username.empty())\r
+ throw LogicExceptionImpl("Service::RemoveUser", _("Username required."));\r
+\r
+ IBS status;\r
+ SPB spb;\r
+\r
+ spb.Insert(isc_action_svc_delete_user);\r
+ spb.InsertString(isc_spb_sec_username, 2, username.c_str());\r
+\r
+ (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::RemoveUser", _("isc_service_start failed"));\r
+\r
+ Wait();\r
+}\r
+\r
+void ServiceImpl::GetUser(IBPP::User& user)\r
+{\r
+ if (gds.Call()->mGDSVersion < 60)\r
+ throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Service::GetUser", _("Service is not connected."));\r
+ if (user.username.empty())\r
+ throw LogicExceptionImpl("Service::GetUser", _("Username required."));\r
+\r
+ SPB spb;\r
+ spb.Insert(isc_action_svc_display_user);\r
+ spb.InsertString(isc_spb_sec_username, 2, user.username.c_str());\r
+\r
+ IBS status;\r
+ (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::GetUser", _("isc_service_start failed"));\r
+\r
+ RB result(8000);\r
+ char request[] = {isc_info_svc_get_users};\r
+ status.Reset();\r
+ (*gds.Call()->m_service_query)(status.Self(), &mHandle, 0, 0, 0,\r
+ sizeof(request), request, result.Size(), result.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::GetUser", _("isc_service_query failed"));\r
+\r
+ char* p = result.Self();\r
+ if (*p != isc_info_svc_get_users)\r
+ throw SQLExceptionImpl(status, "Service::GetUser", _("isc_service_query returned unexpected answer"));\r
+\r
+ p += 3; // Skips the 'isc_info_svc_get_users' and its total length\r
+ user.clear();\r
+ while (*p != isc_info_end)\r
+ {\r
+ if (*p == isc_spb_sec_userid)\r
+ {\r
+ user.userid = (uint32_t)(*gds.Call()->m_vax_integer)(p+1, 4);\r
+ p += 5;\r
+ }\r
+ else if (*p == isc_spb_sec_groupid)\r
+ {\r
+ user.groupid = (uint32_t)(*gds.Call()->m_vax_integer)(p+1, 4);\r
+ p += 5;\r
+ }\r
+ else\r
+ {\r
+ unsigned short len = (unsigned short)(*gds.Call()->m_vax_integer)(p+1, 2);\r
+ switch (*p)\r
+ {\r
+ case isc_spb_sec_username :\r
+ // For each user, this is the first element returned\r
+ if (len != 0) user.username.assign(p+3, len);\r
+ break;\r
+ case isc_spb_sec_password :\r
+ if (len != 0) user.password.assign(p+3, len);\r
+ break;\r
+ case isc_spb_sec_firstname :\r
+ if (len != 0) user.firstname.assign(p+3, len);\r
+ break;\r
+ case isc_spb_sec_middlename :\r
+ if (len != 0) user.middlename.assign(p+3, len);\r
+ break;\r
+ case isc_spb_sec_lastname :\r
+ if (len != 0) user.lastname.assign(p+3, len);\r
+ break;\r
+ }\r
+ p += (3 + len);\r
+ }\r
+ }\r
+}\r
+\r
+void ServiceImpl::GetUsers(std::vector<IBPP::User>& users)\r
+{\r
+ if (gds.Call()->mGDSVersion < 60)\r
+ throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Service::GetUsers", _("Service is not connected."));\r
+\r
+ SPB spb;\r
+ spb.Insert(isc_action_svc_display_user);\r
+\r
+ IBS status;\r
+ (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::GetUsers", _("isc_service_start failed"));\r
+\r
+ RB result(8000);\r
+ char request[] = {isc_info_svc_get_users};\r
+ status.Reset();\r
+ (*gds.Call()->m_service_query)(status.Self(), &mHandle, 0, 0, 0,\r
+ sizeof(request), request, result.Size(), result.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::GetUsers", _("isc_service_query failed"));\r
+\r
+ users.clear();\r
+ char* p = result.Self();\r
+ if (*p != isc_info_svc_get_users)\r
+ throw SQLExceptionImpl(status, "Service::GetUsers", _("isc_service_query returned unexpected answer"));\r
+\r
+ p += 3; // Skips the 'isc_info_svc_get_users' and its total length\r
+ IBPP::User user;\r
+ while (*p != isc_info_end)\r
+ {\r
+ if (*p == isc_spb_sec_userid)\r
+ {\r
+ user.userid = (uint32_t)(*gds.Call()->m_vax_integer)(p+1, 4);\r
+ p += 5;\r
+ }\r
+ else if (*p == isc_spb_sec_groupid)\r
+ {\r
+ user.groupid = (uint32_t)(*gds.Call()->m_vax_integer)(p+1, 4);\r
+ p += 5;\r
+ }\r
+ else\r
+ {\r
+ unsigned short len = (unsigned short)(*gds.Call()->m_vax_integer)(p+1, 2);\r
+ switch (*p)\r
+ {\r
+ case isc_spb_sec_username :\r
+ // For each user, this is the first element returned\r
+ if (! user.username.empty()) users.push_back(user); // Flush previous user\r
+ user.clear();\r
+ if (len != 0) user.username.assign(p+3, len);\r
+ break;\r
+ case isc_spb_sec_password :\r
+ if (len != 0) user.password.assign(p+3, len);\r
+ break;\r
+ case isc_spb_sec_firstname :\r
+ if (len != 0) user.firstname.assign(p+3, len);\r
+ break;\r
+ case isc_spb_sec_middlename :\r
+ if (len != 0) user.middlename.assign(p+3, len);\r
+ break;\r
+ case isc_spb_sec_lastname :\r
+ if (len != 0) user.lastname.assign(p+3, len);\r
+ break;\r
+ }\r
+ p += (3 + len);\r
+ }\r
+ }\r
+ if (! user.username.empty()) users.push_back(user); // Flush last user\r
+}\r
+\r
+void ServiceImpl::SetPageBuffers(const std::string& dbfile, int buffers)\r
+{\r
+ if (gds.Call()->mGDSVersion < 60)\r
+ throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Service::SetPageBuffers", _("Service is not connected."));\r
+ if (dbfile.empty())\r
+ throw LogicExceptionImpl("Service::SetPageBuffers", _("Main database file must be specified."));\r
+\r
+ IBS status;\r
+ SPB spb;\r
+\r
+ spb.Insert(isc_action_svc_properties);\r
+ spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());\r
+ spb.InsertQuad(isc_spb_prp_page_buffers, buffers);\r
+\r
+ (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::SetPageBuffers", _("isc_service_start failed"));\r
+\r
+ Wait();\r
+}\r
+\r
+void ServiceImpl::SetSweepInterval(const std::string& dbfile, int sweep)\r
+{\r
+ if (gds.Call()->mGDSVersion < 60)\r
+ throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Service::SetSweepInterval", _("Service is not connected."));\r
+ if (dbfile.empty())\r
+ throw LogicExceptionImpl("Service::SetSweepInterval", _("Main database file must be specified."));\r
+\r
+ IBS status;\r
+ SPB spb;\r
+\r
+ spb.Insert(isc_action_svc_properties);\r
+ spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());\r
+ spb.InsertQuad(isc_spb_prp_sweep_interval, sweep);\r
+\r
+ (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::SetSweepInterval", _("isc_service_start failed"));\r
+\r
+ Wait();\r
+}\r
+\r
+void ServiceImpl::SetSyncWrite(const std::string& dbfile, bool sync)\r
+{\r
+ if (gds.Call()->mGDSVersion < 60)\r
+ throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Service::SetSyncWrite", _("Service is not connected."));\r
+ if (dbfile.empty())\r
+ throw LogicExceptionImpl("Service::SetSyncWrite", _("Main database file must be specified."));\r
+\r
+ IBS status;\r
+ SPB spb;\r
+\r
+ spb.Insert(isc_action_svc_properties);\r
+ spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());\r
+ if (sync) spb.InsertByte(isc_spb_prp_write_mode, (char)isc_spb_prp_wm_sync);\r
+ else spb.InsertByte(isc_spb_prp_write_mode, (char)isc_spb_prp_wm_async);\r
+\r
+ (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::SetSyncWrite", _("isc_service_start failed"));\r
+\r
+ Wait();\r
+}\r
+\r
+void ServiceImpl::SetReadOnly(const std::string& dbfile, bool readonly)\r
+{\r
+ if (gds.Call()->mGDSVersion < 60)\r
+ throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Service::SetReadOnly", _("Service is not connected."));\r
+ if (dbfile.empty())\r
+ throw LogicExceptionImpl("Service::SetReadOnly", _("Main database file must be specified."));\r
+\r
+ IBS status;\r
+ SPB spb;\r
+\r
+ spb.Insert(isc_action_svc_properties);\r
+ spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());\r
+ if (readonly) spb.InsertByte(isc_spb_prp_access_mode, (char)isc_spb_prp_am_readonly);\r
+ else spb.InsertByte(isc_spb_prp_access_mode, (char)isc_spb_prp_am_readwrite);\r
+\r
+ (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::SetReadOnly", _("isc_service_start failed"));\r
+\r
+ Wait();\r
+}\r
+\r
+void ServiceImpl::SetReserveSpace(const std::string& dbfile, bool reserve)\r
+{\r
+ if (gds.Call()->mGDSVersion < 60)\r
+ throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Service::SetReserveSpace", _("Service is not connected."));\r
+ if (dbfile.empty())\r
+ throw LogicExceptionImpl("Service::SetReserveSpace", _("Main database file must be specified."));\r
+\r
+ IBS status;\r
+ SPB spb;\r
+\r
+ spb.Insert(isc_action_svc_properties);\r
+ spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());\r
+ if (reserve) spb.InsertByte(isc_spb_prp_reserve_space, (char)isc_spb_prp_res);\r
+ else spb.InsertByte(isc_spb_prp_reserve_space, (char)isc_spb_prp_res_use_full);\r
+\r
+ (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::SetReserveSpace", _("isc_service_start failed"));\r
+\r
+ Wait();\r
+}\r
+\r
+void ServiceImpl::Shutdown(const std::string& dbfile, IBPP::DSM mode, int sectimeout)\r
+{\r
+ if (gds.Call()->mGDSVersion < 60)\r
+ throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Service::Shutdown", _("Service is not connected."));\r
+ if (dbfile.empty())\r
+ throw LogicExceptionImpl("Service::Shutdown", _("Main database file must be specified."));\r
+\r
+ IBS status;\r
+ SPB spb;\r
+\r
+ spb.Insert(isc_action_svc_properties);\r
+ spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());\r
+ switch (mode)\r
+ {\r
+ case IBPP::dsDenyAttach :\r
+ spb.InsertQuad(isc_spb_prp_deny_new_attachments, sectimeout);\r
+ break;\r
+ case IBPP::dsDenyTrans :\r
+ spb.InsertQuad(isc_spb_prp_deny_new_transactions, sectimeout);\r
+ break;\r
+ case IBPP::dsForce :\r
+ spb.InsertQuad(isc_spb_prp_shutdown_db, sectimeout);\r
+ break;\r
+ }\r
+\r
+ (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::Shutdown", _("isc_service_start failed"));\r
+\r
+ Wait();\r
+}\r
+\r
+void ServiceImpl::Restart(const std::string& dbfile)\r
+{\r
+ if (gds.Call()->mGDSVersion < 60)\r
+ throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Service::Restart", _("Service is not connected."));\r
+ if (dbfile.empty())\r
+ throw LogicExceptionImpl("Service::Restart", _("Main database file must be specified."));\r
+\r
+ IBS status;\r
+ SPB spb;\r
+\r
+ spb.Insert(isc_action_svc_properties);\r
+ spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());\r
+ spb.InsertQuad(isc_spb_options, isc_spb_prp_db_online);\r
+\r
+ (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::Restart", _("isc_service_start failed"));\r
+\r
+ Wait();\r
+}\r
+\r
+void ServiceImpl::Sweep(const std::string& dbfile)\r
+{\r
+ if (gds.Call()->mGDSVersion < 60)\r
+ throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Service::Sweep", _("Service is not connected."));\r
+ if (dbfile.empty())\r
+ throw LogicExceptionImpl("Service::Sweep", _("Main database file must be specified."));\r
+\r
+ IBS status;\r
+ SPB spb;\r
+\r
+ spb.Insert(isc_action_svc_repair);\r
+ spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());\r
+ spb.InsertQuad(isc_spb_options, isc_spb_rpr_sweep_db);\r
+\r
+ (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::Sweep", _("isc_service_start failed"));\r
+\r
+ Wait();\r
+}\r
+\r
+void ServiceImpl::Repair(const std::string& dbfile, IBPP::RPF flags)\r
+{\r
+ if (gds.Call()->mGDSVersion < 60)\r
+ throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Service::Repair", _("Service is not connected."));\r
+ if (dbfile.empty())\r
+ throw LogicExceptionImpl("Service::Repair", _("Main database file must be specified."));\r
+\r
+ IBS status;\r
+ SPB spb;\r
+\r
+ spb.Insert(isc_action_svc_repair);\r
+ spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());\r
+\r
+ unsigned int mask;\r
+ if (flags & IBPP::rpValidateFull) mask = (isc_spb_rpr_full | isc_spb_rpr_validate_db);\r
+ else if (flags & IBPP::rpValidatePages) mask = isc_spb_rpr_validate_db;\r
+ else if (flags & IBPP::rpMendRecords) mask = isc_spb_rpr_mend_db;\r
+ else throw LogicExceptionImpl("Service::Repair",\r
+ _("One of rpMendRecords, rpValidatePages, rpValidateFull is required."));\r
+\r
+ if (flags & IBPP::rpReadOnly) mask |= isc_spb_rpr_check_db;\r
+ if (flags & IBPP::rpIgnoreChecksums) mask |= isc_spb_rpr_ignore_checksum;\r
+ if (flags & IBPP::rpKillShadows) mask |= isc_spb_rpr_kill_shadows;\r
+ \r
+ spb.InsertQuad(isc_spb_options, mask);\r
+\r
+ (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::Repair", _("isc_service_start failed"));\r
+\r
+ Wait();\r
+}\r
+\r
+void ServiceImpl::StartBackup(const std::string& dbfile,\r
+ const std::string& bkfile, IBPP::BRF flags)\r
+{\r
+ if (gds.Call()->mGDSVersion < 60)\r
+ throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Service::Backup", _("Service is not connected."));\r
+ if (dbfile.empty())\r
+ throw LogicExceptionImpl("Service::Backup", _("Main database file must be specified."));\r
+ if (bkfile.empty())\r
+ throw LogicExceptionImpl("Service::Backup", _("Backup file must be specified."));\r
+\r
+ IBS status;\r
+ SPB spb;\r
+\r
+ spb.Insert(isc_action_svc_backup);\r
+ spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());\r
+ spb.InsertString(isc_spb_bkp_file, 2, bkfile.c_str());\r
+ if (flags & IBPP::brVerbose) spb.Insert(isc_spb_verbose);\r
+\r
+ unsigned int mask = 0;\r
+ if (flags & IBPP::brIgnoreChecksums) mask |= isc_spb_bkp_ignore_checksums;\r
+ if (flags & IBPP::brIgnoreLimbo) mask |= isc_spb_bkp_ignore_limbo;\r
+ if (flags & IBPP::brMetadataOnly) mask |= isc_spb_bkp_metadata_only;\r
+ if (flags & IBPP::brNoGarbageCollect) mask |= isc_spb_bkp_no_garbage_collect;\r
+ if (flags & IBPP::brNonTransportable) mask |= isc_spb_bkp_non_transportable;\r
+ if (flags & IBPP::brConvertExtTables) mask |= isc_spb_bkp_convert;\r
+ if (mask != 0) spb.InsertQuad(isc_spb_options, mask);\r
+\r
+ (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::Backup", _("isc_service_start failed"));\r
+}\r
+\r
+void ServiceImpl::StartRestore(const std::string& bkfile, const std::string& dbfile,\r
+ int pagesize, IBPP::BRF flags)\r
+{\r
+ if (gds.Call()->mGDSVersion < 60)\r
+ throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Service::Restore", _("Service is not connected."));\r
+ if (bkfile.empty())\r
+ throw LogicExceptionImpl("Service::Restore", _("Backup file must be specified."));\r
+ if (dbfile.empty())\r
+ throw LogicExceptionImpl("Service::Restore", _("Main database file must be specified."));\r
+\r
+ IBS status;\r
+ SPB spb;\r
+\r
+ spb.Insert(isc_action_svc_restore);\r
+ spb.InsertString(isc_spb_bkp_file, 2, bkfile.c_str());\r
+ spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());\r
+ if (flags & IBPP::brVerbose) spb.Insert(isc_spb_verbose);\r
+ if (pagesize != 0) spb.InsertQuad(isc_spb_res_page_size, pagesize);\r
+\r
+ unsigned int mask;\r
+ if (flags & IBPP::brReplace) mask = isc_spb_res_replace;\r
+ else mask = isc_spb_res_create; // Safe default mode\r
+\r
+ if (flags & IBPP::brDeactivateIdx) mask |= isc_spb_res_deactivate_idx;\r
+ if (flags & IBPP::brNoShadow) mask |= isc_spb_res_no_shadow;\r
+ if (flags & IBPP::brNoValidity) mask |= isc_spb_res_no_validity;\r
+ if (flags & IBPP::brPerTableCommit) mask |= isc_spb_res_one_at_a_time;\r
+ if (flags & IBPP::brUseAllSpace) mask |= isc_spb_res_use_all_space;\r
+ if (mask != 0) spb.InsertQuad(isc_spb_options, mask);\r
+\r
+ (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Service::Restore", _("isc_service_start failed"));\r
+}\r
+\r
+const char* ServiceImpl::WaitMsg()\r
+{\r
+ IBS status;\r
+ SPB req;\r
+ RB result(1024);\r
+\r
+ if (gds.Call()->mGDSVersion < 60)\r
+ throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
+\r
+ req.Insert(isc_info_svc_line); // Request one line of textual output\r
+\r
+ // _service_query will only block until a line of result is available\r
+ // (or until the end of the task if it does not report information)\r
+ (*gds.Call()->m_service_query)(status.Self(), &mHandle, 0, 0, 0,\r
+ req.Size(), req.Self(), result.Size(), result.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "ServiceImpl::Wait", _("isc_service_query failed"));\r
+\r
+ // If message length is zero bytes, task is finished\r
+ if (result.GetString(isc_info_svc_line, mWaitMessage) == 0) return 0;\r
+\r
+ // Task is not finished, but we have something to report\r
+ return mWaitMessage.c_str();\r
+}\r
+\r
+void ServiceImpl::Wait()\r
+{\r
+ IBS status;\r
+ SPB spb;\r
+ RB result(1024);\r
+ std::string msg;\r
+\r
+ if (gds.Call()->mGDSVersion < 60)\r
+ throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));\r
+\r
+ spb.Insert(isc_info_svc_line);\r
+ for (;;)\r
+ {\r
+ // Sleeps 1 millisecond upfront. This will release the remaining\r
+ // timeslot of the thread. Doing so will give a good chance for small\r
+ // services tasks to finish before we check if they are still running.\r
+ // The deal is to limit (in that particular case) the number of loops\r
+ // polling _service_query that will happen.\r
+\r
+ Sleep(1);\r
+\r
+ // _service_query will only block until a line of result is available\r
+ // (or until the end of the task if it does not report information) \r
+ (*gds.Call()->m_service_query)(status.Self(), &mHandle, 0, 0, 0,\r
+ spb.Size(), spb.Self(), result.Size(), result.Self());\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "ServiceImpl::Wait", _("isc_service_query failed"));\r
+\r
+ // If message length is zero bytes, task is finished\r
+ if (result.GetString(isc_info_svc_line, msg) == 0) return;\r
+\r
+ status.Reset();\r
+ result.Reset();\r
+ }\r
+}\r
+\r
+IBPP::IService* ServiceImpl::AddRef()\r
+{\r
+ ASSERTION(mRefCount >= 0);\r
+ ++mRefCount;\r
+ return this;\r
+}\r
+\r
+void ServiceImpl::Release()\r
+{\r
+ // Release cannot throw, except in DEBUG builds on assertion\r
+ ASSERTION(mRefCount >= 0);\r
+ --mRefCount;\r
+ try { if (mRefCount <= 0) delete this; }\r
+ catch (...) { }\r
+}\r
+\r
+// (((((((( OBJECT INTERNAL METHODS ))))))))\r
+\r
+void ServiceImpl::SetServerName(const char* newName)\r
+{\r
+ if (newName == 0) mServerName.erase();\r
+ else mServerName = newName;\r
+}\r
+\r
+void ServiceImpl::SetUserName(const char* newName)\r
+{\r
+ if (newName == 0) mUserName.erase();\r
+ else mUserName = newName;\r
+}\r
+\r
+void ServiceImpl::SetUserPassword(const char* newPassword)\r
+{\r
+ if (newPassword == 0) mUserPassword.erase();\r
+ else mUserPassword = newPassword;\r
+}\r
+\r
+ServiceImpl::ServiceImpl(const std::string& ServerName,\r
+ const std::string& UserName, const std::string& UserPassword)\r
+ : mRefCount(0), mHandle(0),\r
+ mServerName(ServerName), mUserName(UserName), mUserPassword(UserPassword)\r
+{\r
+}\r
+\r
+ServiceImpl::~ServiceImpl()\r
+{\r
+ try { if (Connected()) Disconnect(); }\r
+ catch (...) { }\r
+}\r
+\r
+//\r
+// Eof\r
+//\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: statement.cpp,v 1.2 2009/03/19 20:00:28 faust Exp $\r
+// Subject : IBPP, Service class implementation\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning(disable: 4786 4996)\r
+#ifndef _DEBUG\r
+#pragma warning(disable: 4702)\r
+#endif\r
+#endif\r
+\r
+#include "_ibpp.h"\r
+\r
+#ifdef HAS_HDRSTOP\r
+#pragma hdrstop\r
+#endif\r
+\r
+#include <cstring>\r
+\r
+using namespace ibpp_internals;\r
+\r
+// (((((((( OBJECT INTERFACE IMPLEMENTATION ))))))))\r
+\r
+void StatementImpl::Prepare(const std::string& sql)\r
+{\r
+ if (mDatabase == 0)\r
+ throw LogicExceptionImpl("Statement::Prepare", _("An IDatabase must be attached."));\r
+ if (mDatabase->GetHandle() == 0)\r
+ throw LogicExceptionImpl("Statement::Prepare", _("IDatabase must be connected."));\r
+ if (mTransaction == 0)\r
+ throw LogicExceptionImpl("Statement::Prepare", _("An ITransaction must be attached."));\r
+ if (mTransaction->GetHandle() == 0)\r
+ throw LogicExceptionImpl("Statement::Prepare", _("ITransaction must be started."));\r
+ if (sql.empty())\r
+ throw LogicExceptionImpl("Statement::Prepare", _("SQL statement can't be 0."));\r
+\r
+ // Saves the SQL sentence, only for reporting reasons in case of errors\r
+ mSql = sql;\r
+\r
+ IBS status;\r
+\r
+ // Free all resources currently attached to this Statement, then allocate\r
+ // a new statement descriptor.\r
+ Close();\r
+ (*gds.Call()->m_dsql_allocate_statement)(status.Self(), mDatabase->GetHandlePtr(), &mHandle);\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Statement::Prepare",\r
+ _("isc_dsql_allocate_statement failed"));\r
+\r
+ // Empirical estimate of parameters count and output columns count.\r
+ // This is by far not an exact estimation, which would require parsing the\r
+ // SQL statement. If the SQL statement contains '?' and ',' in string\r
+ // constants, this count will obviously be wrong, but it will be exagerated.\r
+ // It won't hurt. We just try to not have to re-allocate those descriptors later.\r
+ // So we prefer to get them a little bit larger than needed than the other way.\r
+ int16_t inEstimate = 0;\r
+ int16_t outEstimate = 1;\r
+ for (size_t i = 0; i < strlen(sql.c_str()); i++)\r
+ {\r
+ if (sql[i] == '?') ++inEstimate;\r
+ if (sql[i] == ',') ++outEstimate;\r
+ }\r
+\r
+ /*\r
+ DebugStream()<< "Prepare(\""<< sql<< "\")"<< fds;\r
+ DebugStream()<< _("Estimation: ")<< inEstimate<< _(" IN parameters and ")\r
+ << outEstimate<< _(" OUT columns")<< fds;\r
+ */\r
+\r
+ // Allocates output descriptor and prepares the statement\r
+ mOutRow = new RowImpl(mDatabase->Dialect(), outEstimate, mDatabase, mTransaction);\r
+ mOutRow->AddRef();\r
+\r
+ status.Reset();\r
+ (*gds.Call()->m_dsql_prepare)(status.Self(), mTransaction->GetHandlePtr(),\r
+ &mHandle, (short)sql.length(), const_cast<char*>(sql.c_str()),\r
+ short(mDatabase->Dialect()), mOutRow->Self());\r
+ if (status.Errors())\r
+ {\r
+ Close();\r
+ std::string context = "Statement::Prepare( ";\r
+ context.append(mSql).append(" )");\r
+ throw SQLExceptionImpl(status, context.c_str(),\r
+ _("isc_dsql_prepare failed"));\r
+ }\r
+\r
+ // Read what kind of statement was prepared\r
+ status.Reset();\r
+ char itemsReq[] = {isc_info_sql_stmt_type};\r
+ char itemsRes[8];\r
+ (*gds.Call()->m_dsql_sql_info)(status.Self(), &mHandle, 1, itemsReq,\r
+ sizeof(itemsRes), itemsRes);\r
+ if (status.Errors())\r
+ {\r
+ Close();\r
+ throw SQLExceptionImpl(status, "Statement::Prepare",\r
+ _("isc_dsql_sql_info failed"));\r
+ }\r
+ if (itemsRes[0] == isc_info_sql_stmt_type)\r
+ {\r
+ switch (itemsRes[3])\r
+ {\r
+ case isc_info_sql_stmt_select : mType = IBPP::stSelect; break;\r
+ case isc_info_sql_stmt_insert : mType = IBPP::stInsert; break;\r
+ case isc_info_sql_stmt_update : mType = IBPP::stUpdate; break;\r
+ case isc_info_sql_stmt_delete : mType = IBPP::stDelete; break;\r
+ case isc_info_sql_stmt_ddl : mType = IBPP::stDDL; break;\r
+ case isc_info_sql_stmt_exec_procedure : mType = IBPP::stExecProcedure; break;\r
+ case isc_info_sql_stmt_select_for_upd : mType = IBPP::stSelectUpdate; break;\r
+ case isc_info_sql_stmt_set_generator : mType = IBPP::stSetGenerator; break;\r
+ case isc_info_sql_stmt_savepoint : mType = IBPP::stSavePoint; break;\r
+ default : mType = IBPP::stUnsupported;\r
+ }\r
+ }\r
+ if (mType == IBPP::stUnknown || mType == IBPP::stUnsupported)\r
+ {\r
+ Close();\r
+ throw LogicExceptionImpl("Statement::Prepare",\r
+ _("Unknown or unsupported statement type"));\r
+ }\r
+\r
+ if (mOutRow->Columns() == 0)\r
+ {\r
+ // Get rid of the output descriptor, if it wasn't required (no output)\r
+ mOutRow->Release();\r
+ mOutRow = 0;\r
+ /*\r
+ DebugStream()<< _("Dropped output descriptor which was not required")<< fds;\r
+ */\r
+ }\r
+ else if (mOutRow->Columns() > mOutRow->AllocatedSize())\r
+ {\r
+ // Resize the output descriptor (which is too small).\r
+ // The statement does not need to be prepared again, though the\r
+ // output columns must be described again.\r
+\r
+ /*\r
+ DebugStream()<< _("Resize output descriptor from ")\r
+ << mOutRow->AllocatedSize()<< _(" to ")<< mOutRow->Columns()<< fds;\r
+ */\r
+\r
+ mOutRow->Resize(mOutRow->Columns());\r
+ status.Reset();\r
+ (*gds.Call()->m_dsql_describe)(status.Self(), &mHandle, 1, mOutRow->Self());\r
+ if (status.Errors())\r
+ {\r
+ Close();\r
+ throw SQLExceptionImpl(status, "Statement::Prepare",\r
+ _("isc_dsql_describe failed"));\r
+ }\r
+ }\r
+\r
+ if (inEstimate > 0)\r
+ {\r
+ // Ready an input descriptor\r
+ mInRow = new RowImpl(mDatabase->Dialect(), inEstimate, mDatabase, mTransaction);\r
+ mInRow->AddRef();\r
+\r
+ status.Reset();\r
+ (*gds.Call()->m_dsql_describe_bind)(status.Self(), &mHandle, 1, mInRow->Self());\r
+ if (status.Errors())\r
+ {\r
+ Close();\r
+ throw SQLExceptionImpl(status, "Statement::Prepare",\r
+ _("isc_dsql_describe_bind failed"));\r
+ }\r
+\r
+ if (mInRow->Columns() == 0)\r
+ {\r
+ // Get rid of the input descriptor, if it wasn't required (no parameters)\r
+ mInRow->Release();\r
+ mInRow = 0;\r
+ /*\r
+ DebugStream()<< _("Dropped input descriptor which was not required")<< fds;\r
+ */\r
+ }\r
+ else if (mInRow->Columns() > mInRow->AllocatedSize())\r
+ {\r
+ // Resize the input descriptor (which is too small).\r
+ // The statement does not need to be prepared again, though the\r
+ // parameters must be described again.\r
+\r
+ /*\r
+ DebugStream()<< _("Resize input descriptor from ")\r
+ << mInRow->AllocatedSize()<< _(" to ")\r
+ << mInRow->Columns()<< fds;\r
+ */\r
+\r
+ mInRow->Resize(mInRow->Columns());\r
+ status.Reset();\r
+ (*gds.Call()->m_dsql_describe_bind)(status.Self(), &mHandle, 1, mInRow->Self());\r
+ if (status.Errors())\r
+ {\r
+ Close();\r
+ throw SQLExceptionImpl(status, "Statement::Prepare",\r
+ _("isc_dsql_describe_bind failed"));\r
+ }\r
+ }\r
+ }\r
+\r
+ // Allocates variables of the input descriptor\r
+ if (mInRow != 0)\r
+ {\r
+ // Turn on 'can be NULL' on each input parameter\r
+ for (int i = 0; i < mInRow->Columns(); i++)\r
+ {\r
+ XSQLVAR* var = &(mInRow->Self()->sqlvar[i]);\r
+ if (! (var->sqltype & 1)) var->sqltype += short(1);\r
+ }\r
+ mInRow->AllocVariables();\r
+ }\r
+\r
+ // Allocates variables of the output descriptor\r
+ if (mOutRow != 0) mOutRow->AllocVariables();\r
+}\r
+\r
+void StatementImpl::Plan(std::string& plan)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::Plan", _("No statement has been prepared."));\r
+ if (mDatabase == 0)\r
+ throw LogicExceptionImpl("Statement::Plan", _("A Database must be attached."));\r
+ if (mDatabase->GetHandle() == 0)\r
+ throw LogicExceptionImpl("Statement::Plan", _("Database must be connected."));\r
+\r
+ IBS status;\r
+ RB result(4096);\r
+ char itemsReq[] = {isc_info_sql_get_plan};\r
+\r
+ (*gds.Call()->m_dsql_sql_info)(status.Self(), &mHandle, 1, itemsReq,\r
+ result.Size(), result.Self());\r
+ if (status.Errors()) throw SQLExceptionImpl(status,\r
+ "Statement::Plan", _("isc_dsql_sql_info failed."));\r
+\r
+ result.GetString(isc_info_sql_get_plan, plan);\r
+ if (plan[0] == '\n') plan.erase(0, 1);\r
+}\r
+\r
+void StatementImpl::Execute(const std::string& sql)\r
+{\r
+ if (! sql.empty()) Prepare(sql);\r
+\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::Execute",\r
+ _("No statement has been prepared."));\r
+\r
+ // Check that a value has been set for each input parameter\r
+ if (mInRow != 0 && mInRow->MissingValues())\r
+ throw LogicExceptionImpl("Statement::Execute",\r
+ _("All parameters must be specified."));\r
+\r
+ CursorFree(); // Free a previous 'cursor' if any\r
+\r
+ IBS status;\r
+ if (mType == IBPP::stSelect)\r
+ {\r
+ // Could return a result set (none, single or multi rows)\r
+ (*gds.Call()->m_dsql_execute)(status.Self(), mTransaction->GetHandlePtr(),\r
+ &mHandle, 1, mInRow == 0 ? 0 : mInRow->Self());\r
+ if (status.Errors())\r
+ {\r
+ //Close(); Commented because Execute error should not free the statement\r
+ std::string context = "Statement::Execute( ";\r
+ context.append(mSql).append(" )");\r
+ throw SQLExceptionImpl(status, context.c_str(),\r
+ _("isc_dsql_execute failed"));\r
+ }\r
+ if (mOutRow != 0)\r
+ {\r
+ mResultSetAvailable = true;\r
+ mCursorOpened = true;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ // Should return at most a single row\r
+ (*gds.Call()->m_dsql_execute2)(status.Self(), mTransaction->GetHandlePtr(),\r
+ &mHandle, 1, mInRow == 0 ? 0 : mInRow->Self(),\r
+ mOutRow == 0 ? 0 : mOutRow->Self());\r
+ if (status.Errors())\r
+ {\r
+ //Close(); Commented because Execute error should not free the statement\r
+ std::string context = "Statement::Execute( ";\r
+ context.append(mSql).append(" )");\r
+ throw SQLExceptionImpl(status, context.c_str(),\r
+ _("isc_dsql_execute2 failed"));\r
+ }\r
+ }\r
+}\r
+\r
+void StatementImpl::CursorExecute(const std::string& cursor, const std::string& sql)\r
+{\r
+ if (cursor.empty())\r
+ throw LogicExceptionImpl("Statement::CursorExecute", _("Cursor name can't be 0."));\r
+\r
+ if (! sql.empty()) Prepare(sql);\r
+\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::CursorExecute", _("No statement has been prepared."));\r
+ if (mType != IBPP::stSelectUpdate)\r
+ throw LogicExceptionImpl("Statement::CursorExecute", _("Statement must be a SELECT FOR UPDATE."));\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::CursorExecute", _("Statement would return no rows."));\r
+\r
+ // Check that a value has been set for each input parameter\r
+ if (mInRow != 0 && mInRow->MissingValues())\r
+ throw LogicExceptionImpl("Statement::CursorExecute",\r
+ _("All parameters must be specified."));\r
+\r
+ CursorFree(); // Free a previous 'cursor' if any\r
+\r
+ IBS status;\r
+ (*gds.Call()->m_dsql_execute)(status.Self(), mTransaction->GetHandlePtr(),\r
+ &mHandle, 1, mInRow == 0 ? 0 : mInRow->Self());\r
+ if (status.Errors())\r
+ {\r
+ //Close(); Commented because Execute error should not free the statement\r
+ std::string context = "Statement::CursorExecute( ";\r
+ context.append(mSql).append(" )");\r
+ throw SQLExceptionImpl(status, context.c_str(),\r
+ _("isc_dsql_execute failed"));\r
+ }\r
+\r
+ status.Reset();\r
+ (*gds.Call()->m_dsql_set_cursor_name)(status.Self(), &mHandle, const_cast<char*>(cursor.c_str()), 0);\r
+ if (status.Errors())\r
+ {\r
+ //Close(); Commented because Execute error should not free the statement\r
+ throw SQLExceptionImpl(status, "Statement::CursorExecute",\r
+ _("isc_dsql_set_cursor_name failed"));\r
+ }\r
+\r
+ mResultSetAvailable = true;\r
+ mCursorOpened = true;\r
+}\r
+\r
+void StatementImpl::ExecuteImmediate(const std::string& sql)\r
+{\r
+ if (mDatabase == 0)\r
+ throw LogicExceptionImpl("Statement::ExecuteImmediate", _("An IDatabase must be attached."));\r
+ if (mDatabase->GetHandle() == 0)\r
+ throw LogicExceptionImpl("Statement::ExecuteImmediate", _("IDatabase must be connected."));\r
+ if (mTransaction == 0)\r
+ throw LogicExceptionImpl("Statement::ExecuteImmediate", _("An ITransaction must be attached."));\r
+ if (mTransaction->GetHandle() == 0)\r
+ throw LogicExceptionImpl("Statement::ExecuteImmediate", _("ITransaction must be started."));\r
+ if (sql.empty())\r
+ throw LogicExceptionImpl("Statement::ExecuteImmediate", _("SQL statement can't be 0."));\r
+\r
+ IBS status;\r
+ Close();\r
+ (*gds.Call()->m_dsql_execute_immediate)(status.Self(), mDatabase->GetHandlePtr(),\r
+ mTransaction->GetHandlePtr(), 0, const_cast<char*>(sql.c_str()),\r
+ short(mDatabase->Dialect()), 0);\r
+ if (status.Errors())\r
+ {\r
+ std::string context = "Statement::ExecuteImmediate( ";\r
+ context.append(sql).append(" )");\r
+ throw SQLExceptionImpl(status, context.c_str(),\r
+ _("isc_dsql_execute_immediate failed"));\r
+ }\r
+}\r
+\r
+int StatementImpl::AffectedRows()\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::AffectedRows", _("No statement has been prepared."));\r
+ if (mDatabase == 0)\r
+ throw LogicExceptionImpl("Statement::AffectedRows", _("A Database must be attached."));\r
+ if (mDatabase->GetHandle() == 0)\r
+ throw LogicExceptionImpl("Statement::AffectedRows", _("Database must be connected."));\r
+\r
+ int count;\r
+ IBS status;\r
+ RB result;\r
+ char itemsReq[] = {isc_info_sql_records};\r
+\r
+ (*gds.Call()->m_dsql_sql_info)(status.Self(), &mHandle, 1, itemsReq,\r
+ result.Size(), result.Self());\r
+ if (status.Errors()) throw SQLExceptionImpl(status,\r
+ "Statement::AffectedRows", _("isc_dsql_sql_info failed."));\r
+\r
+ if (mType == IBPP::stInsert)\r
+ count = result.GetValue(isc_info_sql_records, isc_info_req_insert_count);\r
+ else if (mType == IBPP::stUpdate)\r
+ count = result.GetValue(isc_info_sql_records, isc_info_req_update_count);\r
+ else if (mType == IBPP::stDelete)\r
+ count = result.GetValue(isc_info_sql_records, isc_info_req_delete_count);\r
+ else if (mType == IBPP::stSelect)\r
+ count = result.GetValue(isc_info_sql_records, isc_info_req_select_count);\r
+ else count = 0; // Returns zero count for unknown cases\r
+\r
+ return count;\r
+}\r
+\r
+bool StatementImpl::Fetch()\r
+{\r
+ if (! mResultSetAvailable)\r
+ throw LogicExceptionImpl("Statement::Fetch",\r
+ _("No statement has been executed or no result set available."));\r
+\r
+ IBS status;\r
+ int code = (*gds.Call()->m_dsql_fetch)(status.Self(), &mHandle, 1, mOutRow->Self());\r
+ if (code == 100) // This special code means "no more rows"\r
+ {\r
+ mResultSetAvailable = false;\r
+ // Oddly enough, fetching rows up to the last one seems to open\r
+ // an 'implicit' cursor that needs to be closed.\r
+ mCursorOpened = true;\r
+ CursorFree(); // Free the explicit or implicit cursor/result-set\r
+ return false;\r
+ }\r
+ if (status.Errors())\r
+ {\r
+ Close();\r
+ throw SQLExceptionImpl(status, "Statement::Fetch",\r
+ _("isc_dsql_fetch failed."));\r
+ }\r
+\r
+ return true;\r
+}\r
+\r
+bool StatementImpl::Fetch(IBPP::Row& row)\r
+{\r
+ if (! mResultSetAvailable)\r
+ throw LogicExceptionImpl("Statement::Fetch(row)",\r
+ _("No statement has been executed or no result set available."));\r
+\r
+ RowImpl* rowimpl = new RowImpl(*mOutRow);\r
+ row = rowimpl;\r
+\r
+ IBS status;\r
+ int code = (*gds.Call()->m_dsql_fetch)(status.Self(), &mHandle, 1,\r
+ rowimpl->Self());\r
+ if (code == 100) // This special code means "no more rows"\r
+ {\r
+ mResultSetAvailable = false;\r
+ // Oddly enough, fetching rows up to the last one seems to open\r
+ // an 'implicit' cursor that needs to be closed.\r
+ mCursorOpened = true;\r
+ CursorFree(); // Free the explicit or implicit cursor/result-set\r
+ row.clear();\r
+ return false;\r
+ }\r
+ if (status.Errors())\r
+ {\r
+ Close();\r
+ row.clear();\r
+ throw SQLExceptionImpl(status, "Statement::Fetch(row)",\r
+ _("isc_dsql_fetch failed."));\r
+ }\r
+\r
+ return true;\r
+}\r
+\r
+void StatementImpl::Close()\r
+{\r
+ // Free all statement resources.\r
+ // Used before preparing a new statement or from destructor.\r
+\r
+ if (mInRow != 0) { mInRow->Release(); mInRow = 0; }\r
+ if (mOutRow != 0) { mOutRow->Release(); mOutRow = 0; }\r
+\r
+ mResultSetAvailable = false;\r
+ mCursorOpened = false;\r
+ mType = IBPP::stUnknown;\r
+\r
+ if (mHandle != 0)\r
+ {\r
+ IBS status;\r
+ (*gds.Call()->m_dsql_free_statement)(status.Self(), &mHandle, DSQL_drop);\r
+ mHandle = 0;\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Statement::Close(DSQL_drop)",\r
+ _("isc_dsql_free_statement failed."));\r
+ }\r
+}\r
+\r
+void StatementImpl::SetNull(int param)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::SetNull", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::SetNull", _("The statement does not take parameters."));\r
+\r
+ mInRow->SetNull(param);\r
+}\r
+\r
+void StatementImpl::Set(int param, bool value)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::Set[bool]", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::Set[bool]", _("The statement does not take parameters."));\r
+\r
+ mInRow->Set(param, value);\r
+}\r
+\r
+void StatementImpl::Set(int param, const char* cstring)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::Set[char*]", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::Set[char*]", _("The statement does not take parameters."));\r
+\r
+ mInRow->Set(param, cstring);\r
+}\r
+\r
+void StatementImpl::Set(int param, const void* bindata, int len)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::Set[void*]", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::Set[void*]", _("The statement does not take parameters."));\r
+\r
+ mInRow->Set(param, bindata, len);\r
+}\r
+\r
+void StatementImpl::Set(int param, const std::string& s)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::Set[string]", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::Set[string]", _("The statement does not take parameters."));\r
+\r
+ mInRow->Set(param, s);\r
+}\r
+\r
+void StatementImpl::Set(int param, int16_t value)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::Set[int16_t]", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::Set[int16_t]", _("The statement does not take parameters."));\r
+\r
+ mInRow->Set(param, value);\r
+}\r
+\r
+void StatementImpl::Set(int param, int32_t value)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::Set[int32_t]", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::Set[int32_t]", _("The statement does not take parameters."));\r
+\r
+ mInRow->Set(param, value);\r
+}\r
+\r
+void StatementImpl::Set(int param, int64_t value)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::Set[int64_t]", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::Set[int64_t]", _("The statement does not take parameters."));\r
+\r
+ mInRow->Set(param, value);\r
+}\r
+\r
+void StatementImpl::Set(int param, float value)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::Set[float]", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::Set[float]", _("The statement does not take parameters."));\r
+\r
+ mInRow->Set(param, value);\r
+}\r
+\r
+void StatementImpl::Set(int param, double value)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::Set[double]", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::Set[double]", _("The statement does not take parameters."));\r
+\r
+ mInRow->Set(param, value);\r
+}\r
+\r
+void StatementImpl::Set(int param, const IBPP::Timestamp& value)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::Set[Timestamp]", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::Set[Timestamp]", _("The statement does not take parameters."));\r
+\r
+ mInRow->Set(param, value);\r
+}\r
+\r
+void StatementImpl::Set(int param, const IBPP::Date& value)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::Set[Date]", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::Set[Date]", _("The statement does not take parameters."));\r
+\r
+ mInRow->Set(param, value);\r
+}\r
+\r
+void StatementImpl::Set(int param, const IBPP::Time& value)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::Set[Time]", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::Set[Time]", _("The statement does not take parameters."));\r
+\r
+ mInRow->Set(param, value);\r
+}\r
+\r
+void StatementImpl::Set(int param, const IBPP::Blob& blob)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::Set[Blob]", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::Set[Blob]", _("The statement does not take parameters."));\r
+\r
+ mInRow->Set(param, blob);\r
+}\r
+\r
+void StatementImpl::Set(int param, const IBPP::Array& array)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::Set[Array]", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::Set[Array]", _("The statement does not take parameters."));\r
+\r
+ mInRow->Set(param, array);\r
+}\r
+\r
+void StatementImpl::Set(int param, const IBPP::DBKey& key)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::Set[DBKey]", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::Set[DBKey]", _("The statement does not take parameters."));\r
+\r
+ mInRow->Set(param, key);\r
+}\r
+\r
+/*\r
+void StatementImpl::Set(int param, const IBPP::Value& value)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::Set[Value]", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::Set[Value]", _("The statement does not take parameters."));\r
+\r
+ mInRow->Set(param, value);\r
+}\r
+*/\r
+\r
+bool StatementImpl::IsNull(int column)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::IsNull", _("The row is not initialized."));\r
+\r
+ return mOutRow->IsNull(column);\r
+}\r
+\r
+bool StatementImpl::Get(int column, bool* retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+ if (retvalue == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));\r
+\r
+ return mOutRow->Get(column, *retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(int column, bool& retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(column, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(int column, char* retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(column, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(int column, void* bindata, int& userlen)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(column, bindata, userlen);\r
+}\r
+\r
+bool StatementImpl::Get(int column, std::string& retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(column, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(int column, int16_t* retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+ if (retvalue == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));\r
+\r
+ return mOutRow->Get(column, *retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(int column, int16_t& retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(column, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(int column, int32_t* retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+ if (retvalue == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));\r
+\r
+ return mOutRow->Get(column, *retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(int column, int32_t& retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(column, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(int column, int64_t* retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+ if (retvalue == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));\r
+\r
+ return mOutRow->Get(column, *retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(int column, int64_t& retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(column, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(int column, float* retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+ if (retvalue == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));\r
+\r
+ return mOutRow->Get(column, *retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(int column, float& retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(column, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(int column, double* retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+ if (retvalue == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));\r
+\r
+ return mOutRow->Get(column, *retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(int column, double& retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(column, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(int column, IBPP::Timestamp& timestamp)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(column, timestamp);\r
+}\r
+\r
+bool StatementImpl::Get(int column, IBPP::Date& date)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(column, date);\r
+}\r
+\r
+bool StatementImpl::Get(int column, IBPP::Time& time)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(column, time);\r
+}\r
+\r
+bool StatementImpl::Get(int column, IBPP::Blob& blob)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(column, blob);\r
+}\r
+\r
+bool StatementImpl::Get(int column, IBPP::DBKey& key)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(column, key);\r
+}\r
+\r
+bool StatementImpl::Get(int column, IBPP::Array& array)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(column, array);\r
+}\r
+\r
+/*\r
+const IBPP::Value StatementImpl::Get(int column)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(column);\r
+}\r
+*/\r
+\r
+bool StatementImpl::IsNull(const std::string& name)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::IsNull", _("The row is not initialized."));\r
+\r
+ return mOutRow->IsNull(name);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, bool* retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+ if (retvalue == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));\r
+\r
+ return mOutRow->Get(name, *retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, bool& retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(name, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, char* retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get[char*]", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(name, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, void* retvalue, int& count)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get[void*,int]", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(name, retvalue, count);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, std::string& retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::GetString", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(name, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, int16_t* retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+ if (retvalue == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));\r
+\r
+ return mOutRow->Get(name, *retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, int16_t& retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(name, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, int32_t* retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+ if (retvalue == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));\r
+\r
+ return mOutRow->Get(name, *retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, int32_t& retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(name, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, int64_t* retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+ if (retvalue == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));\r
+\r
+ return mOutRow->Get(name, *retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, int64_t& retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(name, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, float* retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+ if (retvalue == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));\r
+\r
+ return mOutRow->Get(name, *retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, float& retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(name, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, double* retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+ if (retvalue == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));\r
+\r
+ return mOutRow->Get(name, *retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, double& retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(name, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, IBPP::Timestamp& retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(name, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, IBPP::Date& retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(name, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, IBPP::Time& retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(name, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string&name, IBPP::Blob& retblob)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(name, retblob);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, IBPP::DBKey& retvalue)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(name, retvalue);\r
+}\r
+\r
+bool StatementImpl::Get(const std::string& name, IBPP::Array& retarray)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(name, retarray);\r
+}\r
+\r
+/*\r
+const IBPP::Value StatementImpl::Get(const std::string& name)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));\r
+\r
+ return mOutRow->Get(name);\r
+}\r
+*/\r
+\r
+int StatementImpl::Columns()\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Columns", _("The row is not initialized."));\r
+\r
+ return mOutRow->Columns();\r
+}\r
+\r
+int StatementImpl::ColumnNum(const std::string& name)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::ColumnNum", _("The row is not initialized."));\r
+\r
+ return mOutRow->ColumnNum(name);\r
+}\r
+\r
+const char* StatementImpl::ColumnName(int varnum)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Columns", _("The row is not initialized."));\r
+\r
+ return mOutRow->ColumnName(varnum);\r
+}\r
+\r
+const char* StatementImpl::ColumnAlias(int varnum)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Columns", _("The row is not initialized."));\r
+\r
+ return mOutRow->ColumnAlias(varnum);\r
+}\r
+\r
+const char* StatementImpl::ColumnTable(int varnum)\r
+{\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::Columns", _("The row is not initialized."));\r
+\r
+ return mOutRow->ColumnTable(varnum);\r
+}\r
+\r
+IBPP::SDT StatementImpl::ColumnType(int varnum)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::ColumnType", _("No statement has been prepared."));\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::ColumnType", _("The statement does not return results."));\r
+\r
+ return mOutRow->ColumnType(varnum);\r
+}\r
+\r
+int StatementImpl::ColumnSubtype(int varnum)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::ColumnSubtype", _("No statement has been prepared."));\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::ColumnSubtype", _("The statement does not return results."));\r
+\r
+ return mOutRow->ColumnSubtype(varnum);\r
+}\r
+\r
+int StatementImpl::ColumnSize(int varnum)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::ColumnSize", _("No statement has been prepared."));\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::ColumnSize", _("The row is not initialized."));\r
+\r
+ return mOutRow->ColumnSize(varnum);\r
+}\r
+\r
+int StatementImpl::ColumnScale(int varnum)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::ColumnScale", _("No statement has been prepared."));\r
+ if (mOutRow == 0)\r
+ throw LogicExceptionImpl("Statement::ColumnScale", _("The row is not initialized."));\r
+\r
+ return mOutRow->ColumnScale(varnum);\r
+}\r
+\r
+int StatementImpl::Parameters()\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::Parameters", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::Parameters", _("The statement uses no parameters."));\r
+\r
+ return mInRow->Columns();\r
+}\r
+\r
+IBPP::SDT StatementImpl::ParameterType(int varnum)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::ParameterType", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::ParameterType", _("The statement uses no parameters."));\r
+\r
+ return mInRow->ColumnType(varnum);\r
+}\r
+\r
+int StatementImpl::ParameterSubtype(int varnum)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::ParameterSubtype", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::ParameterSubtype", _("The statement uses no parameters."));\r
+\r
+ return mInRow->ColumnSubtype(varnum);\r
+}\r
+\r
+int StatementImpl::ParameterSize(int varnum)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::ParameterSize", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::ParameterSize", _("The statement uses no parameters."));\r
+\r
+ return mInRow->ColumnSize(varnum);\r
+}\r
+\r
+int StatementImpl::ParameterScale(int varnum)\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Statement::ParameterScale", _("No statement has been prepared."));\r
+ if (mInRow == 0)\r
+ throw LogicExceptionImpl("Statement::ParameterScale", _("The statement uses no parameters."));\r
+\r
+ return mInRow->ColumnScale(varnum);\r
+}\r
+\r
+IBPP::Database StatementImpl::DatabasePtr() const\r
+{\r
+ return mDatabase;\r
+}\r
+\r
+IBPP::Transaction StatementImpl::TransactionPtr() const\r
+{\r
+ return mTransaction;\r
+}\r
+\r
+IBPP::IStatement* StatementImpl::AddRef()\r
+{\r
+ ASSERTION(mRefCount >= 0);\r
+ ++mRefCount;\r
+\r
+ return this;\r
+}\r
+\r
+void StatementImpl::Release()\r
+{\r
+ // Release cannot throw, except in DEBUG builds on assertion\r
+ ASSERTION(mRefCount >= 0);\r
+ --mRefCount;\r
+ try { if (mRefCount <= 0) delete this; }\r
+ catch (...) { }\r
+}\r
+\r
+// (((((((( OBJECT INTERNAL METHODS ))))))))\r
+\r
+void StatementImpl::AttachDatabaseImpl(DatabaseImpl* database)\r
+{\r
+ if (database == 0)\r
+ throw LogicExceptionImpl("Statement::AttachDatabase",\r
+ _("Can't attach a 0 IDatabase object."));\r
+\r
+ if (mDatabase != 0) mDatabase->DetachStatementImpl(this);\r
+ mDatabase = database;\r
+ mDatabase->AttachStatementImpl(this);\r
+}\r
+\r
+void StatementImpl::DetachDatabaseImpl()\r
+{\r
+ if (mDatabase == 0) return;\r
+\r
+ Close();\r
+ mDatabase->DetachStatementImpl(this);\r
+ mDatabase = 0;\r
+}\r
+\r
+void StatementImpl::AttachTransactionImpl(TransactionImpl* transaction)\r
+{\r
+ if (transaction == 0)\r
+ throw LogicExceptionImpl("Statement::AttachTransaction",\r
+ _("Can't attach a 0 ITransaction object."));\r
+\r
+ if (mTransaction != 0) mTransaction->DetachStatementImpl(this);\r
+ mTransaction = transaction;\r
+ mTransaction->AttachStatementImpl(this);\r
+}\r
+\r
+void StatementImpl::DetachTransactionImpl()\r
+{\r
+ if (mTransaction == 0) return;\r
+\r
+ Close();\r
+ mTransaction->DetachStatementImpl(this);\r
+ mTransaction = 0;\r
+}\r
+\r
+void StatementImpl::CursorFree()\r
+{\r
+ if (mCursorOpened)\r
+ {\r
+ mCursorOpened = false;\r
+ if (mHandle != 0)\r
+ {\r
+ IBS status;\r
+ (*gds.Call()->m_dsql_free_statement)(status.Self(), &mHandle, DSQL_close);\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "StatementImpl::CursorFree(DSQL_close)",\r
+ _("isc_dsql_free_statement failed."));\r
+ }\r
+ }\r
+}\r
+\r
+StatementImpl::StatementImpl(DatabaseImpl* database, TransactionImpl* transaction,\r
+ const std::string& sql)\r
+ : mRefCount(0), mHandle(0), mDatabase(0), mTransaction(0),\r
+ mInRow(0), mOutRow(0),\r
+ mResultSetAvailable(false), mCursorOpened(false), mType(IBPP::stUnknown)\r
+{\r
+ AttachDatabaseImpl(database);\r
+ if (transaction != 0) AttachTransactionImpl(transaction);\r
+ if (! sql.empty()) Prepare(sql);\r
+}\r
+\r
+StatementImpl::~StatementImpl()\r
+{\r
+ try { Close(); }\r
+ catch (...) { }\r
+ try { if (mTransaction != 0) mTransaction->DetachStatementImpl(this); }\r
+ catch (...) { }\r
+ try { if (mDatabase != 0) mDatabase->DetachStatementImpl(this); }\r
+ catch (...) { }\r
+}\r
+\r
+//\r
+// EOF\r
+//\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: time.cpp,v 1.1 2007/05/05 17:00:43 faust Exp $\r
+// Subject : IBPP, Time class implementation\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning(disable: 4786 4996)\r
+#ifndef _DEBUG\r
+#pragma warning(disable: 4702)\r
+#endif\r
+#endif\r
+\r
+#include "_ibpp.h"\r
+\r
+#ifdef HAS_HDRSTOP\r
+#pragma hdrstop\r
+#endif\r
+\r
+#include <time.h> // Can't use <ctime> thanks to MSVC6 buggy library\r
+\r
+using namespace ibpp_internals;\r
+\r
+void IBPP::Time::Now()\r
+{\r
+ time_t systime = time(0);\r
+ tm* loctime = localtime(&systime);\r
+ IBPP::itot(&mTime, loctime->tm_hour, loctime->tm_min, loctime->tm_sec, 0);\r
+}\r
+\r
+void IBPP::Time::SetTime(int tm)\r
+{\r
+ if (tm < 0 || tm > 863999999)\r
+ throw LogicExceptionImpl("Time::SetTime", _("Invalid time value"));\r
+ mTime = tm;\r
+}\r
+\r
+void IBPP::Time::SetTime(int hour, int minute, int second, int tenthousandths)\r
+{\r
+ if (hour < 0 || hour > 23 ||\r
+ minute < 0 || minute > 59 ||\r
+ second < 0 || second > 59 ||\r
+ tenthousandths < 0 || tenthousandths > 9999)\r
+ throw LogicExceptionImpl("Time::SetTime",\r
+ _("Invalid hour, minute, second values"));\r
+ IBPP::itot(&mTime, hour, minute, second, tenthousandths);\r
+}\r
+\r
+void IBPP::Time::GetTime(int& hour, int& minute, int& second) const\r
+{\r
+ IBPP::ttoi(mTime, &hour, &minute, &second, 0);\r
+}\r
+\r
+void IBPP::Time::GetTime(int& hour, int& minute, int& second, int& tenthousandths) const\r
+{\r
+ IBPP::ttoi(mTime, &hour, &minute, &second, &tenthousandths);\r
+}\r
+\r
+int IBPP::Time::Hours() const\r
+{\r
+ int hours;\r
+ IBPP::ttoi(mTime, &hours, 0, 0, 0);\r
+ return hours;\r
+}\r
+\r
+int IBPP::Time::Minutes() const\r
+{\r
+ int minutes;\r
+ IBPP::ttoi(mTime, 0, &minutes, 0, 0);\r
+ return minutes;\r
+}\r
+\r
+int IBPP::Time::Seconds() const\r
+{\r
+ int seconds;\r
+ IBPP::ttoi(mTime, 0, 0, &seconds, 0);\r
+ return seconds;\r
+}\r
+\r
+int IBPP::Time::SubSeconds() const // Actually tenthousandths of seconds\r
+{\r
+ int tenthousandths;\r
+ IBPP::ttoi(mTime, 0, 0, 0, &tenthousandths);\r
+ return tenthousandths;\r
+}\r
+\r
+IBPP::Time::Time(int hour, int minute, int second, int tenthousandths)\r
+{\r
+ SetTime(hour, minute, second, tenthousandths);\r
+}\r
+\r
+IBPP::Time::Time(const IBPP::Time& copied)\r
+{\r
+ mTime = copied.mTime;\r
+}\r
+\r
+IBPP::Time& IBPP::Time::operator=(const IBPP::Timestamp& assigned)\r
+{\r
+ mTime = assigned.GetTime();\r
+ return *this;\r
+}\r
+\r
+IBPP::Time& IBPP::Time::operator=(const IBPP::Time& assigned)\r
+{\r
+ mTime = assigned.mTime;\r
+ return *this;\r
+}\r
+\r
+// Time calculations. Internal format is the number of seconds elapsed since\r
+// midnight. Splits such a time in its hours, minutes, seconds components.\r
+\r
+void IBPP::ttoi(int itime, int *h, int *m, int *s, int* t)\r
+{\r
+ int hh, mm, ss, tt;\r
+\r
+ hh = (int) (itime / 36000000); itime = itime - hh * 36000000;\r
+ mm = (int) (itime / 600000); itime = itime - mm * 600000;\r
+ ss = (int) (itime / 10000);\r
+ tt = (int) (itime - ss * 10000);\r
+\r
+ if (h != 0) *h = hh;\r
+ if (m != 0) *m = mm;\r
+ if (s != 0) *s = ss;\r
+ if (t != 0) *t = tt;\r
+\r
+ return;\r
+}\r
+\r
+// Get the internal time format, given hour, minute, second.\r
+\r
+void IBPP::itot (int *ptime, int hour, int minute, int second, int tenthousandths)\r
+{\r
+ *ptime = hour * 36000000 + minute * 600000 + second * 10000 + tenthousandths;\r
+ return;\r
+}\r
+\r
+namespace ibpp_internals\r
+{\r
+\r
+//\r
+// The following functions are helper conversions functions between IBPP\r
+// Date, Time, Timestamp and ISC_DATE, ISC_TIME and ISC_TIMESTAMP.\r
+// (They must be maintained if the encoding used by Firebird evolve.)\r
+// These helper functions are used from row.cpp and from array.cpp.\r
+//\r
+\r
+void encodeDate(ISC_DATE& isc_dt, const IBPP::Date& dt)\r
+{\r
+ // There simply has a shift of 15019 between the native Firebird\r
+ // date model and the IBPP model.\r
+ isc_dt = (ISC_DATE)(dt.GetDate() + 15019);\r
+}\r
+\r
+void decodeDate(IBPP::Date& dt, const ISC_DATE& isc_dt)\r
+{\r
+ // There simply has a shift of 15019 between the native Firebird\r
+ // date model and the IBPP model.\r
+ dt.SetDate((int)isc_dt - 15019);\r
+}\r
+\r
+void encodeTime(ISC_TIME& isc_tm, const IBPP::Time& tm)\r
+{\r
+ isc_tm = (ISC_TIME)tm.GetTime();\r
+}\r
+\r
+void decodeTime(IBPP::Time& tm, const ISC_TIME& isc_tm)\r
+{\r
+ tm.SetTime((int)isc_tm);\r
+}\r
+\r
+void encodeTimestamp(ISC_TIMESTAMP& isc_ts, const IBPP::Timestamp& ts)\r
+{\r
+ encodeDate(isc_ts.timestamp_date, ts);\r
+ encodeTime(isc_ts.timestamp_time, ts);\r
+}\r
+\r
+void decodeTimestamp(IBPP::Timestamp& ts, const ISC_TIMESTAMP& isc_ts)\r
+{\r
+ decodeDate(ts, isc_ts.timestamp_date);\r
+ decodeTime(ts, isc_ts.timestamp_time);\r
+}\r
+\r
+}\r
+\r
+//\r
+// EOF\r
+//\r
+\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: transaction.cpp,v 1.1 2007/05/05 17:00:43 faust Exp $\r
+// Subject : IBPP, Database class implementation\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning(disable: 4786 4996)\r
+#ifndef _DEBUG\r
+#pragma warning(disable: 4702)\r
+#endif\r
+#endif\r
+\r
+#include "_ibpp.h"\r
+\r
+#ifdef HAS_HDRSTOP\r
+#pragma hdrstop\r
+#endif\r
+\r
+#include <algorithm>\r
+\r
+using namespace ibpp_internals;\r
+\r
+// (((((((( OBJECT INTERFACE IMPLEMENTATION ))))))))\r
+\r
+void TransactionImpl::AttachDatabase(IBPP::Database db,\r
+ IBPP::TAM am, IBPP::TIL il, IBPP::TLR lr, IBPP::TFF flags)\r
+{\r
+ if (db.intf() == 0)\r
+ throw LogicExceptionImpl("Transaction::AttachDatabase",\r
+ _("Can't attach an unbound Database."));\r
+\r
+ AttachDatabaseImpl(dynamic_cast<DatabaseImpl*>(db.intf()), am, il, lr, flags);\r
+}\r
+\r
+void TransactionImpl::DetachDatabase(IBPP::Database db)\r
+{\r
+ if (db.intf() == 0)\r
+ throw LogicExceptionImpl("Transaction::DetachDatabase",\r
+ _("Can't detach an unbound Database."));\r
+\r
+ DetachDatabaseImpl(dynamic_cast<DatabaseImpl*>(db.intf()));\r
+}\r
+\r
+void TransactionImpl::AddReservation(IBPP::Database db,\r
+ const std::string& table, IBPP::TTR tr)\r
+{\r
+ if (mHandle != 0)\r
+ throw LogicExceptionImpl("Transaction::AddReservation",\r
+ _("Can't add table reservation if Transaction started."));\r
+ if (db.intf() == 0)\r
+ throw LogicExceptionImpl("Transaction::AddReservation",\r
+ _("Can't add table reservation on an unbound Database."));\r
+\r
+ // Find the TPB associated with this database\r
+ std::vector<DatabaseImpl*>::iterator pos =\r
+ std::find(mDatabases.begin(), mDatabases.end(), dynamic_cast<DatabaseImpl*>(db.intf()));\r
+ if (pos != mDatabases.end())\r
+ {\r
+ size_t index = pos - mDatabases.begin();\r
+ TPB* tpb = mTPBs[index];\r
+ \r
+ // Now add the reservations to the TPB\r
+ switch (tr)\r
+ {\r
+ case IBPP::trSharedWrite :\r
+ tpb->Insert(isc_tpb_lock_write);\r
+ tpb->Insert(table);\r
+ tpb->Insert(isc_tpb_shared);\r
+ break;\r
+ case IBPP::trSharedRead :\r
+ tpb->Insert(isc_tpb_lock_read);\r
+ tpb->Insert(table);\r
+ tpb->Insert(isc_tpb_shared);\r
+ break;\r
+ case IBPP::trProtectedWrite :\r
+ tpb->Insert(isc_tpb_lock_write);\r
+ tpb->Insert(table);\r
+ tpb->Insert(isc_tpb_protected);\r
+ break;\r
+ case IBPP::trProtectedRead :\r
+ tpb->Insert(isc_tpb_lock_read);\r
+ tpb->Insert(table);\r
+ tpb->Insert(isc_tpb_protected);\r
+ break;\r
+ default :\r
+ throw LogicExceptionImpl("Transaction::AddReservation",\r
+ _("Illegal TTR value detected."));\r
+ }\r
+ }\r
+ else throw LogicExceptionImpl("Transaction::AddReservation",\r
+ _("The database connection you specified is not attached to this transaction."));\r
+}\r
+\r
+void TransactionImpl::Start()\r
+{\r
+ if (mHandle != 0) return; // Already started anyway\r
+\r
+ if (mDatabases.empty())\r
+ throw LogicExceptionImpl("Transaction::Start", _("No Database is attached."));\r
+\r
+ struct ISC_TEB\r
+ {\r
+ ISC_LONG* db_ptr;\r
+ ISC_LONG tpb_len;\r
+ char* tpb_ptr;\r
+ } * teb = new ISC_TEB[mDatabases.size()];\r
+\r
+ unsigned i;\r
+ for (i = 0; i < mDatabases.size(); i++)\r
+ {\r
+ if (mDatabases[i]->GetHandle() == 0)\r
+ {\r
+ // All Databases must be connected to Start the transaction !\r
+ delete [] teb;\r
+ throw LogicExceptionImpl("Transaction::Start",\r
+ _("All attached Database should have been connected."));\r
+ }\r
+ teb[i].db_ptr = (ISC_LONG*) mDatabases[i]->GetHandlePtr();\r
+ teb[i].tpb_len = mTPBs[i]->Size();\r
+ teb[i].tpb_ptr = mTPBs[i]->Self();\r
+ }\r
+\r
+ IBS status;\r
+ (*gds.Call()->m_start_multiple)(status.Self(), &mHandle, (short)mDatabases.size(), teb);\r
+ delete [] teb;\r
+ if (status.Errors())\r
+ {\r
+ mHandle = 0; // Should be, but better be sure...\r
+ throw SQLExceptionImpl(status, "Transaction::Start");\r
+ }\r
+}\r
+\r
+void TransactionImpl::Commit()\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Transaction::Commit", _("Transaction is not started."));\r
+ \r
+ IBS status;\r
+\r
+ (*gds.Call()->m_commit_transaction)(status.Self(), &mHandle);\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Transaction::Commit");\r
+ mHandle = 0; // Should be, better be sure\r
+}\r
+\r
+void TransactionImpl::CommitRetain()\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Transaction::CommitRetain", _("Transaction is not started."));\r
+\r
+ IBS status;\r
+\r
+ (*gds.Call()->m_commit_retaining)(status.Self(), &mHandle);\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Transaction::CommitRetain");\r
+}\r
+\r
+void TransactionImpl::Rollback()\r
+{\r
+ if (mHandle == 0) return; // Transaction not started anyway\r
+\r
+ IBS status;\r
+\r
+ (*gds.Call()->m_rollback_transaction)(status.Self(), &mHandle);\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Transaction::Rollback");\r
+ mHandle = 0; // Should be, better be sure\r
+}\r
+\r
+void TransactionImpl::RollbackRetain()\r
+{\r
+ if (mHandle == 0)\r
+ throw LogicExceptionImpl("Transaction::RollbackRetain", _("Transaction is not started."));\r
+\r
+ IBS status;\r
+\r
+ (*gds.Call()->m_rollback_retaining)(status.Self(), &mHandle);\r
+ if (status.Errors())\r
+ throw SQLExceptionImpl(status, "Transaction::RollbackRetain");\r
+}\r
+\r
+IBPP::ITransaction* TransactionImpl::AddRef()\r
+{\r
+ ASSERTION(mRefCount >= 0);\r
+ ++mRefCount;\r
+ return this;\r
+}\r
+\r
+void TransactionImpl::Release()\r
+{\r
+ // Release cannot throw, except in DEBUG builds on assertion\r
+ ASSERTION(mRefCount >= 0);\r
+ --mRefCount;\r
+ try { if (mRefCount <= 0) delete this; }\r
+ catch (...) { }\r
+}\r
+\r
+// (((((((( OBJECT INTERNAL METHODS ))))))))\r
+\r
+void TransactionImpl::Init()\r
+{\r
+ mHandle = 0;\r
+ mDatabases.clear();\r
+ mTPBs.clear();\r
+ mStatements.clear();\r
+ mBlobs.clear();\r
+ mArrays.clear();\r
+}\r
+\r
+void TransactionImpl::AttachStatementImpl(StatementImpl* st)\r
+{\r
+ if (st == 0)\r
+ throw LogicExceptionImpl("Transaction::AttachStatement",\r
+ _("Can't attach a 0 Statement object."));\r
+\r
+ mStatements.push_back(st);\r
+}\r
+\r
+void TransactionImpl::DetachStatementImpl(StatementImpl* st)\r
+{\r
+ if (st == 0)\r
+ throw LogicExceptionImpl("Transaction::DetachStatement",\r
+ _("Can't detach a 0 Statement object."));\r
+\r
+ mStatements.erase(std::find(mStatements.begin(), mStatements.end(), st));\r
+}\r
+\r
+void TransactionImpl::AttachBlobImpl(BlobImpl* bb)\r
+{\r
+ if (bb == 0)\r
+ throw LogicExceptionImpl("Transaction::AttachBlob",\r
+ _("Can't attach a 0 BlobImpl object."));\r
+\r
+ mBlobs.push_back(bb);\r
+}\r
+\r
+void TransactionImpl::DetachBlobImpl(BlobImpl* bb)\r
+{\r
+ if (bb == 0)\r
+ throw LogicExceptionImpl("Transaction::DetachBlob",\r
+ _("Can't detach a 0 BlobImpl object."));\r
+\r
+ mBlobs.erase(std::find(mBlobs.begin(), mBlobs.end(), bb));\r
+}\r
+\r
+void TransactionImpl::AttachArrayImpl(ArrayImpl* ar)\r
+{\r
+ if (ar == 0)\r
+ throw LogicExceptionImpl("Transaction::AttachArray",\r
+ _("Can't attach a 0 ArrayImpl object."));\r
+\r
+ mArrays.push_back(ar);\r
+}\r
+\r
+void TransactionImpl::DetachArrayImpl(ArrayImpl* ar)\r
+{\r
+ if (ar == 0)\r
+ throw LogicExceptionImpl("Transaction::DetachArray",\r
+ _("Can't detach a 0 ArrayImpl object."));\r
+\r
+ mArrays.erase(std::find(mArrays.begin(), mArrays.end(), ar));\r
+}\r
+\r
+void TransactionImpl::AttachDatabaseImpl(DatabaseImpl* dbi,\r
+ IBPP::TAM am, IBPP::TIL il, IBPP::TLR lr, IBPP::TFF flags)\r
+{\r
+ if (mHandle != 0)\r
+ throw LogicExceptionImpl("Transaction::AttachDatabase",\r
+ _("Can't attach a Database if Transaction started."));\r
+ if (dbi == 0)\r
+ throw LogicExceptionImpl("Transaction::AttachDatabase",\r
+ _("Can't attach a null Database."));\r
+\r
+ mDatabases.push_back(dbi);\r
+\r
+ // Prepare a new TPB\r
+ TPB* tpb = new TPB;\r
+ if (am == IBPP::amRead) tpb->Insert(isc_tpb_read);\r
+ else tpb->Insert(isc_tpb_write);\r
+\r
+ switch (il)\r
+ {\r
+ case IBPP::ilConsistency : tpb->Insert(isc_tpb_consistency); break;\r
+ case IBPP::ilReadDirty : tpb->Insert(isc_tpb_read_committed);\r
+ tpb->Insert(isc_tpb_rec_version); break;\r
+ case IBPP::ilReadCommitted : tpb->Insert(isc_tpb_read_committed);\r
+ tpb->Insert(isc_tpb_no_rec_version); break;\r
+ default : tpb->Insert(isc_tpb_concurrency); break;\r
+ }\r
+\r
+ if (lr == IBPP::lrNoWait) tpb->Insert(isc_tpb_nowait);\r
+ else tpb->Insert(isc_tpb_wait);\r
+\r
+ if (flags & IBPP::tfIgnoreLimbo) tpb->Insert(isc_tpb_ignore_limbo);\r
+ if (flags & IBPP::tfAutoCommit) tpb->Insert(isc_tpb_autocommit);\r
+ if (flags & IBPP::tfNoAutoUndo) tpb->Insert(isc_tpb_no_auto_undo);\r
+\r
+ mTPBs.push_back(tpb);\r
+\r
+ // Signals the Database object that it has been attached to the Transaction\r
+ dbi->AttachTransactionImpl(this);\r
+}\r
+\r
+void TransactionImpl::DetachDatabaseImpl(DatabaseImpl* dbi)\r
+{\r
+ if (mHandle != 0)\r
+ throw LogicExceptionImpl("Transaction::DetachDatabase",\r
+ _("Can't detach a Database if Transaction started."));\r
+ if (dbi == 0)\r
+ throw LogicExceptionImpl("Transaction::DetachDatabase",\r
+ _("Can't detach a null Database."));\r
+\r
+ std::vector<DatabaseImpl*>::iterator pos =\r
+ std::find(mDatabases.begin(), mDatabases.end(), dbi);\r
+ if (pos != mDatabases.end())\r
+ {\r
+ size_t index = pos - mDatabases.begin();\r
+ TPB* tpb = mTPBs[index];\r
+ mDatabases.erase(pos);\r
+ mTPBs.erase(mTPBs.begin()+index);\r
+ delete tpb;\r
+ }\r
+\r
+ // Signals the Database object that it has been detached from the Transaction\r
+ dbi->DetachTransactionImpl(this);\r
+}\r
+\r
+TransactionImpl::TransactionImpl(DatabaseImpl* db,\r
+ IBPP::TAM am, IBPP::TIL il, IBPP::TLR lr, IBPP::TFF flags)\r
+ : mRefCount(0)\r
+{\r
+ Init();\r
+ AttachDatabaseImpl(db, am, il, lr, flags);\r
+}\r
+\r
+TransactionImpl::~TransactionImpl()\r
+{\r
+ // Rollback the transaction if it was Started\r
+ try { if (Started()) Rollback(); }\r
+ catch (...) { }\r
+\r
+ // Let's detach cleanly all Blobs from this Transaction.\r
+ // No Blob object can still maintain pointers to this\r
+ // Transaction which is disappearing.\r
+ //\r
+ // We use a reverse traversal of the array to avoid loops.\r
+ // The array shrinks on each loop (mBbCount decreases).\r
+ // And during the deletion, there is a packing of the array through a\r
+ // copy of elements from the end to the beginning of the array.\r
+ try {\r
+ while (mBlobs.size() > 0)\r
+ mBlobs.back()->DetachTransactionImpl();\r
+ } catch (...) { }\r
+\r
+ // Let's detach cleanly all Arrays from this Transaction.\r
+ // No Array object can still maintain pointers to this\r
+ // Transaction which is disappearing.\r
+ try {\r
+ while (mArrays.size() > 0)\r
+ mArrays.back()->DetachTransactionImpl();\r
+ } catch (...) { }\r
+\r
+ // Let's detach cleanly all Statements from this Transaction.\r
+ // No Statement object can still maintain pointers to this\r
+ // Transaction which is disappearing.\r
+ try {\r
+ while (mStatements.size() > 0)\r
+ mStatements.back()->DetachTransactionImpl();\r
+ } catch (...) { }\r
+\r
+ // Very important : let's detach cleanly all Databases from this\r
+ // Transaction. No Database object can still maintain pointers to this\r
+ // Transaction which is disappearing.\r
+ try {\r
+ while (mDatabases.size() > 0)\r
+ {\r
+ size_t i = mDatabases.size()-1;\r
+ DetachDatabaseImpl(mDatabases[i]); // <-- remove link to database from mTPBs\r
+ // array and destroy TPB object\r
+ // Fixed : Maxim Abrashkin on 12 Jun 2002\r
+ //mDatabases.back()->DetachTransaction(this);\r
+ }\r
+ } catch (...) { }\r
+}\r
+\r
+//\r
+// EOF\r
+//\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// File : $Id: user.cpp,v 1.1 2007/05/05 17:00:43 faust Exp $\r
+// Subject : IBPP, User class implementation\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
+//\r
+// The contents of this file are subject to the IBPP License (the "License");\r
+// you may not use this file except in compliance with the License. You may\r
+// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
+// file which must have been distributed along with this file.\r
+//\r
+// This software, distributed under the License, is distributed on an "AS IS"\r
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+// License for the specific language governing rights and limitations\r
+// under the License.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// COMMENTS\r
+// * Tabulations should be set every four characters when editing this file.\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _MSC_VER\r
+#pragma warning(disable: 4786 4996)\r
+#ifndef _DEBUG\r
+#pragma warning(disable: 4702)\r
+#endif\r
+#endif\r
+\r
+#include "_ibpp.h"\r
+\r
+#ifdef HAS_HDRSTOP\r
+#pragma hdrstop\r
+#endif\r
+\r
+#include <iostream>\r
+#include <sstream>\r
+#include <iomanip>\r
+\r
+using namespace ibpp_internals;\r
+\r
+// Private implementation\r
+\r
+void IBPP::User::copyfrom(const IBPP::User& r)\r
+{\r
+ username = r.username;\r
+ password = r.password;\r
+ firstname = r.firstname;\r
+ middlename = r.middlename;\r
+ lastname = r.lastname;\r
+ userid = r.userid;\r
+ groupid = r.groupid;\r
+}\r
+\r
+// Public implementation\r
+\r
+void IBPP::User::clear()\r
+{\r
+ username.erase(); password.erase();\r
+ firstname.erase(); middlename.erase(); lastname.erase();\r
+ userid = groupid = 0;\r
+}\r
+\r
+//\r
+// EOF\r
+//\r
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.5 2008/12/04 17:13:14 faust Exp $
+###############################################################################
+
+LIB_NAME = stg_pinger
+PROG = lib$(LIB_NAME)
+
+SRCS = pinger.cpp
+
+INCS = pinger.h
+
+LIBS = $(LIB_THREAD)
+
+include ../Makefile.in
+
+test: all
+ g++ -c test.cpp
+ g++ -o test test.o ./libstg_pinger.a -lpthread
--- /dev/null
+#include <stdlib.h>
+#include <pthread.h>
+#include <signal.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/time.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <math.h>
+#include <stdio.h>
+
+#include "pinger.h"
+#include "common.h"
+#include "stg_locker.h"
+
+#ifdef STG_TIME
+extern volatile time_t stgTime;
+#endif
+
+//-----------------------------------------------------------------------------
+STG_PINGER::STG_PINGER(time_t d)
+{
+ delay = d;
+ pthread_mutex_init(&mutex, NULL);
+ pid = 0;
+}
+//-----------------------------------------------------------------------------
+STG_PINGER::~STG_PINGER()
+{
+ pthread_mutex_destroy(&mutex);
+}
+//-----------------------------------------------------------------------------
+int STG_PINGER::Start()
+{
+ struct protoent *proto = NULL;
+ proto = getprotobyname("ICMP");
+ sendSocket = socket(PF_INET, SOCK_RAW, proto->p_proto);
+ recvSocket = socket(PF_INET, SOCK_RAW, proto->p_proto);
+ nonstop = true;
+ pid = (int) getpid() % 65535;
+ if (sendSocket < 0 || recvSocket < 0)
+ {
+ errorStr = "Cannot create socket.";
+ return -1;
+ }
+
+ if (pthread_create(&sendThread, NULL, RunSendPing, this))
+ {
+ errorStr = "Cannot create send thread.";
+ return -1;
+ }
+
+ if (pthread_create(&recvThread, NULL, RunRecvPing, this))
+ {
+ errorStr = "Cannot create recv thread.";
+ return -1;
+ }
+
+ return 0;
+}
+//-----------------------------------------------------------------------------
+int STG_PINGER::Stop()
+{
+ close(recvSocket);
+ nonstop = false;
+ if (isRunningRecver)
+ {
+ //5 seconds to thread stops itself
+ int i;
+ for (i = 0; i < 25; i++)
+ {
+ if (i % 5 == 0)
+ SendPing(0x0100007f);//127.0.0.1
+
+ if (!isRunningRecver)
+ break;
+
+ usleep(200000);
+ }
+
+ //after 5 seconds waiting thread still running. now killing it
+ if (isRunningRecver)
+ {
+ //if (pthread_kill(recvThread, SIGINT))
+ // {
+ errorStr = "Cannot kill thread.";
+ return -1;
+ // }
+ //printf("recvThread killed\n");
+ }
+ }
+
+ if (isRunningSender)
+ {
+ //5 seconds to thread stops itself
+ int i;
+ for (i = 0; i < 25; i++)
+ {
+ if (!isRunningSender)
+ break;
+
+ usleep(200000);
+ }
+
+ //after 5 seconds waiting thread still running. now killing it
+ if (isRunningSender)
+ {
+ //if (pthread_kill(sendThread, SIGINT))
+ // {
+ errorStr = "Cannot kill thread.";
+ return -1;
+ // }
+ //printf("sendThread killed\n");
+ }
+ }
+
+ close(sendSocket);
+ return 0;
+}
+//-----------------------------------------------------------------------------
+void STG_PINGER::AddIP(uint32_t ip)
+{
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ //printf("AddIP\n");
+ ipToAdd.push_back(ip);
+}
+//-----------------------------------------------------------------------------
+void STG_PINGER::DelIP(uint32_t ip)
+{
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ //printf("DelIP\n");
+ ipToDel.push_back(ip);
+}
+//-----------------------------------------------------------------------------
+void STG_PINGER::RealAddIP()
+ {
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+ list<uint32_t>::iterator iter;
+ iter = ipToAdd.begin();
+ while (iter != ipToAdd.end())
+ {
+ /*packets.insert(pair<RAW_PACKET, PACKET_EXTRA_DATA>(rawPacket, ed));*/
+ //pingIP[*iter] = 0;
+ pingIP.insert(pair<uint32_t, time_t>(*iter, 0));
+ iter++;
+ }
+ ipToAdd.erase(ipToAdd.begin(), ipToAdd.end());
+ }
+//-----------------------------------------------------------------------------
+void STG_PINGER::RealDelIP()
+{
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+
+ list<uint32_t>::iterator iter;
+ multimap<uint32_t, time_t>::iterator treeIter;
+ iter = ipToDel.begin();
+ while (iter != ipToDel.end())
+ {
+ treeIter = pingIP.find(*iter);
+ //printf("Found %X\n", *iter);
+ if (treeIter != pingIP.end())
+ pingIP.erase(treeIter);
+
+ iter++;
+ }
+ ipToDel.erase(ipToDel.begin(), ipToDel.end());
+}
+//-----------------------------------------------------------------------------
+int STG_PINGER::GetPingIPNum()
+{
+ return pingIP.size();
+}
+//-----------------------------------------------------------------------------
+void STG_PINGER::GetAllIP(vector<PING_IP_TIME> *)
+{
+ //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+}
+//-----------------------------------------------------------------------------
+void STG_PINGER::PrintAllIP()
+{
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ multimap<uint32_t, time_t>::iterator iter;
+ iter = pingIP.begin();
+ while (iter != pingIP.end())
+ {
+ uint32_t ip = iter->first;
+ time_t t = iter->second;
+ string s;
+ x2str(t, s);
+ printf("ip = %s, time = %9s\n", inet_ntostring(ip).c_str(), s.c_str());
+ iter++;
+ }
+
+}
+//-----------------------------------------------------------------------------
+int STG_PINGER::GetIPTime(uint32_t ip, time_t * t)
+{
+ STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+ multimap<uint32_t, time_t>::iterator treeIter;
+
+ treeIter = pingIP.find(ip);
+ if (treeIter == pingIP.end())
+ return -1;
+
+ *t = treeIter->second;
+ return 0;
+}
+//-----------------------------------------------------------------------------
+void STG_PINGER::SetDelayTime(time_t d)
+{
+ delay = d;
+}
+//-----------------------------------------------------------------------------
+time_t STG_PINGER::GetDelayTime()
+{
+ return delay;
+}
+//-----------------------------------------------------------------------------
+string STG_PINGER::GetStrError()
+{
+ return errorStr;
+}
+//-----------------------------------------------------------------------------
+uint16_t STG_PINGER::PingCheckSum(void * data, int len)
+{
+ unsigned short * buf = (unsigned short *)data;
+ unsigned int sum = 0;
+ unsigned short result;
+
+ for ( sum = 0; len > 1; len -= 2 )
+ sum += *buf++;
+
+ if ( len == 1 )
+ sum += *(unsigned char*)buf;
+
+ sum = (sum >> 16) + (sum & 0xFFFF);
+ sum += (sum >> 16);
+ result = ~sum;
+ return result;
+}
+//-----------------------------------------------------------------------------
+int STG_PINGER::SendPing(uint32_t ip)
+{
+ struct sockaddr_in addr;
+ //printf("SendPing %X \n", ip);
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = 0;
+ addr.sin_addr.s_addr = ip;
+
+ memset(&pmSend, 0, sizeof(pmSend));
+ pmSend.hdr.type = ICMP_ECHO;
+ pmSend.hdr.un.echo.id = pid;
+ memcpy(pmSend.msg, &ip, sizeof(ip));
+
+ pmSend.hdr.checksum = PingCheckSum(&pmSend, sizeof(pmSend));
+
+ if (sendto(sendSocket, &pmSend, sizeof(pmSend), 0, (sockaddr *)&addr, sizeof(addr)) <= 0 )
+ {
+ errorStr = "Send ping error: " + string(strerror(errno));
+ return -1;
+ }
+
+
+ return 0;
+}
+//-----------------------------------------------------------------------------
+uint32_t STG_PINGER::RecvPing()
+{
+ struct sockaddr_in addr;
+ uint32_t ipAddr = 0;
+
+ char buf[128];
+ memset(buf, 0, sizeof(buf));
+ int bytes;
+ socklen_t len = sizeof(addr);
+
+ bytes = recvfrom(recvSocket, &buf, sizeof(buf), 0, (struct sockaddr*)&addr, &len);
+ //printf("recvfrom\n");
+ if (bytes > 0)
+ {
+ struct IP_HDR * ip = (struct IP_HDR *)buf;
+ struct ICMP_HDR *icmp = (struct ICMP_HDR *)(buf + ip->ihl * 4);
+
+ //printf("icmp->un.echo.id=%d, pid=%d, tid: %d\n", icmp->un.echo.id, pid);
+ if (icmp->un.echo.id != pid)
+ return 0;
+
+ ipAddr = *(uint32_t*)(buf + sizeof(ICMP_HDR) + ip->ihl * 4);
+ }
+
+ return ipAddr;
+}
+//-----------------------------------------------------------------------------
+void * STG_PINGER::RunSendPing(void * d)
+{
+ STG_PINGER * pinger = (STG_PINGER*)d;
+
+ pinger->isRunningSender = true;
+ time_t lastPing = 0;
+ while (pinger->nonstop)
+ {
+ pinger->RealAddIP();
+ pinger->RealDelIP();
+
+ multimap<uint32_t, time_t>::iterator iter;
+ iter = pinger->pingIP.begin();
+ while (iter != pinger->pingIP.end())
+ {
+ uint32_t ip = iter->first;
+ pinger->SendPing(ip);
+ iter++;
+ }
+
+ time_t currTime;
+
+ #ifdef STG_TIME
+ lastPing = stgTime;
+ currTime = stgTime;
+ #else
+ currTime = lastPing = time(NULL);
+ #endif
+
+ while (currTime - lastPing < pinger->delay && pinger->nonstop)
+ {
+ #ifdef STG_TIME
+ currTime = stgTime;
+ #else
+ currTime = time(NULL);
+ #endif
+ usleep(20000);
+ }
+ //printf("new ping cycle\n");
+ }
+
+ pinger->isRunningSender = false;
+
+ return NULL;
+}
+//-----------------------------------------------------------------------------
+void * STG_PINGER::RunRecvPing(void * d)
+{
+ STG_PINGER * pinger = (STG_PINGER*)d;
+
+ pinger->isRunningRecver = true;
+
+ uint32_t ip;
+ multimap<uint32_t, time_t>::iterator treeIterLower;
+ multimap<uint32_t, time_t>::iterator treeIterUpper;
+
+ while (pinger->nonstop)
+ {
+ ip = pinger->RecvPing();
+
+ if (ip)
+ {
+ //printf("RecvPing %X\n", ip);
+ treeIterUpper = pinger->pingIP.upper_bound(ip);
+ treeIterLower = pinger->pingIP.lower_bound(ip);
+ int i = 0;
+ while (treeIterUpper != treeIterLower)
+ //treeIterUpper = pinger->pingIP.find(ip);
+ //if (treeIterUpper != pinger->pingIP.end())
+ {
+ //printf("+++! time=%d %X i=%d !+++\n", time(NULL), ip, i);
+ //printf("--- time=%d ---\n", time(NULL));
+ #ifdef STG_TIME
+ treeIterLower->second = stgTime;
+ #else
+ treeIterLower->second = time(NULL);
+ #endif
+ ++treeIterLower;
+ i++;
+ }
+ }
+
+ }
+ pinger->isRunningRecver = false;
+ return NULL;
+}
+//-----------------------------------------------------------------------------
+
--- /dev/null
+ /*
+ $Revision: 1.8 $
+ $Date: 2008/05/10 11:59:53 $
+ $Author: nobunaga $
+ */
+
+#ifndef PINGER_H
+#define PINGER_H
+
+#include <time.h>
+#include <string>
+#include <vector>
+#include <list>
+#include <map>
+
+#ifdef LINUX
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/ip_icmp.h>
+#endif
+
+#if defined (FREE_BSD) || defined (FREE_BSD5)
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/ip_var.h>
+#include <arpa/inet.h>
+#endif
+
+#include "os_int.h"
+
+using namespace std;
+
+//-----------------------------------------------------------------------------
+struct ICMP_HDR
+{
+uint8_t type;
+uint8_t code;
+uint16_t checksum;
+union
+ {
+ struct
+ {
+ uint16_t id;
+ uint16_t sequence;
+ } echo;
+ uint32_t gateway;
+ struct
+ {
+ uint16_t unused;
+ uint16_t mtu;
+ } frag;
+ } un;
+};
+//-----------------------------------------------------------------------------
+struct IP_HDR
+{
+ uint8_t ihl:4,
+ version:4;
+ uint8_t tos;
+ uint16_t tot_len;
+ uint16_t id;
+ uint16_t frag_off;
+ uint8_t ttl;
+ uint8_t protocol;
+ uint16_t check;
+ uint32_t saddr;
+ uint32_t daddr;
+};
+//-----------------------------------------------------------------------------
+struct PING_IP_TIME
+{
+uint32_t ip;
+time_t pingTime;
+};
+//-----------------------------------------------------------------------------
+
+#define PING_DATA_LEN (64)
+//-----------------------------------------------------------------------------
+struct PING_MESSAGE
+{
+ ICMP_HDR hdr;
+ char msg[PING_DATA_LEN];
+};
+//-----------------------------------------------------------------------------
+class STG_PINGER
+{
+public:
+ STG_PINGER(time_t delay = 15);
+ ~STG_PINGER();
+
+ int Start();
+ int Stop();
+ void AddIP(uint32_t ip);
+ void DelIP(uint32_t ip);
+ int GetPingIPNum();
+ void GetAllIP(vector<PING_IP_TIME> * ipTime);
+ void PrintAllIP();
+ int GetIPTime(uint32_t ip, time_t * t);
+ void SetDelayTime(time_t delay);
+ time_t GetDelayTime();
+ string GetStrError();
+
+private:
+
+ int delay;
+ bool nonstop;
+ bool isRunningRecver;
+ bool isRunningSender;
+ int sendSocket;
+ int recvSocket;
+ pthread_t sendThread;
+ pthread_t recvThread;
+
+ PING_MESSAGE pmSend;
+ uint32_t pid;
+
+ uint16_t PingCheckSum(void * data, int len);
+ int SendPing(uint32_t ip);
+ uint32_t RecvPing();
+ void RealAddIP();
+ void RealDelIP();
+
+ static void * RunSendPing(void * d);
+ static void * RunRecvPing(void * d);
+
+ string errorStr;
+
+ multimap<uint32_t, time_t> pingIP;
+ list<uint32_t> ipToAdd;
+ list<uint32_t> ipToDel;
+
+ pthread_mutex_t mutex;
+};
+//-----------------------------------------------------------------------------
+#endif
+
+
--- /dev/null
+#include <stdio.h>
+#include <vector>
+#include <string>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "pinger.h"
+
+using namespace std;
+
+in_addr_t addr;
+
+//-----------------------------------------------------------------------------
+void AddRemoveTest(STG_PINGER & pinger)
+{
+addr = inet_addr("192.168.1.2");
+pinger.AddIP(*(uint32_t*)&addr);
+
+addr = inet_addr("192.168.1.2");
+pinger.AddIP(*(uint32_t*)&addr);
+
+sleep(2);
+pinger.PrintAllIP();
+printf("tree size=%d\n", pinger.GetPingIPNum());
+sleep(5);
+pinger.PrintAllIP();
+
+addr = inet_addr("192.168.1.2");
+pinger.DelIP(*(uint32_t*)&addr);
+printf("DelIP\n");
+sleep(10);
+//pinger.PrintAllIP();
+printf("tree size=%d\n", pinger.GetPingIPNum());
+sleep(3);
+pinger.PrintAllIP();
+printf("tree size=%d\n", pinger.GetPingIPNum());
+/*addr = inet_addr("192.168.1.2");
+pinger.DelIP(*(uint32_t*)&addr);
+
+addr = inet_addr("192.168.1.1");
+pinger.DelIP(*(uint32_t*)&addr);
+
+sleep(2);
+
+pinger.PrintAllIP();
+
+printf("tree size=%d\n", pinger.GetPingIPNum());
+sleep(5);
+
+addr = inet_addr("192.168.1.4");
+time_t t;
+if (pinger.GetIPTime(*(uint32_t*)&addr, &t) == 0)
+ {
+ printf("192.168.1.4 t=%lu\n", t);
+ }
+else
+ {
+ printf("192.168.1.4 not found\n");
+ }
+
+
+addr = inet_addr("192.168.1.5");
+if (pinger.GetIPTime(*(uint32_t*)&addr, &t) == 0)
+ {
+ printf("192.168.1.5 t=%lu\n", t);
+ }
+else
+ {
+ printf("192.168.1.5 not found\n");
+ }
+
+
+pinger.PrintAllIP();
+addr = inet_addr("192.168.1.3");
+if (pinger.GetIPTime(*(uint32_t*)&addr, &t))
+ {
+ printf("IP not present\n");
+ }
+else
+ {
+ printf("Ping time:\n");
+ }*/
+
+}
+//-----------------------------------------------------------------------------
+void StressTest(STG_PINGER & pinger)
+{
+
+for (int i = 1; i <= 200; i++)
+ {
+ char s[15];
+ sprintf(s, "192.168.1.%d", i);
+ addr = inet_addr(s);
+ pinger.AddIP(*(uint32_t*)&addr);
+ }
+
+sleep(5);
+pinger.PrintAllIP();
+printf("tree size=%d\n", pinger.GetPingIPNum());
+
+for (int i = 1; i <= 200; i++)
+ {
+ char s[15];
+ sprintf(s, "192.168.1.%d", i);
+ addr = inet_addr(s);
+ pinger.DelIP(*(uint32_t*)&addr);
+ }
+
+/*addr = inet_addr("192.168.1.2");
+pinger.AddIP(*(uint32_t*)&addr);
+
+addr = inet_addr("192.168.1.3");
+pinger.AddIP(*(uint32_t*)&addr);*/
+
+sleep(3);
+pinger.PrintAllIP();
+printf("tree size=%d\n", pinger.GetPingIPNum());
+sleep(1);
+}
+//-----------------------------------------------------------------------------
+int main()
+{
+vector<PING_IP_TIME> pingIP;
+
+STG_PINGER pinger(2);
+
+if (pinger.Start())
+ {
+ printf("%s\n", pinger.GetStrError().c_str());
+ }
+
+
+//AddRemoveTest(pinger);
+StressTest(pinger);
+
+pinger.Stop();
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
+
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.6 2010/01/21 13:02:12 faust Exp $
+###############################################################################
+
+LIB_NAME = script_executer
+PROG = lib$(LIB_NAME)
+
+SRCS = script_executer.cpp
+
+INCS = script_executer.h
+
+include ../Makefile.in
--- /dev/null
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <cstring>
+#include <cerrno>
+#include <csignal>
+
+#include "script_executer.h"
+
+using namespace std;
+
+#define MAX_SCRIPT_LEN (1100)
+
+static int msgid;
+static bool nonstop;
+
+//-----------------------------------------------------------------------------
+struct SCRIPT_DATA
+{
+ long mtype;
+ char script[MAX_SCRIPT_LEN];
+} sd;
+//-----------------------------------------------------------------------------
+static void CatchUSR1Executer(int)
+{
+nonstop = false;
+}
+//-----------------------------------------------------------------------------
+int ScriptExec(const string & str)
+{
+if (str.length() >= MAX_SCRIPT_LEN)
+ return -1;
+
+int ret;
+strncpy(sd.script, str.c_str(), MAX_SCRIPT_LEN);
+sd.mtype = 1;
+ret = msgsnd(msgid, (void *)&sd, MAX_SCRIPT_LEN, 0);
+if (ret < 0)
+ {
+ return -1;
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+#ifdef LINUX
+void Executer(int, int msgID, pid_t pid, char * procName)
+#else
+void Executer(int, int msgID, pid_t pid, char *)
+#endif
+{
+msgid = msgID;
+if (pid)
+ return;
+nonstop = true;
+
+#ifdef LINUX
+memset(procName, 0, strlen(procName));
+strcpy(procName, "stg-exec");
+#else
+setproctitle("stg-exec");
+#endif
+
+struct sigaction newsa, oldsa;
+sigset_t sigmask;
+
+sigemptyset(&sigmask);
+sigaddset(&sigmask, SIGTERM);
+newsa.sa_handler = SIG_IGN;
+newsa.sa_mask = sigmask;
+newsa.sa_flags = 0;
+sigaction(SIGTERM, &newsa, &oldsa);
+
+sigemptyset(&sigmask);
+sigaddset(&sigmask, SIGINT);
+newsa.sa_handler = SIG_IGN;
+newsa.sa_mask = sigmask;
+newsa.sa_flags = 0;
+sigaction(SIGINT, &newsa, &oldsa);
+
+sigemptyset(&sigmask);
+sigaddset(&sigmask, SIGHUP);
+newsa.sa_handler = SIG_IGN;
+newsa.sa_mask = sigmask;
+newsa.sa_flags = 0;
+sigaction(SIGHUP, &newsa, &oldsa);
+
+sigemptyset(&sigmask);
+sigaddset(&sigmask, SIGUSR1);
+newsa.sa_handler = CatchUSR1Executer;
+newsa.sa_mask = sigmask;
+newsa.sa_flags = 0;
+sigaction(SIGUSR1, &newsa, &oldsa);
+
+int ret;
+
+SCRIPT_DATA sd;
+
+while (nonstop)
+ {
+ sd.mtype = 1;
+ ret = msgrcv(msgid, &sd, MAX_SCRIPT_LEN, 0, 0);
+
+ if (ret < 0)
+ {
+ usleep(20000);
+ continue;
+ }
+ int ret = system(sd.script);
+ if (ret == -1)
+ {
+ // Fork failed
+ }
+ }
+}
+//-----------------------------------------------------------------------------
+
+
--- /dev/null
+#ifndef SCRIPT_EXECUTER_H
+#define SCRIPT_EXECUTER_H
+
+#include <string>
+#include <sys/types.h>
+
+int ScriptExec(const std::string & str);
+void Executer(int msgKey, int msgID, pid_t pid, char * procName);
+
+#endif //SCRIPT_EXECUTER_H
+
+
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.9 2010/08/18 07:47:03 faust Exp $
+###############################################################################
+
+LIB_NAME = srvconf
+PROG = lib$(LIB_NAME)
+
+STGLIBS = -lstg_common \
+ -lstg_crypto
+LIBS = -lexpat
+
+SRCS = netunit.cpp \
+ parser.cpp \
+ servconf.cpp
+
+INCS = servconf.h \
+ netunit.h
+
+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 : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+ /*
+ $Revision: 1.6 $
+ $Date: 2009/02/06 10:25:54 $
+ $Author: faust $
+ */
+
+//---------------------------------------------------------------------------
+#include <stdio.h>
+#include <string.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+
+#include "netunit.h"
+#include "common.h"
+
+//---------------------------------------------------------------------------
+
+#define SEND_DATA_ERROR "Send data error!"
+#define RECV_DATA_ANSWER_ERROR "Recv data answer error!"
+#define UNKNOWN_ERROR "Unknown error!"
+#define CONNECT_FAILED "Connect failed!"
+#define INCORRECT_LOGIN "Incorrect login!"
+#define INCORRECT_HEADER "Incorrect header!"
+#define SEND_LOGIN_ERROR "Send login error!"
+#define RECV_LOGIN_ANSWER_ERROR "Recv login answer error!"
+#define CREATE_SOCKET_ERROR "Create socket failed!"
+#define WSASTARTUP_FAILED "WSAStartup failed!"
+#define SEND_HEADER_ERROR "Send header error!"
+#define RECV_HEADER_ANSWER_ERROR "Recv header answer error!"
+
+//---------------------------------------------------------------------------
+NETTRANSACT::NETTRANSACT()
+{
+RxCallBack = NULL;
+}
+//-----------------------------------------------------------------------------
+void NETTRANSACT::EnDecryptInit(const char * passwd, int passwdLen, BLOWFISH_CTX *ctx)
+{
+unsigned char * keyL = NULL;//[PASSWD_LEN]; // ��� ������
+
+keyL = new unsigned char[PASSWD_LEN];
+
+memset(keyL, 0, PASSWD_LEN);
+
+strncpy((char *)keyL, passwd, PASSWD_LEN);
+
+Blowfish_Init(ctx, keyL, PASSWD_LEN);
+
+delete[] keyL;
+}
+//-----------------------------------------------------------------------------
+void NETTRANSACT::Encrypt(char * d, const char * s, BLOWFISH_CTX *ctx)
+{
+/*unsigned char ss[8];
+
+memcpy(ss, s, 8);
+
+Blowfish_Encrypt(ctx, (uint32_t *)ss, (uint32_t *)(ss + 4));
+
+memcpy(d, ss, 8);*/
+EncodeString(d, s, ctx);
+
+}
+//---------------------------------------------------------------------------
+void NETTRANSACT::Decrypt(char * d, const char * s, BLOWFISH_CTX *ctx)
+{
+/*unsigned char ss[8];
+
+memcpy(ss, s, 8);
+
+Blowfish_Decrypt(ctx, (uint32_t *)ss, (uint32_t *)(ss + 4));
+
+memcpy(d, ss, 8);*/
+DecodeString(d, s, ctx);
+
+}
+//---------------------------------------------------------------------------
+int NETTRANSACT::Connect()
+{
+int ret;
+
+outerSocket = socket(PF_INET, SOCK_STREAM, 0);
+if (outerSocket < 0)
+ {
+ strcpy(errorMsg, CREATE_SOCKET_ERROR);
+ return st_conn_fail;
+ }
+
+memset(&outerAddr, 0, sizeof(outerAddr));
+memset(&localAddr, 0, sizeof(localAddr));
+
+struct hostent he;
+struct hostent * phe;
+
+unsigned long ip;
+ip = inet_addr(server);
+
+if (ip == INADDR_NONE)
+ {
+ phe = gethostbyname(server);
+ if (phe == NULL)
+ {
+ sprintf(errorMsg, "DNS error.\nCan not reslove %s", server);
+ return st_dns_err;
+ }
+
+ memcpy(&he, phe, sizeof(he));
+ ip = *((long*)he.h_addr_list[0]);
+ }
+outerAddr.sin_family = AF_INET;
+outerAddr.sin_port = htons(port);
+outerAddr.sin_addr.s_addr = ip;
+
+ret = connect(outerSocket, (struct sockaddr*)&outerAddr, sizeof(outerAddr));
+
+if (ret < 0)
+ {
+ strcpy(errorMsg, CONNECT_FAILED);
+ close(outerSocket);
+ return st_conn_fail;
+ }
+return st_ok;
+}
+//---------------------------------------------------------------------------
+int NETTRANSACT::Disconnect()
+{
+close(outerSocket);
+return 0;
+}
+//---------------------------------------------------------------------------
+int NETTRANSACT::Transact(const char * data)
+{
+int ret;
+if ((ret = TxHeader()) != st_ok)
+ {
+ Disconnect();
+ return ret;
+ }
+
+if ((ret = RxHeaderAnswer()) != st_ok)
+ {
+ Disconnect();
+ return ret;
+ }
+
+if ((ret = TxLogin()) != st_ok)
+ {
+ Disconnect();
+ return ret;
+ }
+
+if ((ret = RxLoginAnswer()) != st_ok)
+ {
+ Disconnect();
+ return ret;
+ }
+
+if ((ret = TxLoginS()) != st_ok)
+ {
+ Disconnect();
+ return ret;
+ }
+
+if ((ret = RxLoginSAnswer()) != st_ok)
+ {
+ Disconnect();
+ return ret;
+ }
+
+if ((ret = TxData(data)) != st_ok)
+ {
+ Disconnect();
+ return ret;
+ }
+
+if ((ret = RxDataAnswer()) != st_ok)
+ {
+ Disconnect();
+ return ret;
+ }
+
+return st_ok;
+}
+//---------------------------------------------------------------------------
+int NETTRANSACT::TxHeader()
+{
+int ret;
+ret = send(outerSocket, STG_HEADER, strlen(STG_HEADER), 0);
+if (ret <= 0)
+ {
+ strcpy(errorMsg, SEND_HEADER_ERROR);
+ return st_send_fail;
+ }
+
+return st_ok;
+}
+//---------------------------------------------------------------------------
+int NETTRANSACT::RxHeaderAnswer()
+{
+char buffer[sizeof(STG_HEADER)+1];
+int ret;//, we;
+
+ret = recv(outerSocket, buffer, strlen(OK_HEADER), 0);
+if (ret <= 0)
+ {
+ //we = WSAGetLastError();
+ strcpy(errorMsg, RECV_HEADER_ANSWER_ERROR);
+ return st_recv_fail;
+ }
+
+if (strncmp(OK_HEADER, buffer, strlen(OK_HEADER)) == 0)
+ {
+ return st_ok;
+ }
+else
+ {
+ if (strncmp(ERR_HEADER, buffer, strlen(ERR_HEADER)) == 0)
+ {
+ strcpy(errorMsg, INCORRECT_HEADER);
+ return st_header_err;
+ }
+ else
+ {
+ strcpy(errorMsg, UNKNOWN_ERROR);
+ return st_unknown_err;
+ }
+ }
+}
+//---------------------------------------------------------------------------
+int NETTRANSACT::TxLogin()
+{
+char loginZ[ADM_LOGIN_LEN];
+int ret;
+
+memset(loginZ, 0, ADM_LOGIN_LEN);
+strncpy(loginZ, login, ADM_LOGIN_LEN);
+ret = send(outerSocket, loginZ, ADM_LOGIN_LEN, 0);
+
+if (ret <= 0)
+ {
+ strcpy(errorMsg, SEND_LOGIN_ERROR);
+ return st_send_fail;
+ }
+
+return st_ok;
+}
+//---------------------------------------------------------------------------
+int NETTRANSACT::RxLoginAnswer()
+{
+char buffer[sizeof(OK_LOGIN)+1];
+int ret;//, we;
+
+ret = recv(outerSocket, buffer, strlen(OK_LOGIN), 0);
+if (ret <= 0)
+ {
+ strcpy(errorMsg, RECV_LOGIN_ANSWER_ERROR);
+ return st_recv_fail;
+ }
+
+if (strncmp(OK_LOGIN, buffer, strlen(OK_LOGIN)) == 0)
+ {
+ return st_ok;
+ }
+else
+ {
+ if (strncmp(ERR_LOGIN, buffer, strlen(ERR_LOGIN)) == 0)
+ {
+ strcpy(errorMsg, INCORRECT_LOGIN);
+ return st_login_err;
+ }
+ else
+ {
+ strcpy(errorMsg, UNKNOWN_ERROR);
+ return st_unknown_err;
+ }
+ }
+}
+//---------------------------------------------------------------------------
+int NETTRANSACT::TxLoginS()
+{
+char loginZ[ADM_LOGIN_LEN];
+char ct[ENC_MSG_LEN];
+int ret;
+
+memset(loginZ, 0, ADM_LOGIN_LEN);
+strncpy(loginZ, login, ADM_LOGIN_LEN);
+
+BLOWFISH_CTX ctx;
+EnDecryptInit(password, PASSWD_LEN, &ctx);
+
+for (int j = 0; j < ADM_LOGIN_LEN / ENC_MSG_LEN; j++)
+ {
+ Encrypt(ct, loginZ + j*ENC_MSG_LEN, &ctx);
+ ret = send(outerSocket, ct, ENC_MSG_LEN, 0);
+ if (ret <= 0)
+ {
+ strcpy(errorMsg, SEND_LOGIN_ERROR);
+ return st_send_fail;
+ }
+ }
+
+return st_ok;
+}
+//---------------------------------------------------------------------------
+int NETTRANSACT::RxLoginSAnswer()
+{
+char buffer[sizeof(OK_LOGINS)+1];
+int ret;
+
+ret = recv(outerSocket, buffer, strlen(OK_LOGINS), 0);
+if (ret <= 0)
+ {
+ strcpy(errorMsg, RECV_LOGIN_ANSWER_ERROR);
+ return st_recv_fail;
+ }
+
+if (strncmp(OK_LOGINS, buffer, strlen(OK_LOGINS)) == 0)
+ {
+ return st_ok;
+ }
+else
+ {
+ if (strncmp(ERR_LOGINS, buffer, strlen(ERR_LOGINS)) == 0)
+ {
+ strcpy(errorMsg, INCORRECT_LOGIN);
+ return st_logins_err;
+ }
+ else
+ {
+ strcpy(errorMsg, UNKNOWN_ERROR);
+ return st_unknown_err;
+ }
+ }
+}
+//---------------------------------------------------------------------------
+int NETTRANSACT::TxData(const char * text)
+{
+char textZ[ENC_MSG_LEN];
+char ct[ENC_MSG_LEN];
+int ret;
+int j;
+
+int n = strlen(text) / ENC_MSG_LEN;
+int r = strlen(text) % ENC_MSG_LEN;
+
+BLOWFISH_CTX ctx;
+EnDecryptInit(password, PASSWD_LEN, &ctx);
+
+for (j = 0; j < n; j++)
+ {
+ strncpy(textZ, text + j*ENC_MSG_LEN, ENC_MSG_LEN);
+ Encrypt(ct, textZ, &ctx);
+ ret = send(outerSocket, ct, ENC_MSG_LEN, 0);
+ if (ret <= 0)
+ {
+ strcpy(errorMsg, SEND_DATA_ERROR);
+ return st_send_fail;
+ }
+ }
+
+memset(textZ, 0, ENC_MSG_LEN);
+if (r)
+ strncpy(textZ, text + j*ENC_MSG_LEN, ENC_MSG_LEN);
+
+EnDecryptInit(password, PASSWD_LEN, &ctx);
+
+Encrypt(ct, textZ, &ctx);
+ret = send(outerSocket, ct, ENC_MSG_LEN, 0);
+if (ret <= 0)
+ {
+ strcpy(errorMsg, SEND_DATA_ERROR);
+ return st_send_fail;
+ }
+
+return st_ok;
+}
+//---------------------------------------------------------------------------
+int NETTRANSACT::TxData(char * data)
+{
+char buff[ENC_MSG_LEN];
+char buffS[ENC_MSG_LEN];
+char passwd[ADM_PASSWD_LEN];
+
+strncpy(passwd, password, ADM_PASSWD_LEN);
+memset(buff, 0, ENC_MSG_LEN);
+
+int l = strlen(data)/ENC_MSG_LEN;
+if (strlen(data)%ENC_MSG_LEN)
+ l++;
+
+BLOWFISH_CTX ctx;
+EnDecryptInit(passwd, PASSWD_LEN, &ctx);
+
+for (int j = 0; j < l; j++)
+ {
+ strncpy(buff, &data[j*ENC_MSG_LEN], ENC_MSG_LEN);
+ Encrypt(buffS, buff, &ctx);
+ send(outerSocket, buffS, ENC_MSG_LEN, 0);
+ }
+
+return 0;
+}
+//---------------------------------------------------------------------------
+int NETTRANSACT::RxDataAnswer()
+{
+int n = 0;
+int ret;
+char bufferS[ENC_MSG_LEN];
+char buffer[ENC_MSG_LEN + 1];
+
+BLOWFISH_CTX ctx;
+EnDecryptInit(password, PASSWD_LEN, &ctx);
+
+while (1)
+ {
+ ret = recv(outerSocket, &bufferS[n++], 1, 0);
+ if (ret <= 0)
+ {
+ close(outerSocket);
+ strcpy(errorMsg, RECV_DATA_ANSWER_ERROR);
+ return st_recv_fail;
+ }
+
+ if (n == ENC_MSG_LEN)
+ {
+
+ n = 0;
+ Decrypt(buffer, bufferS, &ctx);
+ buffer[ENC_MSG_LEN] = 0;
+
+ answerList.push_back(buffer);
+
+ for (int j = 0; j < ENC_MSG_LEN; j++)
+ {
+ if (buffer[j] == 0)
+ {
+ if (RxCallBack)
+ if (st_ok != RxCallBack(dataRxCallBack, &answerList))
+ {
+ return st_xml_parse_error;
+ }
+ return st_ok;
+ }
+ }
+ }
+ }
+}
+//---------------------------------------------------------------------------
+void NETTRANSACT::SetLogin(const char * l)
+{
+strncpy(login, l, ADM_LOGIN_LEN);
+}
+//---------------------------------------------------------------------------
+void NETTRANSACT::SetPassword(const char * p)
+{
+strncpy(password, p, ADM_PASSWD_LEN);
+}
+//---------------------------------------------------------------------------
+void NETTRANSACT::SetServer(const char * serverName)
+{
+strncpy(server, serverName, SERVER_NAME_LEN);
+}
+//---------------------------------------------------------------------------
+void NETTRANSACT::SetServerPort(short unsigned p)
+{
+port = p;
+}
+//---------------------------------------------------------------------------
+void NETTRANSACT::SetRxCallback(void * data, RxCallback_t cb)
+{
+RxCallBack = cb;
+dataRxCallBack = data;
+}
+//---------------------------------------------------------------------------
+char * NETTRANSACT::GetError()
+{
+return errorMsg;
+}
+//---------------------------------------------------------------------------
+void NETTRANSACT::Reset()
+{
+answerList.clear();
+}
+//---------------------------------------------------------------------------
+
--- /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>
+ */
+
+ /*
+ $Revision: 1.6 $
+ $Date: 2010/02/11 12:32:53 $
+ $Author: faust $
+ */
+
+#ifndef NetUnitH
+#define NetUnitH
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <list>
+#include <string>
+
+#include "common.h"
+#include "blowfish.h"
+
+#define STG_HEADER "SG04"
+#define OK_HEADER "OKHD"
+#define ERR_HEADER "ERHD"
+#define OK_LOGIN "OKLG"
+#define ERR_LOGIN "ERLG"
+#define OK_LOGINS "OKLS"
+#define ERR_LOGINS "ERLS"
+
+// äÌÉÎÎÁ ÛÉÆÒÕÅÍÏÇÏ É ÐÅÒÅÄÁ×ÁÅÍÏÇ ÚÁ ÏÄÉÎ ÒÁÚ ÂÌÏËÁ ÉÎÆÏÒÍÁÃÉÉ
+#define ENC_MSG_LEN (8)
+
+#define MAX_ERR_STR_LEN (64)
+
+typedef int(*RxCallback_t)(void *, std::list<std::string> *);
+
+enum status
+{
+st_ok = 0,
+st_conn_fail,
+st_send_fail,
+st_recv_fail,
+st_header_err,
+st_login_err,
+st_logins_err,
+st_data_err,
+st_unknown_err,
+st_dns_err,
+st_xml_parse_error,
+st_data_error
+};
+
+enum CONF_STATE
+{
+confHdr = 0,
+confLogin,
+confLoginCipher,
+confData
+};
+//---------------------------------------------------------------------------
+class NETTRANSACT
+{
+public:
+ NETTRANSACT();
+ int Transact(const char * data);
+ char *GetError();
+
+ void SetRxCallback(void * data, RxCallback_t);
+
+ void SetServer(const char * serverName);
+ void SetServerPort(short unsigned p);
+
+ void SetLogin(const char * l);
+ void SetPassword(const char * p);
+ ////////////////////////////////////////////
+ int Connect();
+ int Disconnect();
+ void Reset();
+private:
+ int TxHeader();
+ int RxHeaderAnswer();
+
+ int TxLogin();
+ int RxLoginAnswer();
+
+ int TxLoginS();
+ int RxLoginSAnswer();
+
+ int TxData(const char * text);
+ int TxData(char * data);
+ int RxDataAnswer();
+
+ void Encrypt(char * d, const char * s, BLOWFISH_CTX *ctx);
+ void EnDecryptInit(const char * passwd, int passwdLen, BLOWFISH_CTX *ctx);
+ void Decrypt(char * d, const char * s, BLOWFISH_CTX *ctx);
+
+ //unsigned ip;
+ char server[SERVER_NAME_LEN];
+ short unsigned port;
+ char login[ADM_LOGIN_LEN];
+ char password[ADM_PASSWD_LEN];
+ int outerSocket;
+ int localSocket;
+ struct sockaddr_in outerAddr;
+ struct sockaddr_in localAddr;
+ int error;
+ std::list<std::string> answerList;
+ RxCallback_t RxCallBack;
+ void * dataRxCallBack;
+ char errorMsg[MAX_ERR_STR_LEN];
+};
+//---------------------------------------------------------------------------
+#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>
+ */
+
+ /*
+ $Revision: 1.18 $
+ $Date: 2010/08/04 00:40:00 $
+ $Author: faust $
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string>
+
+#include "common.h"
+//#include "srvconf_common.h"
+#include "stg_const.h"
+#include "servconf.h"
+
+using namespace std;
+
+//-----------------------------------------------------------------------------
+PARSER::PARSER()
+{
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+PARSER_GET_USERS::PARSER_GET_USERS()
+{
+depth = 0;
+error = false;
+RecvUserDataCb = NULL;
+}
+//-----------------------------------------------------------------------------
+void PARSER_GET_USERS::Reset()
+{
+
+}
+//-----------------------------------------------------------------------------
+int PARSER_GET_USERS::ParseStart(const char *el, const char **attr)
+{
+depth++;
+if (depth == 1)
+ {
+ ParseUsers(el, attr);
+ }
+
+if (depth == 2)
+ {
+ ParseUser(el, attr);
+ }
+
+if (depth == 3)
+ {
+ ParseUserParams(el, attr);
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+void PARSER_GET_USERS::ParseEnd(const char *)
+{
+depth--;
+if (depth == 1)
+ {
+ if (RecvUserDataCb)
+ {
+ RecvUserDataCb(&user, userDataCb);
+ }
+ }
+}
+//-----------------------------------------------------------------------------
+void PARSER_GET_USERS::ParseUsers(const char * el, const char ** attr)
+{
+if (strcasecmp(el, "users") == 0)
+ {
+ if (*attr != NULL)
+ return;
+ return;
+ }
+}
+//-----------------------------------------------------------------------------
+void PARSER_GET_USERS::ParseUser(const char * el, const char ** attr)
+{
+if (el && attr[0])
+ {
+ if (strcasecmp(el, "user") != 0)
+ {
+ return;
+ }
+
+ if (strcasecmp(attr[0], "login") != 0)
+ {
+ return;
+ }
+ user.login = attr[1];
+ }
+}
+//-----------------------------------------------------------------------------
+void PARSER_GET_USERS::ParseUserParams(const char * el, const char ** attr)
+{
+if (strcasecmp(el, "cash") == 0)
+ {
+ if (strtodouble2(attr[1], user.cash) < 0)
+ {
+ return;
+ }
+ }
+
+/*if (strcasecmp(el, "LastCash") == 0)
+ {
+ if (strtodouble2(attr[1], user.lastCash) < 0)
+ {
+ MessageDlg("Error in answer", mtError, TMsgDlgButtons() << mbOK, 0);
+ return 0;
+ }
+ }*/
+
+/*if (strcasecmp(el, "LastActivityTime") == 0)
+ {
+ if (strtol(attr[1], user.lastActivityTime) < 0)
+ {
+ MessageDlg("Error in answer", mtError, TMsgDlgButtons() << mbOK, 0);
+ return 0;
+ }
+ }*/
+
+
+/*if (strcasecmp(el, "LastTimeCash") == 0)
+ {
+ if (strtol(attr[1], user.lastTimeCash) < 0)
+ {
+ MessageDlg("Error in answer", mtError, TMsgDlgButtons() << mbOK, 0);
+ return 0;
+ }
+ }*/
+
+/*if (strcasecmp(el, "CashExpire") == 0)
+ {
+ if (strtol(attr[1], user.cashExpire) < 0)
+ {
+ MessageDlg("Error in answer", mtError, TMsgDlgButtons() << mbOK, 0);
+ return 0;
+ }
+ }*/
+
+if (strcasecmp(el, "credit") == 0)
+ {
+ if (strtodouble2(attr[1], user.credit) < 0)
+ {
+ return;
+ }
+ }
+
+/*if (strcasecmp(el, "freemb") == 0)
+ {
+ if (strtodouble2(attr[1], user.freeMb) < 0)
+ {
+ MessageDlg("Error in answer", mtError, TMsgDlgButtons() << mbOK, 0);
+ return 0;
+ }
+ }*/
+
+if (strcasecmp(el, "down") == 0)
+ {
+ if (str2x(attr[1], user.down) < 0)
+ {
+ return;
+ }
+ }
+
+if (strcasecmp(el, "passive") == 0)
+ {
+ if (str2x(attr[1], user.passive) < 0)
+ {
+ return;
+ }
+ }
+
+if (strcasecmp(el, "disableDetailStat") == 0)
+ {
+ if (str2x(attr[1], user.disableDetailStat) < 0)
+ {
+ return;
+ }
+ }
+
+
+if (strcasecmp(el, "status") == 0)
+ {
+ if (str2x(attr[1], user.connected) < 0)
+ {
+ return;
+ }
+ }
+
+if (strcasecmp(el, "aonline") == 0)
+ {
+ if (str2x(attr[1], user.alwaysOnline) < 0)
+ {
+ return;
+ }
+ }
+
+if (strcasecmp(el, "currip") == 0)
+ {
+ user.ip = inet_addr(attr[1]);
+ }
+
+if (strcasecmp(el, "ip") == 0)
+ {
+ user.ips = attr[1];
+ }
+
+
+if (strcasecmp(el, "tariff") == 0)
+ {
+ //KOIToWin(user.tariff, *(attr+1), TARIFF_LEN);
+ user.tariff = attr[1];
+ return;
+ }
+
+if (strcasecmp(el, "password") == 0)
+ {
+ user.password = *(attr+1);
+ return;
+ }
+
+if (strcasecmp(el, "iface") == 0)
+ {
+ user.iface = attr[1];
+ return;
+ }
+
+/*if (strcasecmp(el, "name") == 0)
+ {
+ / *char nameEnc[REALNM_LEN * 2 + 1];
+ char name[REALNM_LEN];
+ strncpy(nameEnc, attr[1], REALNM_LEN * 2 + 1);
+ Decode21(name, nameEnc);
+ KOIToWin(user.realName, name, REALNM_LEN);* /
+ Decode21str(user.realName, attr[1]);
+ return;
+ }*/
+
+if (strcasecmp(el, "address") == 0)
+ {
+ /*char addressEnc[ADDR_LEN * 2 + 1];
+ char address[ADDR_LEN];
+ strncpy(addressEnc, attr[1], ADDR_LEN * 2 + 1);
+ Decode21(address, addressEnc);
+ KOIToWin(user.address, address, ADDR_LEN);*/
+ Decode21str(user.address, attr[1]);
+ return;
+ }
+
+if (strcasecmp(el, "phone") == 0)
+ {
+ /*char phoneEnc[PHONE_LEN * 2 + 1];
+ char phone[PHONE_LEN];
+ strncpy(phoneEnc, attr[1], PHONE_LEN * 2 + 1);
+ Decode21(phone, phoneEnc);
+ KOIToWin(user.phone, phone, PHONE_LEN);*/
+ Decode21str(user.phone, attr[1]);
+ return;
+ }
+
+if (strcasecmp(el, "note") == 0)
+ {
+ /*char noteEnc[NOTE_LEN * 2 + 1];
+ char note[NOTE_LEN];
+ strncpy(noteEnc, attr[1], NOTE_LEN * 2 + 1);*/
+ //KOIToWin(user.note, note, NOTE_LEN);
+ //user.note = note;
+ Decode21str(user.note, attr[1]);
+ return;
+ }
+
+if (strcasecmp(el, "email") == 0)
+ {
+ /*char emailEnc[EMAIL_LEN * 2 + 1];
+ char email[EMAIL_LEN];
+ strncpy(emailEnc, attr[1], EMAIL_LEN * 2 + 1);
+ Decode21(email, emailEnc);
+ //KOIToWin(user.email, email, EMAIL_LEN);
+ user.email = email;*/
+ Decode21str(user.email, attr[1]);
+ return;
+ }
+
+if (strcasecmp(el, "group") == 0)
+ {
+ /*char groupEnc[GROUP_LEN * 2 + 1];
+ char group[GROUP_LEN];
+ strncpy(groupEnc, attr[1], GROUP_LEN * 2 + 1);
+ Decode21(group, groupEnc);
+ //KOIToWin(user.group, group, GROUP_LEN);
+ user.group = group;*/
+ Decode21str(user.group, attr[1]);
+ return;
+ }
+
+if (strcasecmp(el, "traff") == 0)
+ {
+ ParseUserLoadStat(el, attr);
+ return;
+ }
+
+}
+//-----------------------------------------------------------------------------
+void PARSER_GET_USERS::ParseUserLoadStat(const char *, const char ** attr)
+{
+int i = 0;
+char dir[6];
+while (attr[i])
+ {
+ for (int j = 0; j < DIR_NUM; j++)
+ {
+ sprintf(dir, "MU%d", j);
+ if (strcasecmp(dir, attr[i]) == 0)
+ {
+ str2x(attr[i+1], user.stat.mu[j]);
+ break;
+ }
+ }
+ for (int j = 0; j < DIR_NUM; j++)
+ {
+ sprintf(dir, "MD%d", j);
+ if (strcasecmp(dir, attr[i]) == 0)
+ {
+ str2x(attr[i+1], user.stat.md[j]);
+ break;
+ }
+ }
+ for (int j = 0; j < DIR_NUM; j++)
+ {
+ sprintf(dir, "SU%d", j);
+ if (strcasecmp(dir, attr[i]) == 0)
+ {
+ str2x(attr[i+1], user.stat.su[j]);
+ break;
+ }
+ }
+ for (int j = 0; j < DIR_NUM; j++)
+ {
+ sprintf(dir, "SD%d", j);
+ if (strcasecmp(dir, attr[i]) == 0)
+ {
+ str2x(attr[i+1], user.stat.sd[j]);
+ break;
+ }
+ }
+ i+=2;
+ }
+return;
+}
+//-----------------------------------------------------------------------------
+void PARSER_GET_USERS::SetUserDataRecvCb(RecvUserDataCb_t f, void * data)
+{
+RecvUserDataCb = f;
+userDataCb = data;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+PARSER_GET_USER::PARSER_GET_USER()
+{
+depth = 0;
+error = false;
+RecvUserDataCb = NULL;
+}
+//-----------------------------------------------------------------------------
+void PARSER_GET_USER::Reset()
+{
+
+}
+//-----------------------------------------------------------------------------
+int PARSER_GET_USER::ParseStart(const char *el, const char **attr)
+{
+depth++;
+if (depth == 1)
+ {
+ ParseUser(el, attr);
+ }
+
+if (depth == 2)
+ {
+ ParseUserParams(el, attr);
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+void PARSER_GET_USER::ParseEnd(const char *)
+{
+depth--;
+if (depth == 0)
+ {
+ if (RecvUserDataCb)
+ {
+ RecvUserDataCb(&user, userDataCb);
+ }
+ }
+}
+//-----------------------------------------------------------------------------
+void PARSER_GET_USER::ParseUser(const char * el, const char ** attr)
+{
+if (strcasecmp(el, "user") == 0)
+ {
+ if (strcasecmp(attr[1], "error") == 0)
+ user.login = "";
+ return;
+ }
+}
+//-----------------------------------------------------------------------------
+struct ParsedStringParams
+{
+string * param;
+string paramName;
+};
+//-----------------------------------------------------------------------------
+struct ParsedDoubleParams
+{
+double * param;
+string paramName;
+};
+//-----------------------------------------------------------------------------
+void PARSER_GET_USER::ParseUserParams(const char * el, const char ** attr)
+{
+//printf("PARSER_GET_USER::ParseUserParams el=%s attr[1]=%s\n", el, attr[1]);
+
+if (strcasecmp(el, "login") == 0)
+ {
+ user.login = attr[1];
+ }
+
+
+/*if (strcasecmp(el, "LastActivityTime") == 0)
+ {
+ if (strtol(attr[1], user.lastActivityTime) < 0)
+ {
+ MessageDlg("Error in answer", mtError, TMsgDlgButtons() << mbOK, 0);
+ return 0;
+ }
+ }
+
+
+if (strcasecmp(el, "LastTimeCash") == 0)
+ {
+ if (strtol(attr[1], user.lastTimeCash) < 0)
+ {
+ MessageDlg("Error in answer", mtError, TMsgDlgButtons() << mbOK, 0);
+ return 0;
+ }
+ }
+
+if (strcasecmp(el, "CashExpire") == 0)
+ {
+ if (strtol(attr[1], user.cashExpire) < 0)
+ {
+ MessageDlg("Error in answer", mtError, TMsgDlgButtons() << mbOK, 0);
+ return 0;
+ }
+ }
+*/
+
+if (strcasecmp(el, "down") == 0)
+ {
+ if (str2x(attr[1], user.down) < 0)
+ {
+ return;
+ }
+ }
+
+if (strcasecmp(el, "passive") == 0)
+ {
+ if (str2x(attr[1], user.passive) < 0)
+ {
+ return;
+ }
+ }
+
+if (strcasecmp(el, "disableDetailStat") == 0)
+ {
+ if (str2x(attr[1], user.disableDetailStat) < 0)
+ {
+ return;
+ }
+ }
+
+
+if (strcasecmp(el, "status") == 0)
+ {
+ if (str2x(attr[1], user.connected) < 0)
+ {
+ return;
+ }
+ }
+
+if (strcasecmp(el, "aonline") == 0)
+ {
+ if (str2x(attr[1], user.alwaysOnline) < 0)
+ {
+ return;
+ }
+ }
+
+if (strcasecmp(el, "currip") == 0)
+ {
+ user.ip = inet_addr(attr[1]);
+ }
+
+for (int i = 0; i < USERDATA_NUM; i++)
+ {
+ string num;
+ x2str(i, num);
+ string udName = "UserData" + num;
+ if (strcasecmp(el, udName.c_str()) == 0)
+ {
+ Decode21str(user.userData[i], attr[1]);
+ return;
+ }
+ }
+
+ParsedStringParams psp[] =
+{
+ {&user.ips, "ip"},
+ {&user.tariff, "tariff"},
+ {&user.password, "password"},
+ {&user.iface, "iface"},
+};
+
+for (unsigned i = 0; i < sizeof(psp)/sizeof(ParsedStringParams); i++)
+ {
+ if (strcasecmp(el, psp[i].paramName.c_str()) == 0)
+ {
+ *psp[i].param = attr[1];
+ return;
+ }
+ }
+
+ParsedStringParams pspEnc[] =
+{
+ {&user.note, "note"},
+ {&user.email, "email"},
+ {&user.group, "group"},
+ {&user.name, "name"},
+ {&user.address, "address"},
+ {&user.phone, "phone"}
+};
+
+for (unsigned i = 0; i < sizeof(pspEnc)/sizeof(ParsedStringParams); i++)
+ {
+ if (strcasecmp(el, pspEnc[i].paramName.c_str()) == 0)
+ {
+ Decode21str(*pspEnc[i].param, attr[1]);
+ return;
+ }
+ }
+
+ParsedDoubleParams pdp[] =
+{
+ {&user.cash, "cash"},
+ {&user.credit, "credit"},
+ {&user.lastCash, "lastCash"},
+ {&user.prepaidTraff, "freemb"},
+};
+
+for (unsigned i = 0; i < sizeof(pdp)/sizeof(ParsedDoubleParams); i++)
+ {
+ if (strcasecmp(el, pdp[i].paramName.c_str()) == 0)
+ {
+ strtodouble2(attr[1], *pdp[i].param);
+ return;
+ }
+ }
+
+if (strcasecmp(el, "traff") == 0)
+ {
+ ParseUserLoadStat(el, attr);
+ return;
+ }
+}
+//-----------------------------------------------------------------------------
+void PARSER_GET_USER::ParseUserLoadStat(const char *, const char ** attr)
+{
+int i = 0;
+char dir[6];
+while (attr[i])
+ {
+ for (int j = 0; j < DIR_NUM; j++)
+ {
+ sprintf(dir, "MU%d", j);
+ if (strcasecmp(dir, attr[i]) == 0)
+ {
+ str2x(attr[i+1], user.stat.mu[j]);
+ break;
+ }
+ }
+ for (int j = 0; j < DIR_NUM; j++)
+ {
+ sprintf(dir, "MD%d", j);
+ if (strcasecmp(dir, attr[i]) == 0)
+ {
+ str2x(attr[i+1], user.stat.md[j]);
+ break;
+ }
+ }
+ for (int j = 0; j < DIR_NUM; j++)
+ {
+ sprintf(dir, "SU%d", j);
+ if (strcasecmp(dir, attr[i]) == 0)
+ {
+ str2x(attr[i+1], user.stat.su[j]);
+ break;
+ }
+ }
+ for (int j = 0; j < DIR_NUM; j++)
+ {
+ sprintf(dir, "SD%d", j);
+ if (strcasecmp(dir, attr[i]) == 0)
+ {
+ str2x(attr[i+1], user.stat.sd[j]);
+ break;
+ }
+ }
+ i+=2;
+ }
+return;
+}
+//-----------------------------------------------------------------------------
+void PARSER_GET_USER::SetUserDataRecvCb(RecvUserDataCb_t f, void * data)
+{
+RecvUserDataCb = f;
+userDataCb = data;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+PARSER_GET_SERVER_INFO::PARSER_GET_SERVER_INFO()
+{
+depth = 0;
+error = false;
+RecvServerInfoDataCb = NULL;
+}
+//-----------------------------------------------------------------------------
+void PARSER_GET_SERVER_INFO::Reset()
+{
+
+}
+//-----------------------------------------------------------------------------
+int PARSER_GET_SERVER_INFO::ParseStart(const char *el, const char **attr)
+{
+depth++;
+if (depth == 1)
+ {
+ if (strcasecmp(el, "ServerInfo") != 0)
+ {
+ //printf("%s\n", el);
+ }
+ }
+else
+ {
+ if (depth == 2)
+ {
+ if (strcasecmp(el, "uname") == 0)
+ {
+ ParseUname(attr);
+ return 0;
+ }
+ if (strcasecmp(el, "version") == 0)
+ {
+ ParseServerVersion(attr);
+ return 0;
+ }
+ if (strcasecmp(el, "tariff") == 0)
+ {
+ ParseTariffType(attr);
+ return 0;
+ }
+ if (strcasecmp(el, "dir_num") == 0)
+ {
+ ParseDirNum(attr);
+ return 0;
+ }
+ if (strcasecmp(el, "users_num") == 0)
+ {
+ ParseUsersNum(attr);
+ return 0;
+ }
+ if (strcasecmp(el, "tariff_num") == 0)
+ {
+ ParseTariffsNum(attr);
+ return 0;
+ }
+
+ for (int j = 0; j < DIR_NUM; j++)
+ {
+ char str[16];
+ sprintf(str, "dir_name_%d", j);
+ if (strcasecmp(el, str) == 0)
+ {
+ ParseDirName(attr, j);
+ }
+ }
+
+ }
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+void PARSER_GET_SERVER_INFO::ParseEnd(const char *)
+{
+depth--;
+if (depth == 0)
+ {
+ RecvServerInfoDataCb(&serverInfo, serverInfoDataCb);
+ }
+}
+//-----------------------------------------------------------------------------
+/*void PARSER_GET_SERVER_INFO::ParseServerInfo(const char * el, const char ** attr)
+ {
+ }*/
+//-----------------------------------------------------------------------------
+void PARSER_GET_SERVER_INFO::SetServerInfoRecvCb(RecvServerInfoDataCb_t f, void * data)
+{
+RecvServerInfoDataCb = f;
+serverInfoDataCb = data;
+}
+//-----------------------------------------------------------------------------
+void PARSER_GET_SERVER_INFO::ParseUname(const char ** attr)
+{
+if (strcmp(*attr, "value") == 0)
+ serverInfo.uname = attr[1];
+}
+//-----------------------------------------------------------------------------
+void PARSER_GET_SERVER_INFO::ParseServerVersion(const char ** attr)
+{
+if (strcmp(*attr, "value") == 0)
+ serverInfo.version = attr[1];
+}
+//-----------------------------------------------------------------------------
+void PARSER_GET_SERVER_INFO::ParseUsersNum(const char ** attr)
+{
+if (strcmp(*attr, "value") == 0)
+ {
+ if (str2x(attr[1], serverInfo.usersNum) < 0)
+ {
+ serverInfo.usersNum = -1;
+ return;
+ }
+ }
+}
+//-----------------------------------------------------------------------------
+void PARSER_GET_SERVER_INFO::ParseTariffsNum(const char ** attr)
+{
+if (strcmp(*attr, "value") == 0)
+ {
+ if (str2x(attr[1], serverInfo.tariffNum) < 0)
+ {
+ serverInfo.tariffNum = -1;
+ return;
+ }
+ }
+}
+//-----------------------------------------------------------------------------
+void PARSER_GET_SERVER_INFO::ParseTariffType(const char ** attr)
+{
+if (strcmp(*attr, "value") == 0)
+ {
+ if (str2x(attr[1], serverInfo.tariffType) < 0)
+ {
+ serverInfo.tariffType = -1;
+ return;
+ }
+ }
+}
+//-----------------------------------------------------------------------------
+void PARSER_GET_SERVER_INFO::ParseDirNum(const char **attr)
+{
+if (strcasecmp(*attr, "value") == 0)
+ {
+ if (str2x(attr[1], serverInfo.dirNum) < 0)
+ {
+ serverInfo.dirNum = -1;
+ return;
+ }
+ }
+}
+//-----------------------------------------------------------------------------
+void PARSER_GET_SERVER_INFO::ParseDirName(const char **attr, int d)
+{
+if (strcmp(attr[0], "value") == 0)
+ {
+ char str[2*DIRNAME_LEN + 1];
+ Decode21(str, attr[1]);
+ serverInfo.dirName[d] = str;
+ }
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+PARSER_CHG_USER::PARSER_CHG_USER()
+{
+depth = 0;
+error = false;
+RecvChgUserCb = NULL;
+}
+//-----------------------------------------------------------------------------
+int PARSER_CHG_USER::ParseStart(const char *el, const char **attr)
+{
+depth++;
+if (depth == 1)
+ {
+ if (strcasecmp(el, "SetUser") == 0)
+ {
+ ParseAnswer(el, attr);
+ }
+ else if (strcasecmp(el, "DelUser") == 0)
+ {
+ ParseAnswer(el, attr);
+ }
+ else if (strcasecmp(el, "AddUser") == 0)
+ {
+ ParseAnswer(el, attr);
+ }
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+void PARSER_CHG_USER::ParseEnd(const char *)
+{
+depth--;
+}
+//-----------------------------------------------------------------------------
+void PARSER_CHG_USER::Reset()
+{
+
+}
+//-----------------------------------------------------------------------------
+void PARSER_CHG_USER::ParseAnswer(const char *, const char **attr)
+{
+if (RecvChgUserCb)
+ {
+ RecvChgUserCb(attr[1], chgUserCbData);
+ }
+}
+//-----------------------------------------------------------------------------
+void PARSER_CHG_USER::SetChgUserRecvCb(RecvChgUserCb_t f, void * data)
+{
+RecvChgUserCb = f;
+chgUserCbData = data;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+PARSER_CHECK_USER::PARSER_CHECK_USER()
+{
+depth = 0;
+error = false;
+RecvCheckUserCb = NULL;
+}
+//-----------------------------------------------------------------------------
+int PARSER_CHECK_USER::ParseStart(const char *el, const char **attr)
+{
+depth++;
+if (depth == 1)
+ {
+ if (strcasecmp(el, "CheckUser") == 0)
+ {
+ //printf("el=%s attr[0]=%s attr[1]=%s\n", el, attr[0], attr[1]);
+ ParseAnswer(el, attr);
+ }
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+void PARSER_CHECK_USER::ParseEnd(const char *)
+{
+depth--;
+}
+//-----------------------------------------------------------------------------
+void PARSER_CHECK_USER::ParseAnswer(const char *, const char **attr)
+{
+if (RecvCheckUserCb)
+ {
+ RecvCheckUserCb(attr[1], checkUserCbData);
+ }
+}
+//-----------------------------------------------------------------------------
+void PARSER_CHECK_USER::SetCheckUserRecvCb(RecvCheckUserCb_t f, void * data)
+{
+RecvCheckUserCb = f;
+checkUserCbData = data;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+PARSER_SEND_MESSAGE::PARSER_SEND_MESSAGE()
+{
+depth = 0;
+error = false;
+RecvSendMessageCb = NULL;
+}
+//-----------------------------------------------------------------------------
+int PARSER_SEND_MESSAGE::ParseStart(const char *el, const char **attr)
+{
+depth++;
+if (depth == 1)
+ {
+ if (strcasecmp(el, "SendMessageResult") == 0)
+ {
+ ParseAnswer(el, attr);
+ }
+ }
+return 0;
+}
+//-----------------------------------------------------------------------------
+void PARSER_SEND_MESSAGE::ParseEnd(const char *)
+{
+depth--;
+}
+//-----------------------------------------------------------------------------
+void PARSER_SEND_MESSAGE::Reset()
+{
+
+}
+//-----------------------------------------------------------------------------
+void PARSER_SEND_MESSAGE::ParseAnswer(const char *, const char **attr)
+{
+if (RecvSendMessageCb)
+ RecvSendMessageCb(attr[1], sendMessageCbData);
+}
+//-----------------------------------------------------------------------------
+void PARSER_SEND_MESSAGE::SetSendMessageRecvCb(RecvSendMessageCb_t f, void * data)
+{
+RecvSendMessageCb = f;
+sendMessageCbData = data;
+}
+//-----------------------------------------------------------------------------
+
--- /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>
+ */
+
+ /*
+ $Revision: 1.8 $
+ $Date: 2010/08/04 00:40:38 $
+ $Author: faust $
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "servconf.h"
+
+using namespace std;
+
+//-----------------------------------------------------------------------------
+int AnsRecv(void * data, list<string> * list1)
+{
+//NODE * node;
+SERVCONF * sc;
+char ans[ENC_MSG_LEN + 1];
+int len, done = 0;
+
+sc = (SERVCONF*)data;
+
+XML_ParserReset(sc->parser, NULL);
+XML_SetElementHandler(sc->parser, Start, End);
+XML_SetUserData(sc->parser, data);
+
+//loop parsing
+list<string>::iterator node;
+node = list1->begin();
+
+if (node == list1->end())
+ {
+ return st_ok;
+ }
+
+while (node != list1->end())
+ {
+ strncpy(ans, node->c_str(), ENC_MSG_LEN);
+ ans[ENC_MSG_LEN] = 0;
+ //printf("---> %s\n", ans);
+ len = strlen(ans);
+
+ if (XML_Parse(sc->parser, ans, len, done) == XML_STATUS_ERROR)
+ {
+ snprintf(sc->errorMsg, MAX_ERR_STR_LEN, "XML parse error at line %d: %s",
+ static_cast<int>(XML_GetCurrentLineNumber(sc->parser)),
+ XML_ErrorString(XML_GetErrorCode(sc->parser)));
+ printf(sc->errorMsg, "XML parse error at line %d: %s",
+ XML_GetCurrentLineNumber(sc->parser),
+ XML_ErrorString(XML_GetErrorCode(sc->parser)));
+ return st_xml_parse_error;
+ }
+ ++node;
+
+ }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+void Start(void *data, const char *el, const char **attr)
+{
+SERVCONF * sc;
+sc = (SERVCONF*)data;
+sc->Start(el, attr);
+}
+//-----------------------------------------------------------------------------
+void End(void *data, const char *el)
+{
+SERVCONF * sc;
+sc = (SERVCONF*)data;
+sc->End(el);
+}
+//-----------------------------------------------------------------------------
+SERVCONF::SERVCONF()
+{
+parser = XML_ParserCreate(NULL);
+parseDepth = 0;
+}
+//-----------------------------------------------------------------------------
+void SERVCONF::SetServer(const char * server)
+{
+nt.SetServer(server);
+}
+//-----------------------------------------------------------------------------
+void SERVCONF::SetPort(uint16_t port)
+{
+nt.SetServerPort(port);
+}
+//-----------------------------------------------------------------------------
+void SERVCONF::SetAdmLogin(const char * login)
+{
+nt.SetLogin(login);
+}
+//-----------------------------------------------------------------------------
+void SERVCONF::SetAdmPassword(const char * password)
+{
+nt.SetPassword(password);
+}
+//-----------------------------------------------------------------------------
+int SERVCONF::GetUser(const char * l)
+{
+char request[255];
+snprintf(request, 255, "<GetUser login=\"%s\"/>", l);
+int ret;
+
+currParser = &parserGetUser;
+((PARSER_GET_USER*)currParser)->SetUserDataRecvCb(RecvGetUserDataCb, getUserDataDataCb);
+
+nt.Reset();
+nt.SetRxCallback(this, AnsRecv);
+
+if ((ret = nt.Connect()) != st_ok)
+ {
+ strncpy(errorMsg, nt.GetError(), MAX_ERR_STR_LEN);
+ return ret;
+ }
+if ((ret = nt.Transact(request)) != st_ok)
+ {
+ strncpy(errorMsg, nt.GetError(), MAX_ERR_STR_LEN);
+ return ret;
+ }
+if ((ret = nt.Disconnect()) != st_ok)
+ {
+ strncpy(errorMsg, nt.GetError(), MAX_ERR_STR_LEN);
+ return ret;
+ }
+
+return st_ok;
+}
+//-----------------------------------------------------------------------------
+int SERVCONF::GetUsers()
+{
+char request[] = "<GetUsers/>";
+int ret;
+
+currParser = &parserGetUsers;
+((PARSER_GET_USERS*)currParser)->SetUserDataRecvCb(RecvUserDataCb, getUsersDataDataCb);
+
+nt.Reset();
+nt.SetRxCallback(this, AnsRecv);
+
+if ((ret = nt.Connect()) != st_ok)
+ {
+ strncpy(errorMsg, nt.GetError(), MAX_ERR_STR_LEN);
+ return ret;
+ }
+if ((ret = nt.Transact(request)) != st_ok)
+ {
+ strncpy(errorMsg, nt.GetError(), MAX_ERR_STR_LEN);
+ return ret;
+ }
+if ((ret = nt.Disconnect()) != st_ok)
+ {
+ strncpy(errorMsg, nt.GetError(), MAX_ERR_STR_LEN);
+ return ret;
+ }
+
+return st_ok;
+}
+//-----------------------------------------------------------------------------
+int SERVCONF::SendMessage(const char * login, const char * message, int prio)
+{
+char request[1000];
+char msg[500];
+Encode12(msg, message, strlen(message));
+snprintf(request, 1000, "<Message login=\"%s\" priority=\"%d\" text=\"%s\"/>", login, prio, msg);
+int ret;
+
+currParser = &parserSendMessage;
+parserSendMessage.SetSendMessageRecvCb(RecvSendMessageCb, sendMessageDataCb);
+
+nt.Reset();
+nt.SetRxCallback(this, AnsRecv);
+
+if ((ret = nt.Connect()) != st_ok)
+ {
+ strncpy(errorMsg, nt.GetError(), MAX_ERR_STR_LEN);
+ return ret;
+ }
+if ((ret = nt.Transact(request)) != st_ok)
+ {
+ strncpy(errorMsg, nt.GetError(), MAX_ERR_STR_LEN);
+ return ret;
+ }
+if ((ret = nt.Disconnect()) != st_ok)
+ {
+ strncpy(errorMsg, nt.GetError(), MAX_ERR_STR_LEN);
+ return ret;
+ }
+
+return st_ok;
+}
+//-----------------------------------------------------------------------------
+int SERVCONF::GetServerInfo()
+{
+char request[] = "<GetServerInfo/>";
+int ret;
+
+currParser = &parserServerInfo;
+((PARSER_GET_SERVER_INFO*)currParser)->SetServerInfoRecvCb(RecvServerInfoDataCb, getServerInfoDataCb);
+
+nt.Reset();
+nt.SetRxCallback(this, AnsRecv);
+
+if ((ret = nt.Connect()) != st_ok)
+ {
+ strncpy(errorMsg, nt.GetError(), MAX_ERR_STR_LEN);
+ return ret;
+ }
+if ((ret = nt.Transact(request)) != st_ok)
+ {
+ strncpy(errorMsg, nt.GetError(), MAX_ERR_STR_LEN);
+ return ret;
+ }
+if ((ret = nt.Disconnect()) != st_ok)
+ {
+ strncpy(errorMsg, nt.GetError(), MAX_ERR_STR_LEN);
+ return ret;
+ }
+
+return st_ok;
+}
+//-----------------------------------------------------------------------------
+int SERVCONF::ChgUser(const char * request)
+{
+int ret;
+
+currParser = &parserChgUser;
+((PARSER_CHG_USER*)currParser)->SetChgUserRecvCb(RecvChgUserCb, chgUserDataCb);
+
+nt.Reset();
+nt.SetRxCallback(this, AnsRecv);
+
+if ((ret = nt.Connect()) != st_ok)
+ {
+ strncpy(errorMsg, nt.GetError(), MAX_ERR_STR_LEN);
+ printfd(__FILE__, "Error on connect: '%s'\n", errorMsg);
+ return ret;
+ }
+if ((ret = nt.Transact(request)) != st_ok)
+ {
+ strncpy(errorMsg, nt.GetError(), MAX_ERR_STR_LEN);
+ printfd(__FILE__, "Error on transact: '%s'\n", errorMsg);
+ return ret;
+ }
+if ((ret = nt.Disconnect()) != st_ok)
+ {
+ strncpy(errorMsg, nt.GetError(), MAX_ERR_STR_LEN);
+ printfd(__FILE__, "Error on disconnect: '%s'\n", errorMsg);
+ return ret;
+ }
+
+return st_ok;
+}
+//-----------------------------------------------------------------------------
+// TODO: remove this shit!
+//-----------------------------------------------------------------------------
+int SERVCONF::MsgUser(const char * request)
+{
+int ret;
+
+currParser = &parserSendMessage;
+parserSendMessage.SetSendMessageRecvCb(RecvSendMessageCb, sendMessageDataCb);
+
+nt.Reset();
+nt.SetRxCallback(this, AnsRecv);
+
+if ((ret = nt.Connect()) != st_ok)
+ {
+ strncpy(errorMsg, nt.GetError(), MAX_ERR_STR_LEN);
+ return ret;
+ }
+if ((ret = nt.Transact(request)) != st_ok)
+ {
+ strncpy(errorMsg, nt.GetError(), MAX_ERR_STR_LEN);
+ return ret;
+ }
+if ((ret = nt.Disconnect()) != st_ok)
+ {
+ strncpy(errorMsg, nt.GetError(), MAX_ERR_STR_LEN);
+ return ret;
+ }
+
+return st_ok;
+}
+//-----------------------------------------------------------------------------
+int SERVCONF::CheckUser(const char * login, const char * password)
+{
+char request[255];
+snprintf(request, 255, "<CheckUser login=\"%s\" password=\"%s\"/>", login, password);
+int ret;
+
+currParser = &parserCheckUser;
+((PARSER_CHECK_USER*)currParser)->SetCheckUserRecvCb(RecvCheckUserCb, checkUserDataCb);
+
+nt.Reset();
+nt.SetRxCallback(this, AnsRecv);
+
+if ((ret = nt.Connect()) != st_ok)
+ {
+ strncpy(errorMsg, nt.GetError(), MAX_ERR_STR_LEN);
+ return ret;
+ }
+if ((ret = nt.Transact(request)) != st_ok)
+ {
+ strncpy(errorMsg, nt.GetError(), MAX_ERR_STR_LEN);
+ return ret;
+ }
+if ((ret = nt.Disconnect()) != st_ok)
+ {
+ strncpy(errorMsg, nt.GetError(), MAX_ERR_STR_LEN);
+ return ret;
+ }
+
+return st_ok;
+}
+//-----------------------------------------------------------------------------
+int SERVCONF::Start(const char *el, const char **attr)
+{
+currParser->ParseStart(el, attr);
+return 0;
+}
+//-----------------------------------------------------------------------------
+void SERVCONF::End(const char *el)
+{
+currParser->ParseEnd(el);
+}
+//-----------------------------------------------------------------------------
+void SERVCONF::SetUserDataRecvCb(RecvUserDataCb_t f, void * data)
+{
+RecvUserDataCb = f;
+getUsersDataDataCb = data;
+}
+//-----------------------------------------------------------------------------
+void SERVCONF::SetGetUserDataRecvCb(RecvUserDataCb_t f, void * data)
+{
+RecvGetUserDataCb = f; //GET_USER
+getUserDataDataCb = data;
+}
+//-----------------------------------------------------------------------------
+void SERVCONF::SetServerInfoRecvCb(RecvServerInfoDataCb_t f, void * data)
+{
+RecvServerInfoDataCb = f;
+getServerInfoDataCb = data;
+}
+//-----------------------------------------------------------------------------
+void SERVCONF::SetChgUserCb(RecvChgUserCb_t f, void * data)
+{
+RecvChgUserCb = f;
+chgUserDataCb = data;
+}
+//-----------------------------------------------------------------------------
+void SERVCONF::SetCheckUserCb(RecvCheckUserCb_t f, void * data)
+{
+RecvCheckUserCb = f;
+checkUserDataCb = data;
+}
+//-----------------------------------------------------------------------------
+void SERVCONF::SetSendMessageCb(RecvSendMessageCb_t f, void * data)
+{
+RecvSendMessageCb = f;
+sendMessageDataCb = data;
+}
+//-----------------------------------------------------------------------------
+char * SERVCONF::GetStrError()
+{
+return errorMsg;
+}
+//-----------------------------------------------------------------------------
+int SERVCONF::GetError()
+{
+int e = error;
+error = 0;
+return e;
+}
+//-----------------------------------------------------------------------------
+
--- /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>
+ */
+
+ /*
+ $Revision: 1.10 $
+ $Date: 2009/03/17 09:52:35 $
+ $Author: faust $
+ */
+
+#ifndef SERVCONF_H
+#define SERVCONF_H
+
+#include "os_int.h"
+
+#include <expat.h>
+#include <list>
+#include <string>
+#include "netunit.h"
+#include "stg_const.h"
+
+void Start(void *data, const char *el, const char **attr);
+void End(void *data, const char *el);
+
+#define MAX_ERR_STR_LEN (64)
+#define IP_STRING_LEN (255)
+#define UNAME_LEN (256)
+#define SERV_VER_LEN (64)
+#define DIRNAME_LEN (16)
+
+//-----------------------------------------------------------------------------
+struct STAT
+{
+ long long su[DIR_NUM];
+ long long sd[DIR_NUM];
+ long long mu[DIR_NUM];
+ long long md[DIR_NUM];
+ double freeMb;
+};
+//-----------------------------------------------------------------------------
+struct SERVERINFO
+{
+ std::string version;
+ int tariffNum;
+ int tariffType;
+ int usersNum;
+ std::string uname;
+ int dirNum;
+ std::string dirName[DIR_NUM];
+};
+//-----------------------------------------------------------------------------
+struct USERDATA
+{
+ std::string login;
+ std::string password;
+ double cash;
+ double credit;
+ double lastCash;
+ double prepaidTraff;
+ int down;
+ int passive;
+ int disableDetailStat;
+ int connected;
+ int alwaysOnline;
+ uint32_t ip;
+ std::string ips;
+ std::string tariff;
+ std::string iface;
+ std::string group;
+ std::string note;
+ std::string email;
+ std::string name;
+ std::string address;
+ std::string phone;
+ STAT stat;
+ std::string userData[USERDATA_NUM];
+
+ struct USERDATA * next;
+};
+//-----------------------------------------------------------------------------
+typedef void(*RecvUserDataCb_t)(USERDATA * ud, void * data);
+typedef void(*RecvServerInfoDataCb_t)(SERVERINFO * si, void * data);
+typedef int(*RecvChgUserCb_t)(const char * asnwer, void * data);
+typedef int(*RecvCheckUserCb_t)(const char * answer, void * data);
+typedef int(*RecvSendMessageCb_t)(const char * answer, void * data);
+//-----------------------------------------------------------------------------
+struct ADMINDATA
+{
+ char login[ADM_LOGIN_LEN];
+};
+//-----------------------------------------------------------------------------
+class PARSER
+{
+public:
+ PARSER();
+ virtual ~PARSER(){};
+ virtual int ParseStart(const char *el, const char **attr) = 0;
+ virtual void ParseEnd(const char *el) = 0;
+ void Reset();
+ //virtual bool GetError() = 0;
+ //virtual void SetUserDataRecvCb(RecvUserDataCb_t) = 0;
+protected:
+ //RecvUserDataCb_t RecvUserDataCb;
+private:
+};
+//-----------------------------------------------------------------------------
+class PARSER_CHG_USER: public PARSER
+{
+public:
+ PARSER_CHG_USER();
+ int ParseStart(const char *el, const char **attr);
+ void ParseEnd(const char *el);
+ void Reset();
+ void ParseAnswer(const char *el, const char **attr);
+ void SetChgUserRecvCb(RecvChgUserCb_t, void * data);
+private:
+ RecvChgUserCb_t RecvChgUserCb;
+ void * chgUserCbData;
+ int depth;
+ bool error;
+};
+//-----------------------------------------------------------------------------
+class PARSER_CHECK_USER: public PARSER
+{
+public:
+ PARSER_CHECK_USER();
+ int ParseStart(const char *el, const char **attr);
+ void ParseEnd(const char *el);
+ void Reset();
+ void ParseAnswer(const char *el, const char **attr);
+ void SetCheckUserRecvCb(RecvCheckUserCb_t, void * data);
+private:
+ RecvCheckUserCb_t RecvCheckUserCb;
+ void * checkUserCbData;
+ int depth;
+ bool error;
+};
+//-----------------------------------------------------------------------------
+class PARSER_GET_USERS: public PARSER
+{
+public:
+ PARSER_GET_USERS();
+ int ParseStart(const char *el, const char **attr);
+ void ParseEnd(const char *el);
+ void Reset();
+ void ParseUsers(const char *el, const char **attr);
+ void ParseUser(const char *el, const char **attr);
+ void ParseUserParams(const char *el, const char **attr);
+ void ParseUserLoadStat(const char * el, const char ** attr);
+ //bool GetError();
+ void SetUserDataRecvCb(RecvUserDataCb_t, void * data);
+private:
+ RecvUserDataCb_t RecvUserDataCb;
+ void * userDataCb;
+ USERDATA user;
+ int depth;
+ bool error;
+};
+//-----------------------------------------------------------------------------
+class PARSER_GET_USER: public PARSER
+{
+public:
+ PARSER_GET_USER();
+ int ParseStart(const char *el, const char **attr);
+ void ParseEnd(const char *el);
+ void Reset();
+ void ParseUsers(const char *el, const char **attr);
+ void ParseUser(const char *el, const char **attr);
+ void ParseUserParams(const char *el, const char **attr);
+ void ParseUserLoadStat(const char * el, const char ** attr);
+ void SetUserDataRecvCb(RecvUserDataCb_t, void * data);
+private:
+ RecvUserDataCb_t RecvUserDataCb;
+ void * userDataCb;
+ USERDATA user;
+ int depth;
+ bool error;
+};
+//-----------------------------------------------------------------------------
+class PARSER_GET_SERVER_INFO: public PARSER
+{
+public:
+ PARSER_GET_SERVER_INFO();
+ int ParseStart(const char *el, const char **attr);
+ void ParseEnd(const char *el);
+ void Reset();
+ void ParseServerInfo(const char *el, const char **attr);
+ bool GetError();
+ void SetServerInfoRecvCb(RecvServerInfoDataCb_t, void * data);
+private:
+ void ParseUname(const char ** attr);
+ void ParseServerVersion(const char ** attr);
+ void ParseUsersNum(const char ** attr);
+ void ParseTariffsNum(const char ** attr);
+ void ParseTariffType(const char ** attr);
+ void ParseDirNum(const char **attr);
+ void ParseDirName(const char **attr, int d);
+
+ RecvServerInfoDataCb_t RecvServerInfoDataCb;
+ void * serverInfoDataCb;
+ USERDATA user;
+ int depth;
+ bool error;
+ SERVERINFO serverInfo;
+};
+//-----------------------------------------------------------------------------
+class PARSER_SEND_MESSAGE: public PARSER
+{
+public:
+ PARSER_SEND_MESSAGE();
+ int ParseStart(const char *el, const char **attr);
+ void ParseEnd(const char *el);
+ void Reset();
+ void ParseAnswer(const char *el, const char **attr);
+ void SetSendMessageRecvCb(RecvSendMessageCb_t, void * data);
+private:
+ RecvSendMessageCb_t RecvSendMessageCb;
+ void * sendMessageCbData;
+ int depth;
+ bool error;
+};
+//-----------------------------------------------------------------------------
+class SERVCONF
+{
+public:
+ SERVCONF();
+ void SetServer(const char * server);
+ void SetPort(uint16_t port);
+
+ void SetAdmLogin(const char * login);
+ void SetAdmPassword(const char * password);
+
+ void SetUserDataRecvCb(RecvUserDataCb_t, void * data);
+ void SetServerInfoRecvCb(RecvServerInfoDataCb_t, void * data);
+ void SetChgUserCb(RecvChgUserCb_t, void * data);
+ void SetCheckUserCb(RecvCheckUserCb_t, void * data);
+ void SetGetUserDataRecvCb(RecvUserDataCb_t, void * data);
+ void SetSendMessageCb(RecvSendMessageCb_t, void * data);
+
+ int GetUsers();
+ int GetUser(const char * login);
+ int ChgUser(const char * request);
+ // TODO: Remove this shit!
+ int MsgUser(const char * request);
+ int SendMessage(const char * login, const char * message, int prio);
+ int GetServerInfo();
+ int CheckUser(const char * login, const char * password);
+
+ char * GetStrError();
+ int GetError();
+ int Start(const char *el, const char **attr);
+ void End(const char *el);
+
+private:
+ PARSER * currParser;
+
+ PARSER_GET_USERS parserGetUsers;
+ PARSER_GET_USER parserGetUser;
+ PARSER_GET_SERVER_INFO parserServerInfo;
+ PARSER_CHG_USER parserChgUser;
+ PARSER_CHECK_USER parserCheckUser;
+ PARSER_SEND_MESSAGE parserSendMessage;
+
+ NETTRANSACT nt;
+ int parseDepth;
+ USERDATA ud;
+
+ char errorMsg[MAX_ERR_STR_LEN];
+ int error;
+ XML_Parser parser;
+
+ RecvUserDataCb_t RecvUserDataCb;
+ RecvUserDataCb_t RecvGetUserDataCb;
+ RecvServerInfoDataCb_t RecvServerInfoDataCb;
+ RecvChgUserCb_t RecvChgUserCb;
+ RecvCheckUserCb_t RecvCheckUserCb;
+ RecvSendMessageCb_t RecvSendMessageCb;
+
+ void * getUserDataDataCb;
+ void * getUsersDataDataCb;
+ void * getServerInfoDataCb;
+ void * chgUserDataCb;
+ void * checkUserDataCb;
+ void * sendMessageDataCb;
+
+ friend int AnsRecv(void * data, std::list<std::string> * list);
+};
+//-----------------------------------------------------------------------------
+
+#endif /* _SERVCONF_H_ */
+
+/* EOF */
+
--- /dev/null
+<!DOCTYPE Project SYSTEM "http://www.slickedit.com/dtd/vse/10.0/vpj.dtd">
+<Project
+ Version="10.0"
+ VendorName="SlickEdit"
+ WorkingDir="."
+ BuildSystem="automakefile"
+ BuildMakeFile="makefile">
+ <Config
+ Name="Debug"
+ Type="gnuc"
+ DebugCallbackName="gdb"
+ OutputFile="%bdservconf.a">
+ <Menu>
+ <Target
+ Name="Compile"
+ MenuCaption="&Compile"
+ OutputExts="*.o"
+ Dialog="_gnuc_options_form Compile"
+ RunFromDir="%rw"
+ CaptureOutputWith="ProcessBuffer"
+ SaveOption="SaveCurrent"
+ Deletable="0">
+ <Exec CmdLine='g++ -c %xup -pipe -g -Wall -ggdb -o "%bd%n%oe" %i "%f"'/>
+ </Target>
+ <Target
+ Name="Link"
+ MenuCaption="&Link"
+ ShowOnMenu="Never"
+ Dialog="_gnuc_options_form Link"
+ RunFromDir="%rw"
+ CaptureOutputWith="ProcessBuffer"
+ SaveOption="SaveCurrent"
+ Deletable="0">
+ <Exec CmdLine='g++ %xup -pipe -g -Wall -o "%o" %f %libs'/>
+ </Target>
+ <Target
+ Name="Build"
+ MenuCaption="&Build"
+ RunFromDir="%rw"
+ CaptureOutputWith="ProcessBuffer"
+ SaveOption="SaveWorkspaceFiles"
+ Deletable="0">
+ <Exec CmdLine="gmake -fMakefile"/>
+ </Target>
+ <Target
+ Name="Rebuild"
+ MenuCaption="&Rebuild"
+ RunFromDir="%rw"
+ CaptureOutputWith="ProcessBuffer"
+ Deletable="0">
+ <Exec/>
+ </Target>
+ <Target
+ Name="Debug"
+ MenuCaption="&Debug"
+ RunFromDir="%rw"
+ Deletable="0">
+ <Exec/>
+ </Target>
+ <Target
+ Name="Execute"
+ MenuCaption="E&xecute"
+ RunFromDir="%rw"
+ Deletable="0">
+ <Exec/>
+ </Target>
+ <Target
+ Name="dash"
+ MenuCaption="-"
+ RunFromDir="%rw">
+ <Exec/>
+ </Target>
+ <Target
+ Name="GNU C Options"
+ MenuCaption="GNU C &Options..."
+ ShowOnMenu="HideIfNoCmdLine"
+ Deletable="0">
+ <Exec
+ CmdLine="gnucoptions"
+ Type="Slick-C"/>
+ </Target>
+ </Menu>
+ <Libs>
+ <Lib File="/usr/lib/libexpat.a"/>
+ </Libs>
+ </Config>
+ <Config
+ Name="Release"
+ Type="gnuc"
+ DebugCallbackName="gdb"
+ OutputFile="%bdservconf.a">
+ <Menu>
+ <Target
+ Name="Compile"
+ MenuCaption="&Compile"
+ OutputExts="*.o"
+ Dialog="_gnuc_options_form Compile"
+ RunFromDir="%rw"
+ CaptureOutputWith="ProcessBuffer"
+ SaveOption="SaveCurrent"
+ Deletable="0">
+ <Exec CmdLine='g++ -c %xup -pipe -Wall -o "%bd%n%oe" %i "%f"'/>
+ </Target>
+ <Target
+ Name="Link"
+ MenuCaption="&Link"
+ ShowOnMenu="Never"
+ Dialog="_gnuc_options_form Link"
+ RunFromDir="%rw"
+ CaptureOutputWith="ProcessBuffer"
+ SaveOption="SaveCurrent"
+ Deletable="0">
+ <Exec CmdLine='g++ %xup -pipe -Wall -o "%o" %f %libs'/>
+ </Target>
+ <Target
+ Name="Build"
+ MenuCaption="&Build"
+ RunFromDir="%rw"
+ CaptureOutputWith="ProcessBuffer"
+ SaveOption="SaveWorkspaceFiles"
+ Deletable="0">
+ <Exec CmdLine="gmake -fMakefile"/>
+ </Target>
+ <Target
+ Name="Rebuild"
+ MenuCaption="&Rebuild"
+ RunFromDir="%rw"
+ CaptureOutputWith="ProcessBuffer"
+ Deletable="0">
+ <Exec/>
+ </Target>
+ <Target
+ Name="Debug"
+ MenuCaption="&Debug"
+ RunFromDir="%rw"
+ Deletable="0">
+ <Exec/>
+ </Target>
+ <Target
+ Name="Execute"
+ MenuCaption="E&xecute"
+ RunFromDir="%rw"
+ Deletable="0">
+ <Exec/>
+ </Target>
+ <Target
+ Name="dash"
+ MenuCaption="-"
+ RunFromDir="%rw">
+ <Exec/>
+ </Target>
+ <Target
+ Name="GNU C Options"
+ MenuCaption="GNU C &Options..."
+ ShowOnMenu="HideIfNoCmdLine"
+ Deletable="0">
+ <Exec
+ CmdLine="gnucoptions"
+ Type="Slick-C"/>
+ </Target>
+ </Menu>
+ <Libs>
+ <Lib File="/usr/lib/libexpat.a"/>
+ </Libs>
+ </Config>
+ <Files>
+ <Folder
+ Name="Source Files"
+ Filters="*.c;*.cc;*.cpp;*.cp;*.cxx;*.prg;*.pas;*.dpr;*.asm;*.s;*.bas;*.java;*.sc;*.e;*.cob;*.html;*.rc;*.tcl;*.py;*.pl">
+ <F N="netunit.cpp"/>
+ <F N="parser.cpp"/>
+ <F N="servconf.cpp"/>
+ <F N="test.cpp"/>
+ </Folder>
+ <Folder
+ Name="Header Files"
+ Filters="*.h;*.hh;*.hpp;*.hxx;*.inc;*.sh;*.cpy;*.if">
+ <F N="netunit.h"/>
+ <F N="servconf.h"/>
+ </Folder>
+ <Folder
+ Name="Resource Files"
+ Filters="*.ico;*.cur;*.dlg"/>
+ <Folder
+ Name="Bitmaps"
+ Filters="*.bmp;*.xpm;*.xbm"/>
+ <Folder
+ Name="Other Files"
+ Filters=""/>
+ </Files>
+</Project>
--- /dev/null
+[Global]
+Version=8
+[ProjectFiles]
+servconf.vpj
--- /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>
+ */
+
+ /*
+ $Revision: 1.6 $
+ $Date: 2008/02/09 16:22:18 $
+ $Author: nobunaga $
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "servconf.h"
+
+//-----------------------------------------------------------------------------
+void RecvUserData(USERDATA * ud, void * d)
+{
+// ôÕÔ ×Ù×ÏÄÉÔÓÑ ÞÁÓÔØ ÉÎÆÙ Ï ÐÏÌØÚÏ×ÁÔÅÌÅ, ÎÏ × ud ÐÅÒÅÄÁÅÔÓÑ ×ÓÑ ÉÎÆÁ
+printf("login: %s password :%s cash:%8.2f ip:%16s\n", ud->login, ud->password, ud->cash, ud->ips);
+}
+//-----------------------------------------------------------------------------
+void RecvServerInfoData(SERVERINFO * si, void * d)
+{
+// ôÕÔ ÔÏÖÅ ÔÏÌØËÏ ÞÁÓÔØ ÉÎÆÙ ×Ù×ÏÄÉÔÓÑ ÎÁ ÜËÒÁÎ
+printf("uname: %20s\n", si->uname);
+printf("version: %20s\n", si->version);
+printf("users: %20d\n", si->usersNum);
+for (int i = 0; i < DIR_NUM; i++)
+ {
+ printf("dir name 1: >%16s<\n", si->dirName[i]);
+ }
+}
+//-----------------------------------------------------------------------------
+int RecvSetUserAnswer(const char * ans, void * d)
+{
+printf("ans=%s\n", ans);
+if (strcasecmp("Ok", ans) == 0)
+ *((bool*)d) = true;
+else
+ *((bool*)d) = false;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int RecvCheckUserAnswer(const char * ans, void * d)
+{
+if (strcmp("Ok", ans) == 0)
+ *((bool*)d) = true;
+else
+ *((bool*)d) = false;
+return 0;
+}
+//-----------------------------------------------------------------------------
+int RecvSendMessageAnswer(const char * ans, void * d)
+{
+if (strcasecmp("Ok", ans) == 0)
+ *((bool*)d) = true;
+else
+ *((bool*)d) = false;
+return 0;
+}
+//-----------------------------------------------------------------------------
+int main()
+{
+SERVCONF sc;
+int ret;
+bool userExist = false;
+bool result = false;
+
+sc.SetServer("127.0.0.1"); // õÓÔÁÎÁ×ÌÉ×ÁÅÍ ÉÍÑ ÓÅÒ×ÅÒÁ Ó ËÏÔÏÒÇÏ ÚÁÂÉÒÁÔØ ÉÎÆÕ
+sc.SetPort(5555); // ÁÄÍÉÎÓËÉÊ ÐÏÒÔ ÓÅÒ×ÅÒÁÐÏÒÔ
+sc.SetAdmLogin("admin"); // ÷ÙÓÔÁ×ÌÑÅÍ ÌÏÇÉÎ É ÐÁÒÏÌØ ÁÄÍÉÎÁ
+sc.SetAdmPassword("123456");
+
+sc.SetUserDataRecvCb(RecvUserData, NULL); // óÔÁ×ÉÍ ËÏÌÂÜË-ÆÕÎËÃÉÉ, ËÏÔÏÒÙÅ
+sc.SetGetUserDataRecvCb(RecvUserData, NULL); // GET USER
+sc.SetServerInfoRecvCb(RecvServerInfoData, NULL); // ÂÕÄÕÔ ×ÙÚ×ÁÎÙ ÐÒÉ ÐÏÌÕÞÅÎÉÉ ÉÎÆÏÒÍÁÃÉÉ Ó ÓÅÒ×ÅÒÁ
+sc.SetChgUserCb(RecvSetUserAnswer, &userExist);
+sc.SetCheckUserCb(RecvCheckUserAnswer, &userExist);
+sc.SetSendMessageCb(RecvSendMessageAnswer, &result);
+printf("--------------- GetServerInfo ---------------\n");
+ret = sc.GetServerInfo(); // úÁÐÒÁÛÉ×ÁÅÍ ÉÎÆÕ Ï ÓÅÒ×ÅÒÅ. üÔÏ ÍÏÖÎÏ ÉÓÐÏÌØÚÏ×ÁÔØ
+if (ret != st_ok) // ÄÌÑ ÐÒÏ×ÅÒËÉ ÌÏÇÉÎÁ É ÐÁÒÏÌÑ ÁÄÍÉÎÁ
+ {
+ printf("error %d %s\n", ret, sc.GetStrError());
+ return 0;
+ }
+
+/*printf("--------------- GetUsers ---------------\n");
+ret = sc.GetUsers(); // úÁÐÒÁÛÉ×ÁÅÍ ÉÎÆÕ Ï ÐÏÌØÚÏ×ÁÔÅÌÅ
+if (ret != st_ok)
+ {
+ printf("error %d %s\n", ret, sc.GetStrError());
+ return 0;
+ }*/
+
+printf("--------------- SendMessage ---------------\n");
+ret = sc.SendMessage("zubr11", "test", 0); //
+if (ret != st_ok)
+ {
+ printf("error %d %s\n", ret, sc.GetStrError());
+ return 0;
+ }
+if (result)
+ printf("SendMessage ok\n");
+else
+ printf("SendMessage failed\n");
+
+return 0;
+
+printf("--------------- GetUser ---------------\n");
+ret = sc.GetUser("test"); // úÁÐÒÁÛÉ×ÁÅÍ ÉÎÆÕ Ï ÐÏÌØÚÏ×ÁÔÅÌÅ
+if (ret != st_ok)
+ {
+ printf("error %d %s\n", ret, sc.GetStrError());
+ return 0;
+ }
+
+return 0;
+
+printf("--------------- CheckUser ---------------\n");
+sc.CheckUser("test", "123456");
+if (userExist)
+ printf("login - ok\n");
+else
+ printf("login failed\n");
+
+printf("--------------- ChgUser ON ---------------\n");
+char req[1024];
+sprintf(req, "<SetUser> "
+ "<login value=\"test\"/> "
+ "<ips value=\"192.168.111.100\"/> "
+ "<aonline value=\"1\"/> "
+ "<iface value=\"ppp0\"/></SetUser>");
+sc.ChgUser(req);
+if (userExist)
+ printf("chg user ok\n");
+else
+ printf("chg user error\n");
+
+printf("--------------- ChgUser OFF ---------------\n");
+sprintf(req, "<SetUser> "
+ "<login value=\"test\"/> "
+ "<aonline value=\"0\"/> </SetUser>");
+
+sc.ChgUser(req);
+if (userExist)
+ printf("chg user ok\n");
+else
+ printf("chg user error\n");
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
--- /dev/null
+gcc -g3 test.cpp -L../../lib ./libsrvconf.a -lexpat ../../lib/libstg_common.so ../../lib/libstg_crypto.so -I../../include
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.2 2008/12/04 17:11:55 faust Exp $
+###############################################################################
+
+LIB_NAME = stg_locker
+PROG = lib$(LIB_NAME)
+
+SRCS = stg_locker.cpp
+
+INCS = stg_locker.h
+
+LIBS=$(LIB_THREAD)
+
+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 : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+/*
+ $Revision: 1.2 $
+ $Date: 2007/11/30 08:57:49 $
+ $Author: nobunaga $
+*/
+
+
+
+#include <pthread.h>
+#include "stg_locker.h"
+
+#ifdef DEBUG_LOCKER
+
+long long STG_LOCKER::id = 0;
+pthread_mutex_t STG_LOCKER::lockerMutex = PTHREAD_MUTEX_INITIALIZER;
+
+#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>
+ */
+
+/*
+ $Revision: 1.5 $
+ $Date: 2010/03/04 11:57:11 $
+ $Author: faust $
+*/
+
+
+#ifndef STG_LOCKER_H
+#define STG_LOCKER_H
+
+#include <pthread.h>
+#include "noncopyable.h"
+
+#ifdef DEBUG_LOCKER
+
+#include <iostream>
+#include <string>
+#include <pthread.h>
+
+#endif
+//-----------------------------------------------------------------------------
+class STG_LOCKER : private NONCOPYABLE
+{
+public:
+ #ifdef DEBUG_LOCKER
+ STG_LOCKER(pthread_mutex_t * m, const char * __file__, int __line__)
+ : mutex(m),
+ file(__file__),
+ line(__line__),
+ lockID(0)
+ #else
+ STG_LOCKER(pthread_mutex_t * m, const char *, int)
+ : mutex(m)
+ #endif
+ {
+ mutex = m;
+ #ifdef DEBUG_LOCKER
+ pthread_mutex_lock(&lockerMutex);
+ file = __file__;
+ line = __line__;
+ if (id == 0)
+ pthread_mutex_init(&lockerMutex, NULL);
+
+ lockID = ++id;
+ std::cout << "Lock: " << lockID << " " << file << ":" << line << " " << mutex << " " << pthread_self() << std::endl;
+ pthread_mutex_unlock(&lockerMutex);
+ #endif
+ pthread_mutex_lock(mutex);
+ };
+
+ ~STG_LOCKER()
+ {
+ pthread_mutex_unlock(mutex);
+ #ifdef DEBUG_LOCKER
+ pthread_mutex_lock(&lockerMutex);
+ std::cout << "Unlock: " << lockID << " " << file << ":" << line << " " << mutex << " " << pthread_self() << std::endl;
+ pthread_mutex_unlock(&lockerMutex);
+ #endif
+ };
+private:
+ pthread_mutex_t * mutex;
+ #ifdef DEBUG_LOCKER
+ std::string file;
+ int line;
+ static pthread_mutex_t lockerMutex;
+ static long long id;
+ long long lockID;
+ #endif
+};
+//-----------------------------------------------------------------------------
+
+#endif //STG_LOCKER_H
--- /dev/null
+###############################################################################
+# $Id: Makefile,v 1.3 2007/05/08 14:29:21 faust Exp $
+###############################################################################
+
+LIB_NAME = stg_logger
+PROG = lib$(LIB_NAME)
+
+SRCS = stg_logger.cpp
+
+INCS = stg_logger.h
+
+include ../Makefile.in
--- /dev/null
+#include <stdio.h>
+#include <stdarg.h>
+#include <syslog.h>
+
+#include "stg_logger.h"
+
+#ifdef STG_TIME
+extern const volatile time_t stgTime;
+#endif
+//-----------------------------------------------------------------------------
+STG_LOGGER & GetStgLogger()
+{
+static STG_LOGGER logger;
+return logger;
+}
+//-----------------------------------------------------------------------------
+STG_LOGGER::STG_LOGGER()
+ : fileName()
+{
+pthread_mutex_init(&mutex, NULL);
+}
+//-----------------------------------------------------------------------------
+STG_LOGGER::~STG_LOGGER()
+{
+pthread_mutex_destroy(&mutex);
+}
+//-----------------------------------------------------------------------------
+void STG_LOGGER::SetLogFileName(const std::string & fn)
+{
+STG_LOGGER_LOCKER lock(&mutex);
+fileName = fn;
+}
+//-----------------------------------------------------------------------------
+void STG_LOGGER::operator()(const char * fmt, ...)
+{
+STG_LOGGER_LOCKER lock(&mutex);
+
+char buff[2048];
+
+va_list vl;
+va_start(vl, fmt);
+vsnprintf(buff, sizeof(buff), fmt, vl);
+va_end(vl);
+
+FILE * f;
+if (!fileName.empty())
+ {
+ f = fopen(fileName.c_str(), "at");
+ if (f)
+ {
+ #ifdef STG_TIME
+ fprintf(f, "%s", LogDate(stgTime));
+ #else
+ fprintf(f, "%s", LogDate(time(NULL)));
+ #endif
+ fprintf(f, " -- ");
+ fprintf(f, "%s", buff);
+ fprintf(f, "\n");
+ fclose(f);
+ }
+ else
+ {
+ openlog("stg", LOG_NDELAY, LOG_USER);
+ syslog(LOG_CRIT, "%s", buff);
+ closelog();
+ }
+ }
+else
+ {
+ openlog("stg", LOG_NDELAY, LOG_USER);
+ syslog(LOG_CRIT, "%s", buff);
+ closelog();
+ }
+}
+//-----------------------------------------------------------------------------
+const char * STG_LOGGER::LogDate(time_t t)
+{
+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;
+}
+//-----------------------------------------------------------------------------
--- /dev/null
+#ifndef STG_LOGGER_H
+#define STG_LOGGER_H
+
+#include <pthread.h>
+#include <string>
+#include "noncopyable.h"
+
+const char * LogDate(time_t t);
+//-----------------------------------------------------------------------------
+class STG_LOGGER;
+STG_LOGGER & GetStgLogger();
+//-----------------------------------------------------------------------------
+class STG_LOGGER_LOCKER : private NONCOPYABLE
+{
+public:
+ STG_LOGGER_LOCKER(pthread_mutex_t * m) : mutex(m) { pthread_mutex_lock(mutex); };
+ ~STG_LOGGER_LOCKER() { pthread_mutex_unlock(mutex); };
+private:
+ pthread_mutex_t * mutex;
+};
+//-----------------------------------------------------------------------------
+class STG_LOGGER
+{
+friend STG_LOGGER & GetStgLogger();
+
+public:
+ ~STG_LOGGER();
+ void SetLogFileName(const std::string & fn);
+ void operator()(const char * fmt, ...);
+
+private:
+ STG_LOGGER();
+ const char * LogDate(time_t t);
+
+ std::string fileName;
+ pthread_mutex_t mutex;
+};
+//-----------------------------------------------------------------------------
+
+#endif //STG_LOGGER_H