]> git.stg.codes - stg.git/blob - projects/stargazer/user_impl.cpp
e832c669950f4088d56b6fb0d3ae25ff7da26655
[stg.git] / projects / stargazer / user_impl.cpp
1 /*
2  *    This program is free software; you can redistribute it and/or modify
3  *    it under the terms of the GNU General Public License as published by
4  *    the Free Software Foundation; either version 2 of the License, or
5  *    (at your option) any later version.
6  *
7  *    This program is distributed in the hope that it will be useful,
8  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
9  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  *    GNU General Public License for more details.
11  *
12  *    You should have received a copy of the GNU General Public License
13  *    along with this program; if not, write to the Free Software
14  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
15  */
16
17 /*
18  *    Date: 27.10.2002
19  */
20
21 /*
22  *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
23  */
24
25 /*
26  $Revision: 1.101 $
27  $Date: 2010/11/03 10:50:03 $
28  $Author: faust $
29  */
30
31 #ifndef _GNU_SOURCE
32 #define _GNU_SOURCE
33 #endif
34
35 #include "user_impl.h"
36 #include "settings_impl.h"
37 #include "stg_timer.h"
38
39 #include "stg/users.h"
40 #include "stg/common.h"
41 #include "stg/scriptexecuter.h"
42 #include "stg/tariff.h"
43 #include "stg/tariffs.h"
44 #include "stg/admin.h"
45
46 #include <algorithm>
47 #include <functional>
48
49 #include <cassert>
50 #include <cstdlib>
51 #include <cmath>
52
53 #include <pthread.h>
54 #include <unistd.h> // access
55
56 namespace
57 {
58
59 std::string dirsToString(const bool * dirs)
60 {
61 std::string res;
62 for (size_t i = 0; i < DIR_NUM; i++)
63     res += dirs[i] ? '1' : '0';
64 return res;
65 }
66
67 void dirsFromBits(bool * dirs, uint32_t bits)
68 {
69 for (size_t i = 0; i < DIR_NUM; i++)
70     dirs[i] = bits & (1 << i);
71 }
72
73 }
74
75 #ifdef USE_ABSTRACT_SETTINGS
76 USER_IMPL::USER_IMPL(const SETTINGS * s,
77            const STORE * st,
78            const TARIFFS * t,
79            const ADMIN * a,
80            const USERS * u)
81     : users(u),
82       property(s->GetScriptsDir()),
83       WriteServLog(GetStgLogger()),
84       lastScanMessages(0),
85       id(0),
86       __connected(0),
87       connected(__connected),
88       __currIP(0),
89       currIP(__currIP),
90       lastIPForDisconnect(0),
91       pingTime(0),
92       sysAdmin(a),
93       store(st),
94       tariffs(t),
95       tariff(NULL),
96       settings(s),
97       authorizedModificationTime(0),
98       deleted(false),
99       lastWriteStat(0),
100       lastWriteDetailedStat(0),
101       cash(property.cash),
102       up(property.up),
103       down(property.down),
104       lastCashAdd(property.lastCashAdd),
105       passiveTime(property.passiveTime),
106       lastCashAddTime(property.lastCashAddTime),
107       freeMb(property.freeMb),
108       lastActivityTime(property.lastActivityTime),
109       password(property.password),
110       passive(property.passive),
111       disabled(property.disabled),
112       disabledDetailStat(property.disabledDetailStat),
113       alwaysOnline(property.alwaysOnline),
114       tariffName(property.tariffName),
115       nextTariff(property.nextTariff),
116       address(property.address),
117       note(property.note),
118       group(property.group),
119       email(property.email),
120       phone(property.phone),
121       realName(property.realName),
122       credit(property.credit),
123       creditExpire(property.creditExpire),
124       ips(property.ips),
125       userdata0(property.userdata0),
126       userdata1(property.userdata1),
127       userdata2(property.userdata2),
128       userdata3(property.userdata3),
129       userdata4(property.userdata4),
130       userdata5(property.userdata5),
131       userdata6(property.userdata6),
132       userdata7(property.userdata7),
133       userdata8(property.userdata8),
134       userdata9(property.userdata9),
135       passiveNotifier(this),
136       disabledNotifier(this),
137       tariffNotifier(this),
138       cashNotifier(this),
139       ipNotifier(this)
140 {
141 Init();
142 }
143 #else
144 USER_IMPL::USER_IMPL(const SETTINGS_IMPL * s,
145                      const STORE * st,
146                      const TARIFFS * t,
147                      const ADMIN * a,
148                      const USERS * u)
149     : users(u),
150       property(s->GetScriptsDir()),
151       WriteServLog(GetStgLogger()),
152       lastScanMessages(0),
153       id(0),
154       __connected(0),
155       connected(__connected),
156       __currIP(0),
157       currIP(__currIP),
158       lastIPForDisconnect(0),
159       pingTime(0),
160       sysAdmin(a),
161       store(st),
162       tariffs(t),
163       tariff(NULL),
164       settings(s),
165       authorizedModificationTime(0),
166       deleted(false),
167       lastWriteStat(0),
168       lastWriteDetailedStat(0),
169       cash(property.cash),
170       up(property.up),
171       down(property.down),
172       lastCashAdd(property.lastCashAdd),
173       passiveTime(property.passiveTime),
174       lastCashAddTime(property.lastCashAddTime),
175       freeMb(property.freeMb),
176       lastActivityTime(property.lastActivityTime),
177       password(property.password),
178       passive(property.passive),
179       disabled(property.disabled),
180       disabledDetailStat(property.disabledDetailStat),
181       alwaysOnline(property.alwaysOnline),
182       tariffName(property.tariffName),
183       nextTariff(property.nextTariff),
184       address(property.address),
185       note(property.note),
186       group(property.group),
187       email(property.email),
188       phone(property.phone),
189       realName(property.realName),
190       credit(property.credit),
191       creditExpire(property.creditExpire),
192       ips(property.ips),
193       userdata0(property.userdata0),
194       userdata1(property.userdata1),
195       userdata2(property.userdata2),
196       userdata3(property.userdata3),
197       userdata4(property.userdata4),
198       userdata5(property.userdata5),
199       userdata6(property.userdata6),
200       userdata7(property.userdata7),
201       userdata8(property.userdata8),
202       userdata9(property.userdata9),
203       passiveNotifier(this),
204       disabledNotifier(this),
205       tariffNotifier(this),
206       cashNotifier(this),
207       ipNotifier(this)
208 {
209 Init();
210 }
211 #endif
212 //-----------------------------------------------------------------------------
213 void USER_IMPL::Init()
214 {
215 password = "*_EMPTY_PASSWORD_*";
216 tariffName = NO_TARIFF_NAME;
217 ips = StrToIPS("*");
218 lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
219 lastWriteDetailedStat = stgTime;
220
221 property.tariffName.AddBeforeNotifier(&tariffNotifier);
222 property.passive.AddBeforeNotifier(&passiveNotifier);
223 property.disabled.AddAfterNotifier(&disabledNotifier);
224 property.cash.AddBeforeNotifier(&cashNotifier);
225 ips.AddAfterNotifier(&ipNotifier);
226
227 pthread_mutexattr_t attr;
228 pthread_mutexattr_init(&attr);
229 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
230 pthread_mutex_init(&mutex, &attr);
231 }
232 //-----------------------------------------------------------------------------
233 USER_IMPL::USER_IMPL(const USER_IMPL & u)
234     : USER(),
235       users(u.users),
236       property(u.settings->GetScriptsDir()),
237       WriteServLog(GetStgLogger()),
238       lastScanMessages(0),
239       login(u.login),
240       id(u.id),
241       __connected(0),
242       connected(__connected),
243       userIDGenerator(u.userIDGenerator),
244       __currIP(u.__currIP),
245       currIP(__currIP),
246       lastIPForDisconnect(0),
247       pingTime(u.pingTime),
248       sysAdmin(u.sysAdmin),
249       store(u.store),
250       tariffs(u.tariffs),
251       tariff(u.tariff),
252       traffStat(u.traffStat),
253       traffStatSaved(u.traffStatSaved),
254       settings(u.settings),
255       authorizedModificationTime(u.authorizedModificationTime),
256       messages(u.messages),
257       deleted(u.deleted),
258       lastWriteStat(u.lastWriteStat),
259       lastWriteDetailedStat(u.lastWriteDetailedStat),
260       cash(property.cash),
261       up(property.up),
262       down(property.down),
263       lastCashAdd(property.lastCashAdd),
264       passiveTime(property.passiveTime),
265       lastCashAddTime(property.lastCashAddTime),
266       freeMb(property.freeMb),
267       lastActivityTime(property.lastActivityTime),
268       password(property.password),
269       passive(property.passive),
270       disabled(property.disabled),
271       disabledDetailStat(property.disabledDetailStat),
272       alwaysOnline(property.alwaysOnline),
273       tariffName(property.tariffName),
274       nextTariff(property.nextTariff),
275       address(property.address),
276       note(property.note),
277       group(property.group),
278       email(property.email),
279       phone(property.phone),
280       realName(property.realName),
281       credit(property.credit),
282       creditExpire(property.creditExpire),
283       ips(property.ips),
284       userdata0(property.userdata0),
285       userdata1(property.userdata1),
286       userdata2(property.userdata2),
287       userdata3(property.userdata3),
288       userdata4(property.userdata4),
289       userdata5(property.userdata5),
290       userdata6(property.userdata6),
291       userdata7(property.userdata7),
292       userdata8(property.userdata8),
293       userdata9(property.userdata9),
294       sessionUpload(),
295       sessionDownload(),
296       passiveNotifier(this),
297       disabledNotifier(this),
298       tariffNotifier(this),
299       cashNotifier(this),
300       ipNotifier(this)
301 {
302 if (&u == this)
303     return;
304
305 property.tariffName.AddBeforeNotifier(&tariffNotifier);
306 property.passive.AddBeforeNotifier(&passiveNotifier);
307 property.disabled.AddAfterNotifier(&disabledNotifier);
308 property.cash.AddBeforeNotifier(&cashNotifier);
309 ips.AddAfterNotifier(&ipNotifier);
310
311 property.SetProperties(u.property);
312
313 pthread_mutexattr_t attr;
314 pthread_mutexattr_init(&attr);
315 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
316 pthread_mutex_init(&mutex, &attr);
317 }
318 //-----------------------------------------------------------------------------
319 USER_IMPL::~USER_IMPL()
320 {
321 property.tariffName.DelBeforeNotifier(&tariffNotifier);
322 property.passive.DelBeforeNotifier(&passiveNotifier);
323 property.disabled.DelAfterNotifier(&disabledNotifier);
324 property.cash.DelBeforeNotifier(&cashNotifier);
325 pthread_mutex_destroy(&mutex);
326 }
327 //-----------------------------------------------------------------------------
328 void USER_IMPL::SetLogin(const std::string & l)
329 {
330 STG_LOCKER lock(&mutex);
331 assert(login.empty() && "Login is already set");
332 login = l;
333 id = userIDGenerator.GetNextID();
334 }
335 //-----------------------------------------------------------------------------
336 int USER_IMPL::ReadConf()
337 {
338 STG_LOCKER lock(&mutex);
339 USER_CONF conf;
340
341 if (store->RestoreUserConf(&conf, login))
342     {
343     WriteServLog("Cannot read conf for user %s.", login.c_str());
344     WriteServLog("%s", store->GetStrError().c_str());
345     printfd(__FILE__, "Cannot read conf for user %s.\n", login.c_str());
346     printfd(__FILE__, "%s\n", store->GetStrError().c_str());
347     return -1;
348     }
349
350 property.SetConf(conf);
351
352 tariff = tariffs->FindByName(tariffName);
353 if (tariff == NULL)
354     {
355     WriteServLog("Cannot read user %s. Tariff %s not exist.",
356                  login.c_str(), property.tariffName.Get().c_str());
357     return -1;
358     }
359
360 std::vector<STG_MSG_HDR> hdrsList;
361
362 if (store->GetMessageHdrs(&hdrsList, login))
363     {
364     printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str());
365     WriteServLog("Cannot read user %s. Error reading message headers: %s.",
366                  login.c_str(),
367                  store->GetStrError().c_str());
368     return -1;
369     }
370
371 std::vector<STG_MSG_HDR>::const_iterator it;
372 for (it = hdrsList.begin(); it != hdrsList.end(); ++it)
373     {
374     STG_MSG msg;
375     if (store->GetMessage(it->id, &msg, login) == 0)
376         {
377         messages.push_back(msg);
378         }
379     }
380
381 return 0;
382 }
383 //-----------------------------------------------------------------------------
384 int USER_IMPL::ReadStat()
385 {
386 STG_LOCKER lock(&mutex);
387 USER_STAT stat;
388
389 if (store->RestoreUserStat(&stat, login))
390     {
391     WriteServLog("Cannot read stat for user %s.", login.c_str());
392     WriteServLog("%s", store->GetStrError().c_str());
393     printfd(__FILE__, "Cannot read stat for user %s.\n", login.c_str());
394     printfd(__FILE__, "%s\n", store->GetStrError().c_str());
395     return -1;
396     }
397
398 property.SetStat(stat);
399
400 return 0;
401 }
402 //-----------------------------------------------------------------------------
403 int USER_IMPL::WriteConf()
404 {
405 STG_LOCKER lock(&mutex);
406 USER_CONF conf(property.GetConf());
407
408 printfd(__FILE__, "USER::WriteConf()\n");
409
410 if (store->SaveUserConf(conf, login))
411     {
412     WriteServLog("Cannot write conf for user %s.", login.c_str());
413     WriteServLog("%s", store->GetStrError().c_str());
414     printfd(__FILE__, "Cannot write conf for user %s.\n", login.c_str());
415     printfd(__FILE__, "%s\n", store->GetStrError().c_str());
416     return -1;
417     }
418
419 return 0;
420 }
421 //-----------------------------------------------------------------------------
422 int USER_IMPL::WriteStat()
423 {
424 STG_LOCKER lock(&mutex);
425 USER_STAT stat(property.GetStat());
426
427 if (store->SaveUserStat(stat, login))
428     {
429     WriteServLog("Cannot write stat for user %s.", login.c_str());
430     WriteServLog("%s", store->GetStrError().c_str());
431     printfd(__FILE__, "Cannot write stat for user %s.\n", login.c_str());
432     printfd(__FILE__, "%s\n", store->GetStrError().c_str());
433     return -1;
434     }
435
436 lastWriteStat = stgTime;
437
438 return 0;
439 }
440 //-----------------------------------------------------------------------------
441 int USER_IMPL::WriteMonthStat()
442 {
443 STG_LOCKER lock(&mutex);
444 time_t tt = stgTime - 3600;
445 struct tm t1;
446 localtime_r(&tt, &t1);
447
448 USER_STAT stat(property.GetStat());
449 if (store->SaveMonthStat(stat, t1.tm_mon, t1.tm_year, login))
450     {
451     WriteServLog("Cannot write month stat for user %s.", login.c_str());
452     WriteServLog("%s", store->GetStrError().c_str());
453     printfd(__FILE__, "Cannot write month stat for user %s.\n", login.c_str());
454     printfd(__FILE__, "%s\n", store->GetStrError().c_str());
455     return -1;
456     }
457
458 return 0;
459 }
460 //-----------------------------------------------------------------------------
461 int USER_IMPL::Authorize(uint32_t ip, uint32_t dirs, const AUTH * auth)
462 {
463 STG_LOCKER lock(&mutex);
464 /*
465  *  Authorize user. It only means that user will be authorized. Nothing more.
466  *  User can be connected or disconnected while authorized.
467  *  Example: user is authorized but disconnected due to 0 money or blocking
468  */
469
470 /*
471  * TODO: in fact "authorization" means allowing access to a service. What we
472  * call "authorization" here, int STG, is "authentication". So this should be
473  * fixed in future.
474  */
475
476 /*
477  * Prevent double authorization by identical authorizers
478  */
479 if (authorizedBy.find(auth) != authorizedBy.end())
480     return 0;
481
482 if (!ip)
483     return -1;
484
485 dirsFromBits(enabledDirs, dirs);
486
487 if (!authorizedBy.empty())
488     {
489     if (currIP != ip)
490         {
491         // We are already authorized, but with different IP address
492         errorStr = "User " + login + " already authorized with IP address " + inet_ntostring(ip);
493         return -1;
494         }
495
496     USER * u = NULL;
497     if (!users->FindByIPIdx(ip, &u))
498         {
499         // Address presents in IP-index.
500         // If it's not our IP - report it.
501         if (u != this)
502             {
503             errorStr = "IP address " + inet_ntostring(ip) + " is already in use";
504             return -1;
505             }
506         }
507     }
508 else
509     {
510     if (users->IsIPInIndex(ip))
511         {
512         // Address is already present in IP-index.
513         errorStr = "IP address " + inet_ntostring(ip) + " is already in use";
514         return -1;
515         }
516
517     if (ips.ConstData().IsIPInIPS(ip))
518         {
519         currIP = ip;
520         lastIPForDisconnect = currIP;
521         }
522     else
523         {
524         printfd(__FILE__, " user %s: ips = %s\n", login.c_str(), ips.ConstData().GetIpStr().c_str());
525         errorStr = "IP address " + inet_ntostring(ip) + " does not belong to user " + login;
526         return -1;
527         }
528     }
529
530 if (authorizedBy.empty())
531     authorizedModificationTime = stgTime;
532 authorizedBy.insert(auth);
533
534 ScanMessage();
535
536 return 0;
537 }
538 //-----------------------------------------------------------------------------
539 void USER_IMPL::Unauthorize(const AUTH * auth, const std::string & reason)
540 {
541 STG_LOCKER lock(&mutex);
542 /*
543  *  Authorizer tries to unauthorize user, that was not authorized by it
544  */
545 if (!authorizedBy.erase(auth))
546     return;
547
548 authorizedModificationTime = stgTime;
549
550 if (authorizedBy.empty())
551     {
552     lastDisconnectReason = reason;
553     lastIPForDisconnect = currIP;
554     currIP = 0; // DelUser in traffcounter
555     return;
556     }
557 }
558 //-----------------------------------------------------------------------------
559 bool USER_IMPL::IsAuthorizedBy(const AUTH * auth) const
560 {
561 STG_LOCKER lock(&mutex);
562 // Is this user authorized by specified authorizer?
563 return authorizedBy.find(auth) != authorizedBy.end();
564 }
565 //-----------------------------------------------------------------------------
566 std::vector<std::string> USER_IMPL::GetAuthorizers() const
567 {
568     STG_LOCKER lock(&mutex);
569     std::vector<std::string> list;
570     std::transform(authorizedBy.begin(), authorizedBy.end(), std::back_inserter(list), std::mem_fun(&AUTH::GetVersion));
571     return list;
572 }
573 //-----------------------------------------------------------------------------
574 void USER_IMPL::Connect(bool fakeConnect)
575 {
576 /*
577  * Connect user to Internet. This function is differ from Authorize() !!!
578  */
579
580 STG_LOCKER lock(&mutex);
581
582 if (!fakeConnect)
583     {
584     std::string scriptOnConnect = settings->GetScriptsDir() + "/OnConnect";
585
586     if (access(scriptOnConnect.c_str(), X_OK) == 0)
587         {
588         std::string dirs = dirsToString(enabledDirs);
589
590         std::string scriptOnConnectParams;
591         strprintf(&scriptOnConnectParams,
592                   "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
593                   scriptOnConnect.c_str(),
594                   login.c_str(),
595                   inet_ntostring(currIP).c_str(),
596                   cash.ConstData(),
597                   id,
598                   dirs.c_str());
599
600         std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
601         while (it != settings->GetScriptParams().end())
602             {
603             scriptOnConnectParams += " \"" + GetParamValue(it->c_str()) + "\"";
604             ++it;
605             }
606
607         ScriptExec(scriptOnConnectParams.c_str());
608         }
609     else
610         {
611         WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
612         }
613
614     connected = true;
615     }
616
617 if (store->WriteUserConnect(login, currIP))
618     {
619     WriteServLog("Cannot write connect for user %s.", login.c_str());
620     WriteServLog("%s", store->GetStrError().c_str());
621     }
622
623 if (!fakeConnect)
624     lastIPForDisconnect = currIP;
625 }
626 //-----------------------------------------------------------------------------
627 void USER_IMPL::Disconnect(bool fakeDisconnect, const std::string & reason)
628 {
629 /*
630  *  Disconnect user from Internet. This function is differ from UnAuthorize() !!!
631  */
632
633 STG_LOCKER lock(&mutex);
634
635 if (!lastIPForDisconnect)
636     {
637     printfd(__FILE__, "lastIPForDisconnect\n");
638     return;
639     }
640
641 if (!fakeDisconnect)
642     {
643     lastDisconnectReason = reason;
644     std::string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
645
646     if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
647         {
648         std::string dirs = dirsToString(enabledDirs);
649
650         std::string scriptOnDisonnectParams;
651         strprintf(&scriptOnDisonnectParams,
652                 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
653                 scriptOnDisonnect.c_str(),
654                 login.c_str(),
655                 inet_ntostring(lastIPForDisconnect).c_str(),
656                 cash.ConstData(),
657                 id,
658                 dirs.c_str());
659
660         std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
661         while (it != settings->GetScriptParams().end())
662             {
663             scriptOnDisonnectParams += " \"" + GetParamValue(it->c_str()) + "\"";
664             ++it;
665             }
666
667         ScriptExec(scriptOnDisonnectParams.c_str());
668         }
669     else
670         {
671         WriteServLog("Script OnDisconnect cannot be executed. File not found.");
672         }
673
674     connected = false;
675     }
676
677 std::string reasonMessage(reason);
678 if (!lastDisconnectReason.empty())
679     reasonMessage += ": " + lastDisconnectReason;
680
681 if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload,
682                                cash, freeMb, reasonMessage))
683     {
684     WriteServLog("Cannot write disconnect for user %s.", login.c_str());
685     WriteServLog("%s", store->GetStrError().c_str());
686     }
687
688 if (!fakeDisconnect)
689     lastIPForDisconnect = 0;
690
691 sessionUpload.Reset();
692 sessionDownload.Reset();
693 sessionUploadModTime = stgTime;
694 sessionDownloadModTime = stgTime;
695 }
696 //-----------------------------------------------------------------------------
697 void USER_IMPL::Run()
698 {
699 STG_LOCKER lock(&mutex);
700
701 if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
702     {
703     printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
704     WriteStat();
705     }
706 if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
707     {
708     WriteServLog("User: %s. Credit expired.", login.c_str());
709     credit = 0;
710     creditExpire = 0;
711     WriteConf();
712     }
713
714 if (passive.ConstData()
715     && (stgTime % 30 == 0)
716     && (passiveTime.ModificationTime() != stgTime))
717     {
718     passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
719     printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
720     }
721
722 if (!authorizedBy.empty())
723     {
724     if (connected)
725         property.Stat().lastActivityTime = stgTime;
726
727     if (!connected && IsInetable())
728         Connect();
729
730     if (connected && !IsInetable())
731         {
732         if (disabled)
733             Disconnect(false, "disabled");
734         else if (passive)
735             Disconnect(false, "passive");
736         else
737             Disconnect(false, "no cash");
738         }
739
740     if (stgTime - lastScanMessages > 10)
741         {
742         ScanMessage();
743         lastScanMessages = stgTime;
744         }
745     }
746 else
747     {
748     if (connected)
749         Disconnect(false, "not authorized");
750     }
751
752 }
753 //-----------------------------------------------------------------------------
754 void USER_IMPL::UpdatePingTime(time_t t)
755 {
756 STG_LOCKER lock(&mutex);
757 if (t)
758     pingTime = t;
759 else
760     pingTime = stgTime;
761 }
762 //-----------------------------------------------------------------------------
763 bool USER_IMPL::IsInetable()
764 {
765 if (disabled || passive)
766     return false;
767
768 if (settings->GetFreeMbAllowInet())
769     {
770     if (freeMb >= 0)
771         return true;
772     }
773
774 if (settings->GetShowFeeInCash() || tariff == NULL)
775     return (cash >= -credit);
776
777 return (cash - tariff->GetFee() >= -credit);
778 }
779 //-----------------------------------------------------------------------------
780 std::string USER_IMPL::GetEnabledDirs() const
781 {
782 return dirsToString(enabledDirs);
783 }
784 //-----------------------------------------------------------------------------
785 #ifdef TRAFF_STAT_WITH_PORTS
786 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
787 #else
788 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
789 #endif
790 {
791 STG_LOCKER lock(&mutex);
792
793 if (!connected || tariff == NULL)
794     return;
795
796 double cost = 0;
797 DIR_TRAFF dt(up);
798
799 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
800 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
801
802 dt[dir] += len;
803
804 int tt = tariff->GetTraffType();
805 if (tt == TARIFF::TRAFF_UP ||
806     tt == TARIFF::TRAFF_UP_DOWN ||
807     // Check NEW traff data
808     (tt == TARIFF::TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
809     {
810     double dc = 0;
811     if (traff < threshold &&
812         traff + len >= threshold)
813         {
814         // cash = partBeforeThreshold * priceBeforeThreshold +
815         //        partAfterThreshold * priceAfterThreshold
816         int64_t before = threshold - traff; // Chunk part before threshold
817         int64_t after = len - before; // Chunk part after threshold
818         dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
819                                            down.ConstData()[dir],
820                                            dir,
821                                            stgTime) * before +
822              tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
823                                            down.ConstData()[dir],
824                                            dir,
825                                            stgTime) * after;
826         }
827     else
828         {
829         dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
830                                            down.ConstData()[dir],
831                                            dir,
832                                            stgTime) * len;
833         }
834
835     if (freeMb.ConstData() <= 0) // FreeMb is exhausted
836         cost = dc;
837     else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
838         cost = dc - freeMb.ConstData();
839
840     // Direct access to internal data structures via friend-specifier
841     property.Stat().freeMb -= dc;
842     property.Stat().cash -= cost;
843     cash.ModifyTime();
844     freeMb.ModifyTime();
845     }
846
847 up = dt;
848 sessionUpload[dir] += len;
849 sessionUploadModTime = stgTime;
850
851 //Add detailed stat
852
853 if (!settings->GetWriteFreeMbTraffCost() &&
854      freeMb.ConstData() >= 0)
855     cost = 0;
856
857 #ifdef TRAFF_STAT_WITH_PORTS
858 IP_DIR_PAIR idp(ip, dir, port);
859 #else
860 IP_DIR_PAIR idp(ip, dir);
861 #endif
862
863 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
864 lb = traffStat.lower_bound(idp);
865 if (lb == traffStat.end() || lb->first != idp)
866     {
867     traffStat.insert(lb,
868                      std::make_pair(idp,
869                                     STAT_NODE(len, 0, cost)));
870     }
871 else
872     {
873     lb->second.cash += cost;
874     lb->second.up += len;
875     }
876 }
877 //-----------------------------------------------------------------------------
878 #ifdef TRAFF_STAT_WITH_PORTS
879 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
880 #else
881 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
882 #endif
883 {
884 STG_LOCKER lock(&mutex);
885
886 if (!connected || tariff == NULL)
887     return;
888
889 double cost = 0;
890 DIR_TRAFF dt(down);
891
892 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
893 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
894
895 dt[dir] += len;
896
897 int tt = tariff->GetTraffType();
898 if (tt == TARIFF::TRAFF_DOWN ||
899     tt == TARIFF::TRAFF_UP_DOWN ||
900     // Check NEW traff data
901     (tt == TARIFF::TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
902     {
903     double dc = 0;
904     if (traff < threshold &&
905         traff + len >= threshold)
906         {
907         // cash = partBeforeThreshold * priceBeforeThreshold +
908         //        partAfterThreshold * priceAfterThreshold
909         int64_t before = threshold - traff; // Chunk part before threshold
910         int64_t after = len - before; // Chunk part after threshold
911         dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
912                                            down.ConstData()[dir], // Traff before chunk
913                                            dir,
914                                            stgTime) * before +
915              tariff->GetPriceWithTraffType(up.ConstData()[dir],
916                                            dt[dir], // Traff after chunk
917                                            dir,
918                                            stgTime) * after;
919         }
920     else
921         {
922         dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
923                                            down.ConstData()[dir],
924                                            dir,
925                                            stgTime) * len;
926         }
927
928     if (freeMb.ConstData() <= 0) // FreeMb is exhausted
929         cost = dc;
930     else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
931         cost = dc - freeMb.ConstData();
932
933     property.Stat().freeMb -= dc;
934     property.Stat().cash -= cost;
935     cash.ModifyTime();
936     freeMb.ModifyTime();
937     }
938
939 down = dt;
940 sessionDownload[dir] += len;
941 sessionDownloadModTime = stgTime;
942
943 //Add detailed stat
944
945 if (!settings->GetWriteFreeMbTraffCost() &&
946      freeMb.ConstData() >= 0)
947     cost = 0;
948
949 #ifdef TRAFF_STAT_WITH_PORTS
950 IP_DIR_PAIR idp(ip, dir, port);
951 #else
952 IP_DIR_PAIR idp(ip, dir);
953 #endif
954
955 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
956 lb = traffStat.lower_bound(idp);
957 if (lb == traffStat.end() || lb->first != idp)
958     {
959     traffStat.insert(lb,
960                      std::make_pair(idp,
961                                     STAT_NODE(0, len, cost)));
962     }
963 else
964     {
965     lb->second.cash += cost;
966     lb->second.down += len;
967     }
968 }
969 //-----------------------------------------------------------------------------
970 void USER_IMPL::AddCurrIPBeforeNotifier(CURR_IP_NOTIFIER * notifier)
971 {
972 STG_LOCKER lock(&mutex);
973 currIP.AddBeforeNotifier(notifier);
974 }
975 //-----------------------------------------------------------------------------
976 void USER_IMPL::DelCurrIPBeforeNotifier(const CURR_IP_NOTIFIER * notifier)
977 {
978 STG_LOCKER lock(&mutex);
979 currIP.DelBeforeNotifier(notifier);
980 }
981 //-----------------------------------------------------------------------------
982 void USER_IMPL::AddCurrIPAfterNotifier(CURR_IP_NOTIFIER * notifier)
983 {
984 STG_LOCKER lock(&mutex);
985 currIP.AddAfterNotifier(notifier);
986 }
987 //-----------------------------------------------------------------------------
988 void USER_IMPL::DelCurrIPAfterNotifier(const CURR_IP_NOTIFIER * notifier)
989 {
990 STG_LOCKER lock(&mutex);
991 currIP.DelAfterNotifier(notifier);
992 }
993 //-----------------------------------------------------------------------------
994 void USER_IMPL::AddConnectedBeforeNotifier(CONNECTED_NOTIFIER * notifier)
995 {
996 STG_LOCKER lock(&mutex);
997 connected.AddBeforeNotifier(notifier);
998 }
999 //-----------------------------------------------------------------------------
1000 void USER_IMPL::DelConnectedBeforeNotifier(const CONNECTED_NOTIFIER * notifier)
1001 {
1002 STG_LOCKER lock(&mutex);
1003 connected.DelBeforeNotifier(notifier);
1004 }
1005 //-----------------------------------------------------------------------------
1006 void USER_IMPL::AddConnectedAfterNotifier(CONNECTED_NOTIFIER * notifier)
1007 {
1008 STG_LOCKER lock(&mutex);
1009 connected.AddAfterNotifier(notifier);
1010 }
1011 //-----------------------------------------------------------------------------
1012 void USER_IMPL::DelConnectedAfterNotifier(const CONNECTED_NOTIFIER * notifier)
1013 {
1014 STG_LOCKER lock(&mutex);
1015 connected.DelAfterNotifier(notifier);
1016 }
1017 //-----------------------------------------------------------------------------
1018 void USER_IMPL::OnAdd()
1019 {
1020 STG_LOCKER lock(&mutex);
1021
1022 std::string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
1023
1024 if (access(scriptOnAdd.c_str(), X_OK) == 0)
1025     {
1026     std::string scriptOnAddParams = scriptOnAdd + " \"" + login + "\"";
1027
1028     ScriptExec(scriptOnAddParams.c_str());
1029     }
1030 else
1031     {
1032     WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
1033     }
1034 }
1035 //-----------------------------------------------------------------------------
1036 void USER_IMPL::OnDelete()
1037 {
1038 STG_LOCKER lock(&mutex);
1039
1040 std::string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
1041
1042 if (access(scriptOnDel.c_str(), X_OK) == 0)
1043     {
1044     std::string scriptOnDelParams = scriptOnDel + " \"" + login + "\"";
1045
1046     ScriptExec(scriptOnDelParams.c_str());
1047     }
1048 else
1049     {
1050     WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
1051     }
1052
1053 Run();
1054 }
1055 //-----------------------------------------------------------------------------
1056 int USER_IMPL::WriteDetailStat(bool hard)
1057 {
1058 printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
1059
1060 if (!traffStatSaved.second.empty())
1061     {
1062     if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
1063         {
1064         printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
1065         WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
1066         WriteServLog("%s", store->GetStrError().c_str());
1067         return -1;
1068         }
1069     traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
1070     }
1071
1072 TRAFF_STAT ts;
1073
1074     {
1075     STG_LOCKER lock(&mutex);
1076     ts.swap(traffStat);
1077     }
1078
1079 printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
1080
1081 if (ts.size() && !disabledDetailStat)
1082     {
1083     if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
1084         {
1085         printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
1086         WriteServLog("Cannot write detail stat for user %s.", login.c_str());
1087         WriteServLog("%s", store->GetStrError().c_str());
1088         if (!hard)
1089             {
1090             printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
1091             STG_LOCKER lock(&mutex);
1092             traffStatSaved.second.swap(ts);
1093             traffStatSaved.first = lastWriteDetailedStat;
1094             }
1095         return -1;
1096         }
1097     }
1098 lastWriteDetailedStat = stgTime;
1099 return 0;
1100 }
1101 //-----------------------------------------------------------------------------
1102 double USER_IMPL::GetPassiveTimePart() const
1103 {
1104 STG_LOCKER lock(&mutex);
1105
1106 static int daysInMonth[12] =
1107 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1108
1109 struct tm tms;
1110 time_t t = stgTime;
1111 localtime_r(&t, &tms);
1112
1113 time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
1114
1115 if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
1116     {
1117     // Leap year
1118     secMonth += 24 * 3600;
1119     }
1120
1121 time_t dt = secMonth - passiveTime;
1122
1123 if (dt < 0)
1124     dt = 0;
1125
1126 return static_cast<double>(dt) / secMonth;
1127 }
1128 //-----------------------------------------------------------------------------
1129 void USER_IMPL::SetPassiveTimeAsNewUser()
1130 {
1131 STG_LOCKER lock(&mutex);
1132
1133 time_t t = stgTime;
1134 struct tm tm;
1135 localtime_r(&t, &tm);
1136 int daysCurrMon = DaysInCurrentMonth();
1137 double pt = tm.tm_mday - 1;
1138 pt /= daysCurrMon;
1139
1140 passiveTime = static_cast<time_t>(pt * 24 * 3600 * daysCurrMon);
1141 }
1142 //-----------------------------------------------------------------------------
1143 void USER_IMPL::MidnightResetSessionStat()
1144 {
1145 STG_LOCKER lock(&mutex);
1146
1147 if (connected)
1148     {
1149     Disconnect(true, "fake");
1150     Connect(true);
1151     }
1152 }
1153 //-----------------------------------------------------------------------------
1154 void USER_IMPL::ProcessNewMonth()
1155 {
1156 STG_LOCKER lock(&mutex);
1157 //  Reset traff
1158 if (connected)
1159     Disconnect(true, "fake");
1160
1161 WriteMonthStat();
1162
1163 property.Stat().monthUp.Reset();
1164 property.Stat().monthDown.Reset();
1165
1166 if (connected)
1167     Connect(true);
1168
1169 //  Set new tariff
1170 if (nextTariff.ConstData() != "")
1171     {
1172     const TARIFF * nt = tariffs->FindByName(nextTariff);
1173     if (nt == NULL)
1174         WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
1175                      login.c_str(), property.tariffName.Get().c_str());
1176     else
1177         property.tariffName.Set(nextTariff, sysAdmin, login, store);
1178     ResetNextTariff();
1179     WriteConf();
1180     }
1181 }
1182 //-----------------------------------------------------------------------------
1183 void USER_IMPL::ProcessDayFeeSpread()
1184 {
1185 STG_LOCKER lock(&mutex);
1186
1187 if (passive.ConstData() || tariff == NULL)
1188     return;
1189
1190 if (tariff->GetPeriod() != TARIFF::MONTH)
1191     return;
1192
1193 double fee = tariff->GetFee() / DaysInCurrentMonth();
1194
1195 if (std::fabs(fee) < 1.0e-3)
1196     return;
1197
1198 double c = cash;
1199 switch (settings->GetFeeChargeType())
1200     {
1201     case 0:
1202         property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1203         break;
1204     case 1:
1205         if (c + credit >= 0)
1206             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1207         break;
1208     case 2:
1209         if (c + credit >= fee)
1210             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1211         break;
1212     case 3:
1213         if (c >= 0)
1214             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1215         break;
1216     }
1217 ResetPassiveTime();
1218 }
1219 //-----------------------------------------------------------------------------
1220 void USER_IMPL::ProcessDayFee()
1221 {
1222 STG_LOCKER lock(&mutex);
1223
1224 if (tariff == NULL)
1225     return;
1226
1227 if (tariff->GetPeriod() != TARIFF::MONTH)
1228     return;
1229
1230 double passiveTimePart = 1.0;
1231 if (!settings->GetFullFee())
1232     {
1233     passiveTimePart = GetPassiveTimePart();
1234     }
1235 else
1236     {
1237     if (passive.ConstData())
1238         {
1239         printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1240         return;
1241         }
1242     }
1243 double fee = tariff->GetFee() * passiveTimePart;
1244
1245 ResetPassiveTime();
1246
1247 if (std::fabs(fee) < 1.0e-3)
1248     {
1249     SetPrepaidTraff();
1250     return;
1251     }
1252
1253 double c = cash;
1254 printfd(__FILE__, "login: %8s Cash=%f Credit=%f  Fee=%f PassiveTimePart=%f fee=%f\n",
1255         login.c_str(),
1256         cash.ConstData(),
1257         credit.ConstData(),
1258         tariff->GetFee(),
1259         passiveTimePart,
1260         fee);
1261 switch (settings->GetFeeChargeType())
1262     {
1263     case 0:
1264         property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1265         SetPrepaidTraff();
1266         break;
1267     case 1:
1268         if (c + credit >= 0)
1269             {
1270             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1271             SetPrepaidTraff();
1272             }
1273         break;
1274     case 2:
1275         if (c + credit >= fee)
1276             {
1277             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1278             SetPrepaidTraff();
1279             }
1280         break;
1281     case 3:
1282         if (c >= 0)
1283             {
1284             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1285             SetPrepaidTraff();
1286             }
1287         break;
1288     }
1289 }
1290 //-----------------------------------------------------------------------------
1291 void USER_IMPL::ProcessDailyFee()
1292 {
1293 STG_LOCKER lock(&mutex);
1294
1295 if (passive.ConstData() || tariff == NULL)
1296     return;
1297
1298 if (tariff->GetPeriod() != TARIFF::DAY)
1299     return;
1300
1301 double fee = tariff->GetFee();
1302
1303 if (fee == 0.0)
1304     return;
1305
1306 double c = cash;
1307 switch (settings->GetFeeChargeType())
1308     {
1309     case 0:
1310         property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1311         break;
1312     case 1:
1313         if (c + credit >= 0)
1314             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1315         break;
1316     case 2:
1317         if (c + credit >= fee)
1318             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1319         break;
1320     }
1321 ResetPassiveTime();
1322 }
1323 //-----------------------------------------------------------------------------
1324 void USER_IMPL::SetPrepaidTraff()
1325 {
1326 if (tariff != NULL)
1327     property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
1328 }
1329 //-----------------------------------------------------------------------------
1330 int USER_IMPL::AddMessage(STG_MSG * msg)
1331 {
1332 STG_LOCKER lock(&mutex);
1333
1334 if (SendMessage(*msg))
1335     {
1336     if (store->AddMessage(msg, login))
1337         {
1338         errorStr = store->GetStrError();
1339         WriteServLog("Error adding message: '%s'", errorStr.c_str());
1340         printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
1341         return -1;
1342         }
1343     messages.push_back(*msg);
1344     }
1345 else
1346     {
1347     if (msg->header.repeat > 0)
1348         {
1349         msg->header.repeat--;
1350         #ifndef DEBUG
1351         //TODO: gcc v. 4.x generate ICE on x86_64
1352         msg->header.lastSendTime = static_cast<int>(time(NULL));
1353         #else
1354         msg->header.lastSendTime = static_cast<int>(stgTime);
1355         #endif
1356         if (store->AddMessage(msg, login))
1357             {
1358             errorStr = store->GetStrError();
1359             WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
1360             printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
1361             return -1;
1362             }
1363         messages.push_back(*msg);
1364         }
1365     }
1366 return 0;
1367 }
1368 //-----------------------------------------------------------------------------
1369 int USER_IMPL::SendMessage(STG_MSG & msg) const
1370 {
1371 // No lock `cause we are already locked from caller
1372 int ret = -1;
1373 std::set<const AUTH*>::iterator it(authorizedBy.begin());
1374 while (it != authorizedBy.end())
1375     {
1376     if (!(*it++)->SendMessage(msg, currIP))
1377         ret = 0;
1378     }
1379 if (!ret)
1380     {
1381 #ifndef DEBUG
1382     //TODO: gcc v. 4.x generate ICE on x86_64
1383     msg.header.lastSendTime = static_cast<int>(time(NULL));
1384 #else
1385     msg.header.lastSendTime = static_cast<int>(stgTime);
1386 #endif
1387     msg.header.repeat--;
1388     }
1389 return ret;
1390 }
1391 //-----------------------------------------------------------------------------
1392 void USER_IMPL::ScanMessage()
1393 {
1394 // No lock `cause we are already locked from caller
1395 // We need not check for the authorizedBy `cause it has already checked by caller
1396
1397 std::list<STG_MSG>::iterator it(messages.begin());
1398 while (it != messages.end())
1399     {
1400     if (settings->GetMessageTimeout() > 0 &&
1401         difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
1402         {
1403         // Timeout exceeded
1404         if (store->DelMessage(it->header.id, login))
1405             {
1406             WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1407             printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1408             }
1409         messages.erase(it++);
1410         continue;
1411         }
1412     if (it->GetNextSendTime() <= stgTime)
1413         {
1414         if (SendMessage(*it))
1415             {
1416             // We need to check all messages in queue for timeout
1417             ++it;
1418             continue;
1419             }
1420         if (it->header.repeat < 0)
1421             {
1422             if (store->DelMessage(it->header.id, login))
1423                 {
1424                 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1425                 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1426                 }
1427             messages.erase(it++);
1428             }
1429         else
1430             {
1431             if (store->EditMessage(*it, login))
1432                 {
1433                 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
1434                 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
1435                 }
1436             ++it;
1437             }
1438         }
1439     else
1440         {
1441         ++it;
1442         }
1443     }
1444 }
1445 //-----------------------------------------------------------------------------
1446 std::string USER_IMPL::GetParamValue(const std::string & name) const
1447 {
1448     std::string lowerName = ToLower(name);
1449     if (lowerName == "id")
1450         {
1451         std::ostringstream stream;
1452         stream << id;
1453         return stream.str();
1454         }
1455     if (lowerName == "login")       return login;
1456     if (lowerName == "currip")      return currIP.ToString();
1457     if (lowerName == "enableddirs") return GetEnabledDirs();
1458     if (lowerName == "tariff")      return property.tariffName;
1459     if (property.Exists(lowerName))
1460         return property.GetPropertyValue(lowerName);
1461     else
1462         {
1463         WriteServLog("User’s parameter '%s' does not exist.", name.c_str());
1464         return "";
1465         }
1466 }
1467 //-----------------------------------------------------------------------------
1468 //-----------------------------------------------------------------------------
1469 //-----------------------------------------------------------------------------
1470 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
1471 {
1472 if (newPassive && !oldPassive && user->tariff != NULL)
1473     user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
1474                             user->sysAdmin,
1475                             user->login,
1476                             user->store,
1477                             "Freeze");
1478 }
1479 //-----------------------------------------------------------------------------
1480 void CHG_DISABLED_NOTIFIER::Notify(const int & oldValue, const int & newValue)
1481 {
1482 if (oldValue && !newValue && user->GetConnected())
1483     user->Disconnect(false, "disabled");
1484 else if (!oldValue && newValue && user->IsInetable())
1485     user->Connect(false);
1486 }
1487 //-----------------------------------------------------------------------------
1488 void CHG_TARIFF_NOTIFIER::Notify(const std::string &, const std::string & newTariff)
1489 {
1490 if (user->settings->GetReconnectOnTariffChange() && user->connected)
1491     user->Disconnect(false, "Change tariff");
1492 user->tariff = user->tariffs->FindByName(newTariff);
1493 if (user->settings->GetReconnectOnTariffChange() &&
1494     !user->authorizedBy.empty() &&
1495     user->IsInetable())
1496     user->Connect(false);
1497 }
1498 //-----------------------------------------------------------------------------
1499 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
1500 {
1501 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
1502 user->lastCashAdd = newCash - oldCash;
1503 }
1504 //-----------------------------------------------------------------------------
1505 void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to)
1506 {
1507 printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str());
1508 if (user->connected)
1509     user->Disconnect(false, "Change IP");
1510 if (!user->authorizedBy.empty() && user->IsInetable())
1511     user->Connect(false);
1512 }