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