/* $Revision: 1.44 $ $Date: 2010/09/13 05:54:43 $ $Author: faust $ */ #ifndef USER_PROPERTY_H #define USER_PROPERTY_H #include <ctime> #include <string> #include <set> #include <sstream> #include <iostream> #include <algorithm> #include "base_store.h" #include "stg_logger.h" #include "admin.h" #include "settings.h" #include "notifer.h" #include "stg_logger.h" #include "stg_locker.h" #include "script_executer.h" using namespace std; extern const volatile time_t stgTime; //----------------------------------------------------------------------------- template<typename varT> class USER_PROPERTY { public: USER_PROPERTY(varT& val); USER_PROPERTY<varT>& operator= (const varT&); USER_PROPERTY<varT>& operator-= (const varT&); virtual ~USER_PROPERTY(); const varT * operator&() const throw(); const varT& ConstData() const throw(); operator const varT&() const throw() { return value; } //bool IsEmpty() const throw(); void AddBeforeNotifier(PROPERTY_NOTIFIER_BASE<varT> * n); void DelBeforeNotifier(PROPERTY_NOTIFIER_BASE<varT> * n); void AddAfterNotifier(PROPERTY_NOTIFIER_BASE<varT> * n); void DelAfterNotifier(PROPERTY_NOTIFIER_BASE<varT> * n); time_t ModificationTime() const throw(); void ModifyTime() throw(); protected: varT & value; time_t modificationTime; //typedef set<PROPERTY_NOTIFIER_BASE<varT> *>::iterator notifier_iter_t; mutable set<PROPERTY_NOTIFIER_BASE<varT> *> beforeNotifiers; mutable set<PROPERTY_NOTIFIER_BASE<varT> *> afterNotifiers; mutable pthread_mutex_t mutex; }; //----------------------------------------------------------------------------- template<typename varT> class USER_PROPERTY_LOGGED: public USER_PROPERTY<varT> { public: USER_PROPERTY_LOGGED(varT& val, const string n, bool isPassword, bool isStat, STG_LOGGER & logger, const SETTINGS * s); virtual ~USER_PROPERTY_LOGGED(); //operator const varT&() const throw();; USER_PROPERTY_LOGGED<varT> * GetPointer() throw(); const varT & Get() const; const string & GetName() const; bool Set(const varT & val, const ADMIN & admin, const string & login, const BASE_STORE * store, const string & msg = ""); protected: void WriteAccessDenied(const string & login, const ADMIN & admin, const string & parameter); void WriteSuccessChange(const string & login, const ADMIN & admin, const string & parameter, const string & oldValue, const string & newValue, const string & msg, const BASE_STORE * store); void OnChange(const string & login, const string & paramName, const string & oldValue, const string & newValue, const ADMIN & admin); string name; // parameter name. needed for logging bool isPassword; // is parameter password. when true, it will be logged as ******* bool isStat; // is parameter a stat data or conf data? mutable pthread_mutex_t mutex; STG_LOGGER & stgLogger; // server's logger const SETTINGS * settings; }; //----------------------------------------------------------------------------- class USER_PROPERTIES { friend class USER; /* Ð’ Ñтом меÑте важен порÑдок ÑÐ»ÐµÐ´Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ñ€Ð¸Ð²Ð°Ñ‚Ð½Ð¾Ð¹ и открытой чаÑтей. Ðто ÑвÑзано Ñ Ñ‚ÐµÐ¼, что чаÑÑ‚ÑŒ ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð½Ð°Ñ…Ð¾Ð´Ð¸Ñ‚ÑÑ Ð² публичной Ñекции по Ñути ÑвлÑетÑÑ Ð·Ð°Ð²ÑƒÐ°Ð»Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð½Ð¾Ð¹ ÑÑылкой на закрытую чаÑÑ‚ÑŒ. Т.о. нам нужно чтобы конÑтрукторы из закрытой чаÑти вызвалиÑÑŒ раньше открытой. ПоÑтомому в начале идет Ð·Ð°ÐºÑ€Ñ‹Ñ‚Ð°Ñ ÑÐµÐºÑ†Ð¸Ñ * */ private: USER_STAT stat; USER_CONF conf; public: USER_PROPERTIES(const SETTINGS * settings); USER_PROPERTY_LOGGED<double> cash; USER_PROPERTY_LOGGED<DIR_TRAFF> up; USER_PROPERTY_LOGGED<DIR_TRAFF> down; USER_PROPERTY_LOGGED<double> lastCashAdd; USER_PROPERTY_LOGGED<time_t> passiveTime; USER_PROPERTY_LOGGED<time_t> lastCashAddTime; USER_PROPERTY_LOGGED<double> freeMb; USER_PROPERTY_LOGGED<time_t> lastActivityTime; USER_PROPERTY_LOGGED<string> password; USER_PROPERTY_LOGGED<int> passive; USER_PROPERTY_LOGGED<int> disabled; USER_PROPERTY_LOGGED<int> disabledDetailStat; USER_PROPERTY_LOGGED<int> alwaysOnline; USER_PROPERTY_LOGGED<string> tariffName; USER_PROPERTY_LOGGED<string> nextTariff; USER_PROPERTY_LOGGED<string> address; USER_PROPERTY_LOGGED<string> note; USER_PROPERTY_LOGGED<string> group; USER_PROPERTY_LOGGED<string> email; USER_PROPERTY_LOGGED<string> phone; USER_PROPERTY_LOGGED<string> realName; USER_PROPERTY_LOGGED<double> credit; USER_PROPERTY_LOGGED<time_t> creditExpire; USER_PROPERTY_LOGGED<USER_IPS> ips; USER_PROPERTY_LOGGED<string> userdata0; USER_PROPERTY_LOGGED<string> userdata1; USER_PROPERTY_LOGGED<string> userdata2; USER_PROPERTY_LOGGED<string> userdata3; USER_PROPERTY_LOGGED<string> userdata4; USER_PROPERTY_LOGGED<string> userdata5; USER_PROPERTY_LOGGED<string> userdata6; USER_PROPERTY_LOGGED<string> userdata7; USER_PROPERTY_LOGGED<string> userdata8; USER_PROPERTY_LOGGED<string> userdata9; }; //============================================================================= //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- template <typename varT> USER_PROPERTY<varT>::USER_PROPERTY(varT& val) : value(val) { pthread_mutex_init(&mutex, NULL); modificationTime = stgTime; } //----------------------------------------------------------------------------- template <typename varT> USER_PROPERTY<varT>::~USER_PROPERTY() { } //----------------------------------------------------------------------------- template <typename varT> void USER_PROPERTY<varT>::ModifyTime() throw() { modificationTime = stgTime; } //----------------------------------------------------------------------------- template <typename varT> USER_PROPERTY<varT>& USER_PROPERTY<varT>::operator= (const varT& newValue) { STG_LOCKER locker(&mutex, __FILE__, __LINE__); /* TODO if (value == newValue) return *this;*/ typename set<PROPERTY_NOTIFIER_BASE<varT> *>::iterator ni; //printf("USER_PROPERTY<varT>::operator= (const varT& rhs)\n"); varT oldVal = value; ni = beforeNotifiers.begin(); while (ni != beforeNotifiers.end()) (*ni++)->Notify(oldVal, newValue); value = newValue; modificationTime = stgTime; ni = afterNotifiers.begin(); while (ni != afterNotifiers.end()) (*ni++)->Notify(oldVal, newValue); return *this; } //----------------------------------------------------------------------------- template <typename varT> USER_PROPERTY<varT>& USER_PROPERTY<varT>::operator-= (const varT& delta) { STG_LOCKER locker(&mutex, __FILE__, __LINE__); typename set<PROPERTY_NOTIFIER_BASE<varT> *>::iterator ni; varT oldVal = value; ni = beforeNotifiers.begin(); while (ni != beforeNotifiers.end()) (*ni++)->Notify(oldVal, oldVal - delta); value -= delta; modificationTime = stgTime; ni = afterNotifiers.begin(); while (ni != afterNotifiers.end()) (*ni++)->Notify(oldVal, value); return *this; } //----------------------------------------------------------------------------- template <typename varT> const varT * USER_PROPERTY<varT>::operator&() const throw() { STG_LOCKER locker(&mutex, __FILE__, __LINE__); return &value; } //----------------------------------------------------------------------------- template <typename varT> const varT& USER_PROPERTY<varT>::ConstData() const throw() { STG_LOCKER locker(&mutex, __FILE__, __LINE__); return value; } //----------------------------------------------------------------------------- /*template <typename varT> bool USER_PROPERTY<varT>::IsEmpty() const throw() { STG_LOCKER locker(&mutex, __FILE__, __LINE__); return !is_set; }*/ //----------------------------------------------------------------------------- template <typename varT> void USER_PROPERTY<varT>::AddBeforeNotifier(PROPERTY_NOTIFIER_BASE<varT> * n) { STG_LOCKER locker(&mutex, __FILE__, __LINE__); beforeNotifiers.insert(n); } //----------------------------------------------------------------------------- template <typename varT> void USER_PROPERTY<varT>::DelBeforeNotifier(PROPERTY_NOTIFIER_BASE<varT> * n) { STG_LOCKER locker(&mutex, __FILE__, __LINE__); beforeNotifiers.erase(n); } //----------------------------------------------------------------------------- template <typename varT> void USER_PROPERTY<varT>::AddAfterNotifier(PROPERTY_NOTIFIER_BASE<varT> * n) { STG_LOCKER locker(&mutex, __FILE__, __LINE__); afterNotifiers.insert(n); } //----------------------------------------------------------------------------- template <typename varT> void USER_PROPERTY<varT>::DelAfterNotifier(PROPERTY_NOTIFIER_BASE<varT> * n) { STG_LOCKER locker(&mutex, __FILE__, __LINE__); afterNotifiers.erase(n); } //----------------------------------------------------------------------------- template <typename varT> time_t USER_PROPERTY<varT>::ModificationTime() const throw() { STG_LOCKER locker(&mutex, __FILE__, __LINE__); return modificationTime; } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- template <typename varT> USER_PROPERTY_LOGGED<varT>::USER_PROPERTY_LOGGED( varT& val, string n, bool isPass, bool isSt, STG_LOGGER & logger, const SETTINGS * s) :USER_PROPERTY<varT>(val), stgLogger(logger) { pthread_mutex_init(&mutex, NULL); STG_LOCKER locker(&mutex, __FILE__, __LINE__); USER_PROPERTY<varT>::value = val; isPassword = isPass; isStat = isSt; name = n; settings = s; } //----------------------------------------------------------------------------- template <typename varT> USER_PROPERTY_LOGGED<varT>::~USER_PROPERTY_LOGGED() { STG_LOCKER locker(&mutex, __FILE__, __LINE__); } //----------------------------------------------------------------------------- template <typename varT> USER_PROPERTY_LOGGED<varT> * USER_PROPERTY_LOGGED<varT>::GetPointer() throw() { STG_LOCKER locker(&mutex, __FILE__, __LINE__); return this; } //----------------------------------------------------------------------------- template <typename varT> const varT & USER_PROPERTY_LOGGED<varT>::Get() const { STG_LOCKER locker(&mutex, __FILE__, __LINE__); return USER_PROPERTY<varT>::value; }; //------------------------------------------------------------------------- template <typename varT> const string & USER_PROPERTY_LOGGED<varT>::GetName() const { STG_LOCKER locker(&mutex, __FILE__, __LINE__); return name; }; //------------------------------------------------------------------------- template <typename varT> bool USER_PROPERTY_LOGGED<varT>::Set(const varT & val, const ADMIN & admin, const string & login, const BASE_STORE * store, const string & msg) { STG_LOCKER locker(&mutex, __FILE__, __LINE__); //cout << "USER_PROPERTY_LOGGED " << val << endl; //value = val; //modificationTime = stgTime; const PRIV * priv = admin.GetPriv(); string adm_login = admin.GetLogin(); string adm_ip = admin.GetAdminIPStr(); if ((priv->userConf && !isStat) || (priv->userStat && isStat) || (priv->userPasswd && isPassword) || (priv->userCash && name == "cash")) { stringstream oldVal; stringstream newVal; oldVal.flags(oldVal.flags() | ios::fixed); newVal.flags(newVal.flags() | ios::fixed); oldVal << USER_PROPERTY<varT>::value; newVal << val; OnChange(login, name, oldVal.str(), newVal.str(), admin); if (isPassword) { WriteSuccessChange(login, admin, name, "******", "******", msg, store); } else { WriteSuccessChange(login, admin, name, oldVal.str(), newVal.str(), msg, store); } USER_PROPERTY<varT>::operator =(val); return true; } else { WriteAccessDenied(login, admin, name); return false; } return true; } //------------------------------------------------------------------------- template <typename varT> void USER_PROPERTY_LOGGED<varT>::WriteAccessDenied(const string & login, const ADMIN & admin, const string & parameter) { stgLogger("%s Change user \'%s.\' Parameter \'%s\'. Access denied.", admin.GetLogStr().c_str(), login.c_str(), parameter.c_str()); } //------------------------------------------------------------------------- template <typename varT> void USER_PROPERTY_LOGGED<varT>::WriteSuccessChange(const string & login, const ADMIN & admin, const string & parameter, const string & oldValue, const string & newValue, const string & msg, const BASE_STORE * store) { stgLogger("%s User \'%s\': \'%s\' parameter changed from \'%s\' to \'%s\'. %s", admin.GetLogStr().c_str(), login.c_str(), parameter.c_str(), oldValue.c_str(), newValue.c_str(), msg.c_str()); /*char userLogMsg[2048]; sprintf(userLogMsg, "\'%s\' parameter changed from \'%s\' to \'%s\'. %s", parameter.c_str(), oldValue.c_str(), newValue.c_str(), msg.c_str());*/ store->WriteUserChgLog(login, admin.GetLogin(), admin.GetAdminIP(), parameter, oldValue, newValue, msg); //store->WriteLogString(userLogMsg, login); } //------------------------------------------------------------------------- template <typename varT> void USER_PROPERTY_LOGGED<varT>::OnChange(const string & login, const string & paramName, const string & oldValue, const string & newValue, const ADMIN &) { string str1; str1 = settings->GetConfDir() + "/OnChange"; if (access(str1.c_str(), X_OK) == 0) { string str2("\"" + str1 + "\" \"" + login + "\" \"" + paramName + "\" \"" + oldValue + "\" \"" + newValue + "\""); ScriptExec(str2); } else { stgLogger("Script OnChange cannot be executed. File %s not found.", str1.c_str()); } } //------------------------------------------------------------------------- //------------------------------------------------------------------------- //------------------------------------------------------------------------- template<typename varT> stringstream & operator<< (stringstream & s, const USER_PROPERTY<varT> & v) { s << v.ConstData(); return s; } //----------------------------------------------------------------------------- template<typename varT> ostream & operator<< (ostream & o, const USER_PROPERTY<varT> & v) { return o << v.ConstData(); } //----------------------------------------------------------------------------- #endif // USER_PROPERTY_H