]> git.stg.codes - stg.git/blob - include/stg/user_property.h
Allow user-defined 'ar' and 'ranlib'.
[stg.git] / include / stg / user_property.h
1 /*
2 $Revision: 1.44 $
3 $Date: 2010/09/13 05:54:43 $
4 $Author: faust $
5 */
6
7 #ifndef USER_PROPERTY_H
8 #define USER_PROPERTY_H
9
10 #include <unistd.h> // access
11
12 #include <ctime>
13 #include <string>
14 #include <set>
15 #include <map>
16 #include <sstream>
17 #include <iostream>
18
19 #include "stg/logger.h"
20 #include "stg/locker.h"
21 #include "stg/settings.h"
22 #include "stg/scriptexecuter.h"
23 #include "stg/common.h"
24
25 #include "store.h"
26 #include "admin.h"
27 #include "notifer.h"
28 #include "noncopyable.h"
29
30 extern volatile time_t stgTime;
31 //-----------------------------------------------------------------------------
32 class USER_PROPERTY_BASE {
33 public:
34     virtual std::string ToString() const = 0;
35 };
36 //-----------------------------------------------------------------------------
37 typedef std::map<std::string, USER_PROPERTY_BASE *> REGISTRY;
38 //-----------------------------------------------------------------------------
39 template<typename varT>
40 class USER_PROPERTY : public USER_PROPERTY_BASE {
41 public:
42     explicit USER_PROPERTY(varT & val);
43     virtual ~USER_PROPERTY();
44
45     void Set(const varT & rvalue);
46
47     USER_PROPERTY<varT> & operator= (const varT & rvalue);
48
49     const varT * operator&() const throw() { return &value; }
50     const varT & ConstData() const throw() { return value; }
51
52     operator const varT&() const throw() { return value; }
53
54     void    AddBeforeNotifier(PROPERTY_NOTIFIER_BASE<varT> * n);
55     void    DelBeforeNotifier(const PROPERTY_NOTIFIER_BASE<varT> * n);
56
57     void    AddAfterNotifier(PROPERTY_NOTIFIER_BASE<varT> * n);
58     void    DelAfterNotifier(const PROPERTY_NOTIFIER_BASE<varT> * n);
59
60     time_t  ModificationTime() const throw() { return modificationTime; }
61     void    ModifyTime() throw();
62
63     std::string ToString() const;
64 private:
65     varT & value;
66     time_t modificationTime;
67     std::set<PROPERTY_NOTIFIER_BASE<varT> *> beforeNotifiers;
68     std::set<PROPERTY_NOTIFIER_BASE<varT> *> afterNotifiers;
69     pthread_mutex_t mutex;
70 };
71 //-----------------------------------------------------------------------------
72 template<typename varT>
73 class USER_PROPERTY_LOGGED: public USER_PROPERTY<varT> {
74 public:
75     USER_PROPERTY_LOGGED(varT & val,
76                          const std::string & n,
77                          bool isPassword,
78                          bool isStat,
79                          STG_LOGGER & logger,
80                          const SETTINGS & s,
81                          REGISTRY & properties);
82     virtual ~USER_PROPERTY_LOGGED() {}
83
84     USER_PROPERTY_LOGGED<varT> * GetPointer() throw() { return this; }
85     const USER_PROPERTY_LOGGED<varT> * GetPointer() const throw() { return this; }
86     const varT & Get() const { return USER_PROPERTY<varT>::ConstData(); }
87     const std::string & GetName() const { return name; }
88     bool Set(const varT & val,
89              const ADMIN * admin,
90              const std::string & login,
91              const STORE * store,
92              const std::string & msg = "");
93 private:
94     void WriteAccessDenied(const std::string & login,
95                            const ADMIN * admin,
96                            const std::string & parameter);
97
98     void WriteSuccessChange(const std::string & login,
99                             const ADMIN * admin,
100                             const std::string & parameter,
101                             const std::string & oldValue,
102                             const std::string & newValue,
103                             const std::string & msg,
104                             const STORE * store);
105
106     void OnChange(const std::string & login,
107                   const std::string & paramName,
108                   const std::string & oldValue,
109                   const std::string & newValue,
110                   const ADMIN  * admin);
111
112     STG_LOGGER &      stgLogger;
113     bool              isPassword;
114     bool              isStat;
115     std::string       name;
116     const SETTINGS&   settings;
117 };
118 //-----------------------------------------------------------------------------
119 class USER_PROPERTIES : private NONCOPYABLE {
120 /*
121  В этом месте важен порядок следования приватной и открытой частей.
122  Это связано с тем, что часть которая находится в публичной секции
123  по сути является завуалированной ссылкой на закрытую часть. Т.о. нам нужно
124  чтобы конструкторы из закрытой части вызвались раньше открытой. Поэтомому в
125  начале идет закрытая секция
126  * */
127
128 private:
129     USER_STAT stat;
130     USER_CONF conf;
131
132     REGISTRY properties;
133 public:
134     explicit USER_PROPERTIES(const SETTINGS& s);
135
136     USER_STAT & Stat() { return stat; }
137     USER_CONF & Conf() { return conf; }
138     const USER_STAT & GetStat() const { return stat; }
139     const USER_CONF & GetConf() const { return conf; }
140     void SetStat(const USER_STAT & s) { stat = s; }
141     void SetConf(const USER_CONF & c) { conf = c; }
142
143     void SetProperties(const USER_PROPERTIES & p) { stat = p.stat; conf = p.conf; }
144
145     std::string GetPropertyValue(const std::string & name) const;
146     bool Exists(const std::string & name) const;
147
148     USER_PROPERTY_LOGGED<double>            cash;
149     USER_PROPERTY_LOGGED<DIR_TRAFF>         up;
150     USER_PROPERTY_LOGGED<DIR_TRAFF>         down;
151     USER_PROPERTY_LOGGED<double>            lastCashAdd;
152     USER_PROPERTY_LOGGED<time_t>            passiveTime;
153     USER_PROPERTY_LOGGED<time_t>            lastCashAddTime;
154     USER_PROPERTY_LOGGED<double>            freeMb;
155     USER_PROPERTY_LOGGED<time_t>            lastActivityTime;
156
157     USER_PROPERTY_LOGGED<std::string>       password;
158     USER_PROPERTY_LOGGED<int>               passive;
159     USER_PROPERTY_LOGGED<int>               disabled;
160     USER_PROPERTY_LOGGED<int>               disabledDetailStat;
161     USER_PROPERTY_LOGGED<int>               alwaysOnline;
162     USER_PROPERTY_LOGGED<std::string>       tariffName;
163     USER_PROPERTY_LOGGED<std::string>       nextTariff;
164     USER_PROPERTY_LOGGED<std::string>       address;
165     USER_PROPERTY_LOGGED<std::string>       note;
166     USER_PROPERTY_LOGGED<std::string>       group;
167     USER_PROPERTY_LOGGED<std::string>       email;
168     USER_PROPERTY_LOGGED<std::string>       phone;
169     USER_PROPERTY_LOGGED<std::string>       realName;
170     USER_PROPERTY_LOGGED<double>            credit;
171     USER_PROPERTY_LOGGED<time_t>            creditExpire;
172     USER_PROPERTY_LOGGED<USER_IPS>          ips;
173     USER_PROPERTY_LOGGED<std::string>       userdata0;
174     USER_PROPERTY_LOGGED<std::string>       userdata1;
175     USER_PROPERTY_LOGGED<std::string>       userdata2;
176     USER_PROPERTY_LOGGED<std::string>       userdata3;
177     USER_PROPERTY_LOGGED<std::string>       userdata4;
178     USER_PROPERTY_LOGGED<std::string>       userdata5;
179     USER_PROPERTY_LOGGED<std::string>       userdata6;
180     USER_PROPERTY_LOGGED<std::string>       userdata7;
181     USER_PROPERTY_LOGGED<std::string>       userdata8;
182     USER_PROPERTY_LOGGED<std::string>       userdata9;
183 };
184 //=============================================================================
185
186 //-----------------------------------------------------------------------------
187 //-----------------------------------------------------------------------------
188 //-----------------------------------------------------------------------------
189 template <typename varT>
190 inline
191 USER_PROPERTY<varT>::USER_PROPERTY(varT & val)
192     : value(val),
193       modificationTime(stgTime),
194       beforeNotifiers(),
195       afterNotifiers(),
196       mutex()
197 {
198 pthread_mutex_init(&mutex, NULL);
199 }
200 //-----------------------------------------------------------------------------
201 template <typename varT>
202 inline
203 USER_PROPERTY<varT>::~USER_PROPERTY()
204 {
205 pthread_mutex_destroy(&mutex);
206 }
207 //-----------------------------------------------------------------------------
208 template <typename varT>
209 inline
210 void USER_PROPERTY<varT>::ModifyTime() throw()
211 {
212 modificationTime = stgTime;
213 }
214 //-----------------------------------------------------------------------------
215 template <typename varT>
216 inline
217 void USER_PROPERTY<varT>::Set(const varT & rvalue)
218 {
219 STG_LOCKER locker(&mutex);
220
221 typename std::set<PROPERTY_NOTIFIER_BASE<varT> *>::iterator ni;
222
223 varT oldVal = value;
224
225 ni = beforeNotifiers.begin();
226 while (ni != beforeNotifiers.end())
227     (*ni++)->Notify(oldVal, rvalue);
228
229 value = rvalue;
230 modificationTime = stgTime;
231
232 ni = afterNotifiers.begin();
233 while (ni != afterNotifiers.end())
234     (*ni++)->Notify(oldVal, rvalue);
235 }
236 //-----------------------------------------------------------------------------
237 template <typename varT>
238 inline
239 USER_PROPERTY<varT> & USER_PROPERTY<varT>::operator= (const varT & newValue)
240 {
241 Set(newValue);
242 return *this;
243 }
244 //-----------------------------------------------------------------------------
245 template <typename varT>
246 inline
247 void USER_PROPERTY<varT>::AddBeforeNotifier(PROPERTY_NOTIFIER_BASE<varT> * n)
248 {
249 STG_LOCKER locker(&mutex);
250 beforeNotifiers.insert(n);
251 }
252 //-----------------------------------------------------------------------------
253 template <typename varT>
254 inline
255 void USER_PROPERTY<varT>::DelBeforeNotifier(const PROPERTY_NOTIFIER_BASE<varT> * n)
256 {
257 STG_LOCKER locker(&mutex);
258 beforeNotifiers.erase(const_cast<PROPERTY_NOTIFIER_BASE<varT> *>(n));
259 }
260 //-----------------------------------------------------------------------------
261 template <typename varT>
262 inline
263 void USER_PROPERTY<varT>::AddAfterNotifier(PROPERTY_NOTIFIER_BASE<varT> * n)
264 {
265 STG_LOCKER locker(&mutex);
266 afterNotifiers.insert(n);
267 }
268 //-----------------------------------------------------------------------------
269 template <typename varT>
270 inline
271 void USER_PROPERTY<varT>::DelAfterNotifier(const PROPERTY_NOTIFIER_BASE<varT> * n)
272 {
273 STG_LOCKER locker(&mutex);
274 afterNotifiers.erase(const_cast<PROPERTY_NOTIFIER_BASE<varT> *>(n));
275 }
276 //-----------------------------------------------------------------------------
277 //-----------------------------------------------------------------------------
278 //-----------------------------------------------------------------------------
279 template <typename varT>
280 inline
281 USER_PROPERTY_LOGGED<varT>::USER_PROPERTY_LOGGED(varT & val,
282                                                  const std::string & n,
283                                                  bool isPass,
284                                                  bool isSt,
285                                                  STG_LOGGER & logger,
286                                                  const SETTINGS& s,
287                                                  REGISTRY & properties)
288
289     : USER_PROPERTY<varT>(val),
290       stgLogger(logger),
291       isPassword(isPass),
292       isStat(isSt),
293       name(n),
294       settings(s)
295 {
296 properties.insert(std::make_pair(ToLower(name), this));
297 }
298 //-------------------------------------------------------------------------
299 template <typename varT>
300 bool USER_PROPERTY_LOGGED<varT>::Set(const varT & val,
301                                      const ADMIN * admin,
302                                      const std::string & login,
303                                      const STORE * store,
304                                      const std::string & msg)
305 {
306 const PRIV * priv = admin->GetPriv();
307
308 if ((priv->userConf && !isStat) ||
309     (priv->userStat && isStat) ||
310     (priv->userPasswd && isPassword) ||
311     (priv->userCash && name == "cash"))
312     {
313     std::stringstream oldVal;
314     std::stringstream newVal;
315
316     oldVal.flags(oldVal.flags() | std::ios::fixed);
317     newVal.flags(newVal.flags() | std::ios::fixed);
318
319     oldVal << USER_PROPERTY<varT>::ConstData();
320     newVal << val;
321
322     OnChange(login, name, oldVal.str(), newVal.str(), admin);
323
324     if (isPassword)
325         {
326         WriteSuccessChange(login, admin, name, "******", "******", msg, store);
327         }
328     else
329         {
330         WriteSuccessChange(login, admin, name, oldVal.str(), newVal.str(), msg, store);
331         }
332     USER_PROPERTY<varT>::Set(val);
333     return true;
334     }
335 else
336     {
337     WriteAccessDenied(login, admin, name);
338     return false;
339     }
340 return true;
341 }
342 //-------------------------------------------------------------------------
343 template <typename varT>
344 inline
345 void USER_PROPERTY_LOGGED<varT>::WriteAccessDenied(const std::string & login,
346                                                    const ADMIN * admin,
347                                                    const std::string & parameter)
348 {
349 stgLogger("%s Change user \'%s.\' Parameter \'%s\'. Access denied.",
350           admin->GetLogStr().c_str(), login.c_str(), parameter.c_str());
351 }
352 //-------------------------------------------------------------------------
353 template <typename varT>
354 inline
355 void USER_PROPERTY_LOGGED<varT>::WriteSuccessChange(const std::string & login,
356                                                     const ADMIN * admin,
357                                                     const std::string & parameter,
358                                                     const std::string & oldValue,
359                                                     const std::string & newValue,
360                                                     const std::string & msg,
361                                                     const STORE * store)
362 {
363 stgLogger("%s User \'%s\': \'%s\' parameter changed from \'%s\' to \'%s\'. %s",
364           admin->GetLogStr().c_str(),
365           login.c_str(),
366           parameter.c_str(),
367           oldValue.c_str(),
368           newValue.c_str(),
369           msg.c_str());
370
371 for (size_t i = 0; i < settings.GetFilterParamsLog().size(); ++i)
372     if (settings.GetFilterParamsLog()[i] == "*" || strcasecmp(settings.GetFilterParamsLog()[i].c_str(), parameter.c_str()) == 0)
373         {
374         store->WriteUserChgLog(login, admin->GetLogin(), admin->GetIP(), parameter, oldValue, newValue, msg);
375         return;
376         }
377 }
378 //-------------------------------------------------------------------------
379 template <typename varT>
380 void USER_PROPERTY_LOGGED<varT>::OnChange(const std::string & login,
381                                           const std::string & paramName,
382                                           const std::string & oldValue,
383                                           const std::string & newValue,
384                                           const ADMIN * admin)
385 {
386 static std::string filePath = settings.GetScriptsDir() + "/OnChange";
387
388 if (access(filePath.c_str(), X_OK) == 0)
389     {
390     std::string execString("\"" + filePath + "\" \"" + login + "\" \"" + paramName + "\" \"" + oldValue + "\" \"" + newValue + "\" \"" + admin->GetLogin() + "\" \"" + admin->GetIPStr() + "\"");
391     ScriptExec(execString.c_str());
392     }
393 else
394     {
395     stgLogger("Script OnChange cannot be executed. File %s not found.", filePath.c_str());
396     }
397 }
398 //-------------------------------------------------------------------------
399 //-------------------------------------------------------------------------
400 //-------------------------------------------------------------------------
401 inline
402 std::string USER_PROPERTIES::GetPropertyValue(const std::string & name) const
403 {
404 REGISTRY::const_iterator it = properties.find(ToLower(name));
405 if (it == properties.end())
406     return "";
407 return it->second->ToString();
408 }
409 //-----------------------------------------------------------------------------
410 inline
411 bool USER_PROPERTIES::Exists(const std::string & name) const
412 {
413 return properties.find(ToLower(name)) != properties.end();
414 }
415 //-------------------------------------------------------------------------
416 //-------------------------------------------------------------------------
417 //-------------------------------------------------------------------------
418 template<typename varT>
419 inline
420 std::ostream & operator<< (std::ostream & stream, const USER_PROPERTY<varT> & value)
421 {
422 return stream << value.ConstData();
423 }
424 //-----------------------------------------------------------------------------
425 template<typename varT>
426 inline
427 std::string USER_PROPERTY<varT>::ToString() const
428 {
429 std::ostringstream stream;
430 stream << value;
431 return stream.str();
432 }
433 #endif // USER_PROPERTY_H