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