]> git.stg.codes - stg.git/commitdiff
Break internal classes to interface and implementation
authorMaxim Mamontov <faust.madf@gmail.com>
Thu, 17 Mar 2011 10:24:14 +0000 (12:24 +0200)
committerMaxim Mamontov <faust.madf@gmail.com>
Thu, 17 Mar 2011 10:24:14 +0000 (12:24 +0200)
30 files changed:
include/admin.h [new file with mode: 0644]
include/admins.h [new file with mode: 0644]
include/tariff.h [new file with mode: 0644]
include/tariffs.h [new file with mode: 0644]
include/user.h [new file with mode: 0644]
include/users.h [new file with mode: 0644]
projects/stargazer/admin.cpp [deleted file]
projects/stargazer/admin.h [deleted file]
projects/stargazer/admin_impl.cpp [new file with mode: 0644]
projects/stargazer/admin_impl.h [new file with mode: 0644]
projects/stargazer/admins.cpp [deleted file]
projects/stargazer/admins.h [deleted file]
projects/stargazer/admins_impl.cpp [new file with mode: 0644]
projects/stargazer/admins_impl.h [new file with mode: 0644]
projects/stargazer/tariff.cpp [deleted file]
projects/stargazer/tariff.h [deleted file]
projects/stargazer/tariff_impl.cpp [new file with mode: 0644]
projects/stargazer/tariff_impl.h [new file with mode: 0644]
projects/stargazer/tariffs.cpp [deleted file]
projects/stargazer/tariffs.h [deleted file]
projects/stargazer/tariffs_impl.cpp [new file with mode: 0644]
projects/stargazer/tariffs_impl.h [new file with mode: 0644]
projects/stargazer/user.cpp [deleted file]
projects/stargazer/user.h [deleted file]
projects/stargazer/user_impl.cpp [new file with mode: 0644]
projects/stargazer/user_impl.h [new file with mode: 0644]
projects/stargazer/users.cpp [deleted file]
projects/stargazer/users.h [deleted file]
projects/stargazer/users_impl.cpp [new file with mode: 0644]
projects/stargazer/users_impl.h [new file with mode: 0644]

diff --git a/include/admin.h b/include/admin.h
new file mode 100644 (file)
index 0000000..7095bb6
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#ifndef ADMIN_H
+#define ADMIN_H
+
+#include <string>
+
+#include "admin_conf.h"
+#include "os_int.h"
+
+class ADMIN {
+public:
+      virtual ADMIN & operator=(const ADMIN &) = 0;
+      virtual ADMIN & operator=(const ADMIN_CONF &) = 0;
+      virtual bool    operator==(const ADMIN & rhs) const = 0;
+      virtual bool    operator!=(const ADMIN & rhs) const = 0;
+      virtual bool    operator<(const ADMIN & rhs) const = 0;
+      virtual bool    operator<=(const ADMIN & rhs) const = 0;
+
+      virtual const std::string & GetPassword() const = 0;
+      virtual const std::string & GetLogin() const = 0;
+      virtual PRIV const *        GetPriv() const = 0;
+      virtual uint16_t            GetPrivAsInt() const = 0;
+      virtual const ADMIN_CONF &  GetConf() const = 0;
+      virtual uint32_t            GetIP() const = 0;
+      virtual std::string         GetIPStr() const = 0;
+      virtual void                SetIP(uint32_t ip) = 0;
+      virtual const std::string   GetLogStr() const = 0;
+};
+
+#endif
diff --git a/include/admins.h b/include/admins.h
new file mode 100644 (file)
index 0000000..48c0225
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#ifndef ADMINS_H
+#define ADMINS_H
+
+#include <string>
+
+#include "admin.h"
+#include "admin_conf.h"
+
+class ADMINS {
+public:
+    virtual int Add(const std::string & login, const ADMIN & admin) = 0;
+    virtual int Del(const std::string & login, const ADMIN & admin) = 0;
+    virtual int Change(const ADMIN_CONF & ac, const ADMIN & admin) = 0;
+    virtual const ADMIN * GetSysAdmin() const = 0;
+    virtual const ADMIN * GetNoAdmin() const = 0;
+    virtual bool FindAdmin(const std::string & l, ADMIN ** admin) = 0;
+    virtual bool AdminExists(const std::string & login) const = 0;
+    virtual bool AdminCorrect(const std::string & login,
+                              const std::string & password,
+                              ADMIN * admin) const = 0;
+    virtual const std::string & GetStrError() const = 0;
+
+    virtual int OpenSearch() const = 0;
+    virtual int SearchNext(int, ADMIN_CONF * ac) const = 0;
+    virtual int CloseSearch(int) const = 0;
+};
+
+#endif
diff --git a/include/tariff.h b/include/tariff.h
new file mode 100644 (file)
index 0000000..b19ec47
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#ifndef TARIFF_H
+#define TARIFF_H
+
+#include <ctime>
+
+#include <string>
+
+#include "os_int.h"
+#include "tariff_conf.h"
+
+class TARIFF {
+public:
+    virtual double  GetPriceWithTraffType(uint64_t up,
+                                          uint64_t down,
+                                          int dir,
+                                          time_t t) const = 0;
+    virtual double  GetFreeMb() const = 0;
+    virtual double  GetPassiveCost() const = 0;
+    virtual double  GetFee() const = 0;
+    virtual double  GetFree() const = 0;
+
+    virtual const   std::string & GetName() const = 0;
+    virtual void    SetName(const std::string & name) = 0;
+
+    virtual int     GetTraffType() const = 0;
+    virtual int64_t GetTraffByType(uint64_t up, uint64_t down) const = 0;
+    virtual int     GetThreshold(int dir) const = 0;
+    virtual const TARIFF_DATA & GetTariffData() const = 0;
+
+    virtual TARIFF & operator=(const TARIFF_DATA & td) = 0;
+    virtual TARIFF & operator=(const TARIFF & t) = 0;
+    virtual bool     operator==(const TARIFF & rhs) const = 0;
+    virtual bool     operator!=(const TARIFF & rhs) const = 0;
+};
+
+#endif
diff --git a/include/tariffs.h b/include/tariffs.h
new file mode 100644 (file)
index 0000000..dfc47b4
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#ifndef TARIFFS_H
+#define TARIFFS_H
+
+#include <string>
+#include <list>
+
+class ADMIN;
+class TARIFF;
+class TARIFF_DATA;
+
+class TARIFFS {
+public:
+    virtual int            ReadTariffs () = 0;
+    virtual const TARIFF * FindByName(const std::string & name) const = 0;
+    virtual const TARIFF * GetNoTariff() const = 0;
+    virtual int            GetTariffsNum() const = 0;
+    virtual int            Del(const std::string & name, const ADMIN & admin) = 0;
+    virtual int            Add(const std::string & name, const ADMIN & admin) = 0;
+    virtual int            Chg(const TARIFF_DATA & td, const ADMIN & admin) = 0;
+
+    virtual void           GetTariffsData(std::list<TARIFF_DATA> * tdl) = 0;
+
+    virtual const std::string & GetStrError() const = 0;
+};
+
+#endif
diff --git a/include/user.h b/include/user.h
new file mode 100644 (file)
index 0000000..cac12d5
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#ifndef USER_H
+#define USER_H
+
+#include <ctime>
+#include <string>
+
+#include "os_int.h"
+#include "notifer.h"
+#include "base_auth.h"
+#include "stg_message.h"
+#include "tariff.h"
+#include "user_traff.h"
+
+class USER_PROPERTIES;
+
+class USER {
+public:
+    virtual int                 WriteConf() = 0;
+    virtual int                 WriteStat() = 0;
+
+    virtual const std::string & GetLogin() const = 0;
+
+    virtual uint32_t            GetCurrIP() const = 0;
+    virtual time_t              GetCurrIPModificationTime() const = 0;
+
+    virtual void                AddCurrIPBeforeNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * notifier) = 0;
+    virtual void                DelCurrIPBeforeNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * notifier) = 0;
+
+    virtual void                AddCurrIPAfterNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * notifier) = 0;
+    virtual void                DelCurrIPAfterNotifier(PROPERTY_NOTIFIER_BASE<uint32_t> * notifier) = 0;
+
+    virtual int                 GetID() const = 0;
+
+    virtual double              GetPassiveTimePart() const = 0;
+
+    virtual const TARIFF *      GetTariff() const = 0;
+    virtual void                ResetNextTariff() = 0;
+
+    #ifdef TRAFF_STAT_WITH_PORTS
+    virtual void                AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len) = 0;
+    virtual void                AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len) = 0;
+    #else
+    virtual void                AddTraffStatU(int dir, uint32_t ip, uint32_t len) = 0;
+    virtual void                AddTraffStatD(int dir, uint32_t ip, uint32_t len) = 0;
+    #endif
+
+    virtual const DIR_TRAFF &   GetSessionUpload() const = 0;
+    virtual const DIR_TRAFF &   GetSessionDownload() const = 0;
+
+    virtual bool                GetConnected() const = 0;
+    virtual time_t              GetConnectedModificationTime() const = 0;
+    virtual int                 GetAuthorized() const = 0;
+    virtual int                 Authorize(uint32_t ip,
+                                          const std::string & iface,
+                                          uint32_t enabledDirs,
+                                          const BASE_AUTH * auth) = 0;
+    virtual void                Unauthorize(const BASE_AUTH * auth) = 0;
+    virtual bool                IsAuthorizedBy(const BASE_AUTH * auth) const = 0;
+
+    virtual int                 AddMessage(STG_MSG * msg) = 0;
+
+    virtual void                UpdatePingTime(time_t t = 0) = 0;
+    virtual time_t              GetPingTime() const = 0;
+
+    virtual void                Run() = 0;
+
+    virtual const std::string & GetStrError() const = 0;
+
+    virtual USER_PROPERTIES &   GetProperty() = 0;
+    virtual const USER_PROPERTIES & GetProperty() const = 0;
+
+    virtual bool                GetDeleted() const = 0;
+    virtual void                SetDeleted() = 0;
+
+    virtual time_t              GetLastWriteStatTime() const = 0;
+
+    virtual bool                IsInetable() = 0;
+    virtual std::string         GetEnabledDirs() = 0;
+
+    virtual void                OnAdd() = 0;
+    virtual void                OnDelete() = 0;
+};
+
+typedef USER * USER_PTR;
+
+#endif
diff --git a/include/users.h b/include/users.h
new file mode 100644 (file)
index 0000000..b9454ce
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#ifndef USERS_H
+#define USERS_H
+
+#include <string>
+
+#include "notifer.h"
+#include "user.h"
+
+class ADMIN;
+
+class USERS {
+public:
+    virtual int  FindByName(const std::string & login, USER_PTR * user) = 0;
+
+    virtual bool TariffInUse(const std::string & tariffName) const = 0;
+
+    virtual void AddNotifierUserAdd(NOTIFIER_BASE<USER_PTR> * notifier) = 0;
+    virtual void DelNotifierUserAdd(NOTIFIER_BASE<USER_PTR> * notifier) = 0;
+
+    virtual void AddNotifierUserDel(NOTIFIER_BASE<USER_PTR> * notifier) = 0;
+    virtual void DelNotifierUserDel(NOTIFIER_BASE<USER_PTR> * notifier) = 0;
+
+    virtual int  Add(const std::string & login, const ADMIN & admin) = 0;
+    virtual void Del(const std::string & login, const ADMIN & admin) = 0;
+
+    virtual int  ReadUsers() = 0;
+    virtual int  GetUserNum() const = 0;
+
+    virtual int  FindByIPIdx(uint32_t ip, USER_PTR * user) const = 0;
+    virtual bool IsIPInIndex(uint32_t ip) const = 0;
+
+    virtual int  OpenSearch() = 0;
+    virtual int  SearchNext(int handle, USER_PTR * u) = 0;
+    virtual int  CloseSearch(int handle) = 0;
+
+    virtual int  Start() = 0;
+    virtual int  Stop() = 0;
+};
+
+#endif
diff --git a/projects/stargazer/admin.cpp b/projects/stargazer/admin.cpp
deleted file mode 100644 (file)
index 867717a..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- *    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() + ":";
-}
-//-----------------------------------------------------------------------------
diff --git a/projects/stargazer/admin.h b/projects/stargazer/admin.h
deleted file mode 100644 (file)
index 45979ab..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- *    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
diff --git a/projects/stargazer/admin_impl.cpp b/projects/stargazer/admin_impl.cpp
new file mode 100644 (file)
index 0000000..867717a
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ *    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() + ":";
+}
+//-----------------------------------------------------------------------------
diff --git a/projects/stargazer/admin_impl.h b/projects/stargazer/admin_impl.h
new file mode 100644 (file)
index 0000000..45979ab
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ *    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
diff --git a/projects/stargazer/admins.cpp b/projects/stargazer/admins.cpp
deleted file mode 100644 (file)
index 4e89c9f..0000000
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- *    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;
-}
-//-----------------------------------------------------------------------------
diff --git a/projects/stargazer/admins.h b/projects/stargazer/admins.h
deleted file mode 100644 (file)
index 0993323..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- *    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() const { 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
-
-
diff --git a/projects/stargazer/admins_impl.cpp b/projects/stargazer/admins_impl.cpp
new file mode 100644 (file)
index 0000000..4e89c9f
--- /dev/null
@@ -0,0 +1,321 @@
+/*
+ *    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;
+}
+//-----------------------------------------------------------------------------
diff --git a/projects/stargazer/admins_impl.h b/projects/stargazer/admins_impl.h
new file mode 100644 (file)
index 0000000..0993323
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ *    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() const { 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
+
+
diff --git a/projects/stargazer/tariff.cpp b/projects/stargazer/tariff.cpp
deleted file mode 100644 (file)
index 70b7557..0000000
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- *    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::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;
-        }
-    }*/
-}
-//-----------------------------------------------------------------------------
diff --git a/projects/stargazer/tariff.h b/projects/stargazer/tariff.h
deleted file mode 100644 (file)
index 2086b48..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- *    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 <ctime>
-
-#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; };
-    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
diff --git a/projects/stargazer/tariff_impl.cpp b/projects/stargazer/tariff_impl.cpp
new file mode 100644 (file)
index 0000000..70b7557
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ *    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::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;
+        }
+    }*/
+}
+//-----------------------------------------------------------------------------
diff --git a/projects/stargazer/tariff_impl.h b/projects/stargazer/tariff_impl.h
new file mode 100644 (file)
index 0000000..2086b48
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ *    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 <ctime>
+
+#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; };
+    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
diff --git a/projects/stargazer/tariffs.cpp b/projects/stargazer/tariffs.cpp
deleted file mode 100644 (file)
index 1f8a423..0000000
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- *    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);
-    }
-}
-//-----------------------------------------------------------------------------
diff --git a/projects/stargazer/tariffs.h b/projects/stargazer/tariffs.h
deleted file mode 100644 (file)
index 5fce068..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
- /*
- $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 <pthread.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
diff --git a/projects/stargazer/tariffs_impl.cpp b/projects/stargazer/tariffs_impl.cpp
new file mode 100644 (file)
index 0000000..1f8a423
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+ *    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);
+    }
+}
+//-----------------------------------------------------------------------------
diff --git a/projects/stargazer/tariffs_impl.h b/projects/stargazer/tariffs_impl.h
new file mode 100644 (file)
index 0000000..5fce068
--- /dev/null
@@ -0,0 +1,81 @@
+ /*
+ $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 <pthread.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
diff --git a/projects/stargazer/user.cpp b/projects/stargazer/user.cpp
deleted file mode 100644 (file)
index d8368c4..0000000
+++ /dev/null
@@ -1,1295 +0,0 @@
-/*
- *    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;
-tariff = tariffs->GetNoTariff();
-ips = StrToIPS("*");
-deleted = false;
-lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
-lastWriteDeatiledStat = stgTime;
-
-property.tariffName.AddBeforeNotifier(&tariffNotifier);
-property.passive.AddBeforeNotifier(&passiveNotifier);
-property.cash.AddBeforeNotifier(&cashNotifier);
-currIP.AddAfterNotifier(&ipNotifier);
-
-lastScanMessages = 0;
-
-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;
-
-ipIndex = u.ipIndex;
-
-deleted = u.deleted;
-
-lastWriteStat = u.lastWriteStat;
-lastWriteDeatiledStat = u.lastWriteDeatiledStat;
-
-settings = u.settings;
-
-property.tariffName.AddBeforeNotifier(&tariffNotifier);
-property.passive.AddBeforeNotifier(&passiveNotifier);
-property.cash.AddBeforeNotifier(&cashNotifier);
-currIP.AddAfterNotifier(&ipNotifier);
-
-lastScanMessages = 0;
-
-property.SetProperties(u.property);
-
-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 conf;
-
-if (store->RestoreUserConf(&conf, 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;
-    }
-
-property.SetConf(conf);
-
-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;
-    }
-
-std::vector<STG_MSG_HDR> hdrsList;
-
-if (store->GetMessageHdrs(&hdrsList, login))
-    {
-    printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str());
-    return -1;
-    }
-
-std::vector<STG_MSG_HDR>::const_iterator it;
-for (it = hdrsList.begin(); it != hdrsList.end(); ++it)
-    {
-    STG_MSG msg;
-    if (store->GetMessage(it->id, &msg, login) == 0)
-        {
-        messages.push_back(msg);
-        }
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int USER::ReadStat()
-{
-STG_LOCKER lock(&mutex, __FILE__, __LINE__);
-USER_STAT stat;
-
-if (store->RestoreUserStat(&stat, 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;
-    }
-
-property.SetStat(stat);
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int USER::WriteConf()
-{
-STG_LOCKER lock(&mutex, __FILE__, __LINE__);
-USER_CONF conf(property.GetConf());
-
-printfd(__FILE__, "USER::WriteConf()\n");
-
-if (store->SaveUserConf(conf, 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 stat(property.GetStat());
-
-printfd(__FILE__, "USER::WriteStat()\n");
-
-if (store->SaveUserStat(stat, 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__);
-time_t tt = stgTime - 3600;
-struct tm t1;
-localtime_r(&tt, &t1);
-
-USER_STAT stat(property.GetStat());
-if (store->SaveMonthStat(stat, 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;
-}
-//-----------------------------------------------------------------------------
-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());
-    }
-
-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 > static_cast<time_t>(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 (!settings->GetWriteFreeMbTraffCost() &&
-     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() || lb->first != idp)
-    {
-    traffStat.insert(lb,
-                     pair<IP_DIR_PAIR, STAT_NODE>(idp,
-                                                  STAT_NODE(len, 0, cost)));
-    }
-else
-    {
-    lb->second.cash += cost;
-    lb->second.up += len;
-    }
-}
-//-----------------------------------------------------------------------------
-#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 (!settings->GetWriteFreeMbTraffCost() &&
-     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() || lb->first != idp)
-    {
-    traffStat.insert(lb,
-                     pair<IP_DIR_PAIR, STAT_NODE>(idp,
-                                                  STAT_NODE(0, len, cost)));
-    }
-else
-    {
-    lb->second.cash += cost;
-    lb->second.down += len;
-    }
-}
-//-----------------------------------------------------------------------------
-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();
-}
-//-----------------------------------------------------------------------------
-int USER::WriteDetailStat(bool hard)
-{
-printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
-
-if (!traffStatSaved.second.empty())
-    {
-    if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
-        {
-        printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
-        WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
-        WriteServLog("%s", store->GetStrError().c_str());
-        return -1;
-        }
-    traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
-    }
-
-TRAFF_STAT ts;
-
-    {
-    STG_LOCKER lock(&mutex, __FILE__, __LINE__);
-    ts.swap(traffStat);
-    }
-
-printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
-
-if (ts.size() && !disabledDetailStat)
-    {
-    if (store->WriteDetailedStat(ts, lastWriteDeatiledStat, login))
-        {
-        printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
-        WriteServLog("Cannot write detail stat for user %s.", login.c_str());
-        WriteServLog("%s", store->GetStrError().c_str());
-        if (!hard)
-            {
-            printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
-            STG_LOCKER lock(&mutex, __FILE__, __LINE__);
-            traffStatSaved.second.swap(ts);
-            traffStatSaved.first = lastWriteDeatiledStat;
-            }
-        return -1;
-        }
-    }
-lastWriteDeatiledStat = stgTime;
-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;
-localtime_r(&t, &tms);
-
-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 = stgTime;
-struct tm tm;
-localtime_r(&t, &tm);
-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))
-    {
-    if (store->AddMessage(msg, login))
-        {
-        errorStr = store->GetStrError();
-        WriteServLog("Error adding message: '%s'", errorStr.c_str());
-        printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
-        return -1;
-        }
-    messages.push_back(*msg);
-    }
-else
-    {
-    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();
-            WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
-            printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
-            return -1;
-            }
-        messages.push_back(*msg);
-        }
-    }
-return 0;
-}
-//-----------------------------------------------------------------------------
-int USER::SendMessage(STG_MSG & msg) const
-{
-// No lock `cause we are already locked from caller
-int ret = -1;
-set<const BASE_AUTH*>::iterator it(authorizedBy.begin());
-while (it != authorizedBy.end())
-    {
-    if (!(*it++)->SendMessage(msg, currIP))
-        ret = 0;
-    }
-if (!ret)
-    {
-#ifndef DEBUG
-    //TODO: gcc v. 4.x generate ICE on x86_64
-    msg.header.lastSendTime = time(NULL);
-#else
-    msg.header.lastSendTime = stgTime;
-#endif
-    msg.header.repeat--;
-    }
-return ret;
-}
-//-----------------------------------------------------------------------------
-void USER::ScanMessage()
-{
-// No lock `cause we are already locked from caller
-// We need not check for the authorizedBy `cause it has already checked by caller
-
-std::list<STG_MSG>::iterator it(messages.begin());
-while (it != messages.end())
-    {
-    if (settings->GetMessageTimeout() > 0 &&
-        difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
-        {
-        // Timeout exceeded
-        if (store->DelMessage(it->header.id, login))
-            {
-            WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
-            printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
-            }
-        messages.erase(it++);
-        continue;
-        }
-    if (it->GetNextSendTime() <= stgTime)
-        {
-        if (SendMessage(*it))
-            {
-            // We need to check all messages in queue for timeout
-            ++it;
-            continue;
-            }
-        if (it->header.repeat < 0)
-            {
-            if (store->DelMessage(it->header.id, login))
-                {
-                WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
-                printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
-                }
-            messages.erase(it++);
-            }
-        else
-            {
-            if (store->EditMessage(*it, login))
-                {
-                WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
-                printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
-                }
-            ++it;
-            }
-        }
-    }
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-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)
-        if (user->connected)
-            user->Disconnect(false, "Change IP");
-    if (to != 0)
-        if (user->IsInetable())
-            user->Connect(false);
-}
-//-----------------------------------------------------------------------------
diff --git a/projects/stargazer/user.h b/projects/stargazer/user.h
deleted file mode 100644 (file)
index 1c84ba1..0000000
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
- *    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();
-
-    int             WriteDetailStat(bool hard = false);
-
-    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(STG_MSG & msg) const;
-    void            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;
-
-    TRAFF_STAT      traffStat;
-    std::pair<time_t, TRAFF_STAT> traffStatSaved;
-
-    const SETTINGS * settings;
-
-    set<const BASE_AUTH *> authorizedBy;
-
-    const map<uint32_t, user_iter> * ipIndex;
-
-    list<STG_MSG> messages;
-
-    bool            deleted;
-
-    time_t          lastWriteStat;           // ÷ÒÅÍÑ ÐÏÓÌÅÄÎÅÊ ÚÁÐÉÓÉ ÓÔÁÔÉÓÔÉËÉ
-    time_t          lastWriteDeatiledStat;   // ÷ÒÅÍÑ ÐÏÓÌÅÄÎÅÊ ÚÁÐÉÓÉ ÄÅÔÁÌØÎÏÊ ÓÔÁÔÉÓÔÉËÉ
-
-    // 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
diff --git a/projects/stargazer/user_impl.cpp b/projects/stargazer/user_impl.cpp
new file mode 100644 (file)
index 0000000..d8368c4
--- /dev/null
@@ -0,0 +1,1295 @@
+/*
+ *    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;
+tariff = tariffs->GetNoTariff();
+ips = StrToIPS("*");
+deleted = false;
+lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
+lastWriteDeatiledStat = stgTime;
+
+property.tariffName.AddBeforeNotifier(&tariffNotifier);
+property.passive.AddBeforeNotifier(&passiveNotifier);
+property.cash.AddBeforeNotifier(&cashNotifier);
+currIP.AddAfterNotifier(&ipNotifier);
+
+lastScanMessages = 0;
+
+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;
+
+ipIndex = u.ipIndex;
+
+deleted = u.deleted;
+
+lastWriteStat = u.lastWriteStat;
+lastWriteDeatiledStat = u.lastWriteDeatiledStat;
+
+settings = u.settings;
+
+property.tariffName.AddBeforeNotifier(&tariffNotifier);
+property.passive.AddBeforeNotifier(&passiveNotifier);
+property.cash.AddBeforeNotifier(&cashNotifier);
+currIP.AddAfterNotifier(&ipNotifier);
+
+lastScanMessages = 0;
+
+property.SetProperties(u.property);
+
+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 conf;
+
+if (store->RestoreUserConf(&conf, 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;
+    }
+
+property.SetConf(conf);
+
+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;
+    }
+
+std::vector<STG_MSG_HDR> hdrsList;
+
+if (store->GetMessageHdrs(&hdrsList, login))
+    {
+    printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str());
+    return -1;
+    }
+
+std::vector<STG_MSG_HDR>::const_iterator it;
+for (it = hdrsList.begin(); it != hdrsList.end(); ++it)
+    {
+    STG_MSG msg;
+    if (store->GetMessage(it->id, &msg, login) == 0)
+        {
+        messages.push_back(msg);
+        }
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int USER::ReadStat()
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+USER_STAT stat;
+
+if (store->RestoreUserStat(&stat, 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;
+    }
+
+property.SetStat(stat);
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int USER::WriteConf()
+{
+STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+USER_CONF conf(property.GetConf());
+
+printfd(__FILE__, "USER::WriteConf()\n");
+
+if (store->SaveUserConf(conf, 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 stat(property.GetStat());
+
+printfd(__FILE__, "USER::WriteStat()\n");
+
+if (store->SaveUserStat(stat, 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__);
+time_t tt = stgTime - 3600;
+struct tm t1;
+localtime_r(&tt, &t1);
+
+USER_STAT stat(property.GetStat());
+if (store->SaveMonthStat(stat, 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;
+}
+//-----------------------------------------------------------------------------
+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());
+    }
+
+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 > static_cast<time_t>(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 (!settings->GetWriteFreeMbTraffCost() &&
+     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() || lb->first != idp)
+    {
+    traffStat.insert(lb,
+                     pair<IP_DIR_PAIR, STAT_NODE>(idp,
+                                                  STAT_NODE(len, 0, cost)));
+    }
+else
+    {
+    lb->second.cash += cost;
+    lb->second.up += len;
+    }
+}
+//-----------------------------------------------------------------------------
+#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 (!settings->GetWriteFreeMbTraffCost() &&
+     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() || lb->first != idp)
+    {
+    traffStat.insert(lb,
+                     pair<IP_DIR_PAIR, STAT_NODE>(idp,
+                                                  STAT_NODE(0, len, cost)));
+    }
+else
+    {
+    lb->second.cash += cost;
+    lb->second.down += len;
+    }
+}
+//-----------------------------------------------------------------------------
+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();
+}
+//-----------------------------------------------------------------------------
+int USER::WriteDetailStat(bool hard)
+{
+printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
+
+if (!traffStatSaved.second.empty())
+    {
+    if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
+        {
+        printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
+        WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
+        WriteServLog("%s", store->GetStrError().c_str());
+        return -1;
+        }
+    traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
+    }
+
+TRAFF_STAT ts;
+
+    {
+    STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+    ts.swap(traffStat);
+    }
+
+printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
+
+if (ts.size() && !disabledDetailStat)
+    {
+    if (store->WriteDetailedStat(ts, lastWriteDeatiledStat, login))
+        {
+        printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
+        WriteServLog("Cannot write detail stat for user %s.", login.c_str());
+        WriteServLog("%s", store->GetStrError().c_str());
+        if (!hard)
+            {
+            printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
+            STG_LOCKER lock(&mutex, __FILE__, __LINE__);
+            traffStatSaved.second.swap(ts);
+            traffStatSaved.first = lastWriteDeatiledStat;
+            }
+        return -1;
+        }
+    }
+lastWriteDeatiledStat = stgTime;
+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;
+localtime_r(&t, &tms);
+
+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 = stgTime;
+struct tm tm;
+localtime_r(&t, &tm);
+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))
+    {
+    if (store->AddMessage(msg, login))
+        {
+        errorStr = store->GetStrError();
+        WriteServLog("Error adding message: '%s'", errorStr.c_str());
+        printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
+        return -1;
+        }
+    messages.push_back(*msg);
+    }
+else
+    {
+    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();
+            WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
+            printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
+            return -1;
+            }
+        messages.push_back(*msg);
+        }
+    }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int USER::SendMessage(STG_MSG & msg) const
+{
+// No lock `cause we are already locked from caller
+int ret = -1;
+set<const BASE_AUTH*>::iterator it(authorizedBy.begin());
+while (it != authorizedBy.end())
+    {
+    if (!(*it++)->SendMessage(msg, currIP))
+        ret = 0;
+    }
+if (!ret)
+    {
+#ifndef DEBUG
+    //TODO: gcc v. 4.x generate ICE on x86_64
+    msg.header.lastSendTime = time(NULL);
+#else
+    msg.header.lastSendTime = stgTime;
+#endif
+    msg.header.repeat--;
+    }
+return ret;
+}
+//-----------------------------------------------------------------------------
+void USER::ScanMessage()
+{
+// No lock `cause we are already locked from caller
+// We need not check for the authorizedBy `cause it has already checked by caller
+
+std::list<STG_MSG>::iterator it(messages.begin());
+while (it != messages.end())
+    {
+    if (settings->GetMessageTimeout() > 0 &&
+        difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
+        {
+        // Timeout exceeded
+        if (store->DelMessage(it->header.id, login))
+            {
+            WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
+            printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
+            }
+        messages.erase(it++);
+        continue;
+        }
+    if (it->GetNextSendTime() <= stgTime)
+        {
+        if (SendMessage(*it))
+            {
+            // We need to check all messages in queue for timeout
+            ++it;
+            continue;
+            }
+        if (it->header.repeat < 0)
+            {
+            if (store->DelMessage(it->header.id, login))
+                {
+                WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
+                printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
+                }
+            messages.erase(it++);
+            }
+        else
+            {
+            if (store->EditMessage(*it, login))
+                {
+                WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
+                printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
+                }
+            ++it;
+            }
+        }
+    }
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+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)
+        if (user->connected)
+            user->Disconnect(false, "Change IP");
+    if (to != 0)
+        if (user->IsInetable())
+            user->Connect(false);
+}
+//-----------------------------------------------------------------------------
diff --git a/projects/stargazer/user_impl.h b/projects/stargazer/user_impl.h
new file mode 100644 (file)
index 0000000..1c84ba1
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+ *    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();
+
+    int             WriteDetailStat(bool hard = false);
+
+    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(STG_MSG & msg) const;
+    void            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;
+
+    TRAFF_STAT      traffStat;
+    std::pair<time_t, TRAFF_STAT> traffStatSaved;
+
+    const SETTINGS * settings;
+
+    set<const BASE_AUTH *> authorizedBy;
+
+    const map<uint32_t, user_iter> * ipIndex;
+
+    list<STG_MSG> messages;
+
+    bool            deleted;
+
+    time_t          lastWriteStat;           // ÷ÒÅÍÑ ÐÏÓÌÅÄÎÅÊ ÚÁÐÉÓÉ ÓÔÁÔÉÓÔÉËÉ
+    time_t          lastWriteDeatiledStat;   // ÷ÒÅÍÑ ÐÏÓÌÅÄÎÅÊ ÚÁÐÉÓÉ ÄÅÔÁÌØÎÏÊ ÓÔÁÔÉÓÔÉËÉ
+
+    // 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
diff --git a/projects/stargazer/users.cpp b/projects/stargazer/users.cpp
deleted file mode 100644 (file)
index 84a1022..0000000
+++ /dev/null
@@ -1,753 +0,0 @@
-/*
- *    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;
-localtime_r(&tt, &t);
-
-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;
-    localtime_r(&tt, &t);
-
-    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);
-        }
-
-    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)
-{
-//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");
-    int usersCnt = 0;
-
-    // ðÉÛÅÍ ÀÚÅÒÏ× ÞÁÓÔÑÍÉ. ÷ ÐÅÒÅÒÙ×ÁÈ ×ÙÚÙ×ÁÅÍ USER::Run
-    list<USER>::iterator 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));
-        }
-    }
-
-RealDelUser();
-}
-//-----------------------------------------------------------------------------
-void USERS::NewDay(const struct tm & t)
-{
-struct tm t1;
-time_t tt = stgTime;
-localtime_r(&tt, &t1);
-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));
-
-// 'cause bind2st accepts only constant first param
-for (list<USER>::iterator it = users.begin();
-     it != users.end();
-     ++it)
-    it->WriteDetailStat(true);
-
-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;
-}
diff --git a/projects/stargazer/users.h b/projects/stargazer/users.h
deleted file mode 100644 (file)
index 424958d..0000000
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- *    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() const { 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() const { 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();
-
-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
-
diff --git a/projects/stargazer/users_impl.cpp b/projects/stargazer/users_impl.cpp
new file mode 100644 (file)
index 0000000..84a1022
--- /dev/null
@@ -0,0 +1,753 @@
+/*
+ *    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;
+localtime_r(&tt, &t);
+
+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;
+    localtime_r(&tt, &t);
+
+    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);
+        }
+
+    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)
+{
+//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");
+    int usersCnt = 0;
+
+    // ðÉÛÅÍ ÀÚÅÒÏ× ÞÁÓÔÑÍÉ. ÷ ÐÅÒÅÒÙ×ÁÈ ×ÙÚÙ×ÁÅÍ USER::Run
+    list<USER>::iterator 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));
+        }
+    }
+
+RealDelUser();
+}
+//-----------------------------------------------------------------------------
+void USERS::NewDay(const struct tm & t)
+{
+struct tm t1;
+time_t tt = stgTime;
+localtime_r(&tt, &t1);
+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));
+
+// 'cause bind2st accepts only constant first param
+for (list<USER>::iterator it = users.begin();
+     it != users.end();
+     ++it)
+    it->WriteDetailStat(true);
+
+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;
+}
diff --git a/projects/stargazer/users_impl.h b/projects/stargazer/users_impl.h
new file mode 100644 (file)
index 0000000..424958d
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ *    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() const { 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() const { 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();
+
+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
+