]> git.stg.codes - stg.git/blob - projects/stargazer/user_impl.cpp
f3e234200df5890b1eeb2c91ce65583ec1a2cd80
[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         strprintf(&scriptOnConnectParams,
593                 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
594                 scriptOnConnect.c_str(),
595                 login.c_str(),
596                 inet_ntostring(currIP).c_str(),
597                 cash.ConstData(),
598                 id,
599                 dirsStr);
600
601         std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
602         while (it != settings->GetScriptParams().end())
603             {
604             scriptOnConnectParams += " \"";
605             scriptOnConnectParams += GetParamValue(it->c_str());
606             scriptOnConnectParams += "\"";
607             }
608
609         ScriptExec(scriptOnConnectParams.c_str());
610         }
611     else
612         {
613         WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
614         }
615
616     connected = true;
617     }
618
619 if (store->WriteUserConnect(login, currIP))
620     {
621     WriteServLog("Cannot write connect for user %s.", login.c_str());
622     WriteServLog("%s", store->GetStrError().c_str());
623     }
624
625 if (!fakeConnect)
626     lastIPForDisconnect = currIP;
627 }
628 //-----------------------------------------------------------------------------
629 void USER_IMPL::Disconnect(bool fakeDisconnect, const std::string & reason)
630 {
631 /*
632  *  Disconnect user from Internet. This function is differ from UnAuthorize() !!!
633  */
634
635 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
636
637 if (!lastIPForDisconnect)
638     {
639     printfd(__FILE__, "lastIPForDisconnect\n");
640     return;
641     }
642
643 if (!fakeDisconnect)
644     {
645     std::string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
646
647     if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
648         {
649         char dirsStr[DIR_NUM + 1];
650         dirsStr[DIR_NUM] = 0;
651         for (int i = 0; i < DIR_NUM; i++)
652             {
653             dirsStr[i] = enabledDirs[i] ? '1' : '0';
654             }
655
656         std::string scriptOnDisonnectParams;
657         strprintf(&scriptOnDisonnectParams,
658                 "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
659                 scriptOnDisonnect.c_str(),
660                 login.c_str(),
661                 inet_ntostring(lastIPForDisconnect).c_str(),
662                 cash.ConstData(),
663                 id,
664                 dirsStr);
665
666         std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
667         while (it != settings->GetScriptParams().end())
668             {
669             scriptOnDisonnectParams += " \"";
670             scriptOnDisonnectParams += GetParamValue(it->c_str());
671             scriptOnDisonnectParams += "\"";
672             }
673
674         ScriptExec(scriptOnDisonnectParams.c_str());
675         }
676     else
677         {
678         WriteServLog("Script OnDisconnect cannot be executed. File not found.");
679         }
680
681     connected = false;
682     }
683
684 if (store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload, cash, freeMb, reason))
685     {
686     WriteServLog("Cannot write disconnect for user %s.", login.c_str());
687     WriteServLog("%s", store->GetStrError().c_str());
688     }
689
690 if (!fakeDisconnect)
691     lastIPForDisconnect = 0;
692
693 DIR_TRAFF zeroSesssion;
694
695 sessionUpload = zeroSesssion;
696 sessionDownload = zeroSesssion;
697 }
698 //-----------------------------------------------------------------------------
699 void USER_IMPL::PrintUser() const
700 {
701 //return;
702 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
703 std::cout << "============================================================" << std::endl;
704 std::cout << "id=" << id << std::endl;
705 std::cout << "login=" << login << std::endl;
706 std::cout << "password=" << password << std::endl;
707 std::cout << "passive=" << passive << std::endl;
708 std::cout << "disabled=" << disabled << std::endl;
709 std::cout << "disabledDetailStat=" << disabledDetailStat << std::endl;
710 std::cout << "alwaysOnline=" << alwaysOnline << std::endl;
711 std::cout << "tariffName=" << tariffName << std::endl;
712 std::cout << "address=" << address << std::endl;
713 std::cout << "phone=" << phone << std::endl;
714 std::cout << "email=" << email << std::endl;
715 std::cout << "note=" << note << std::endl;
716 std::cout << "realName=" <<realName << std::endl;
717 std::cout << "group=" << group << std::endl;
718 std::cout << "credit=" << credit << std::endl;
719 std::cout << "nextTariff=" << nextTariff << std::endl;
720 std::cout << "userdata0" << userdata0 << std::endl;
721 std::cout << "userdata1" << userdata1 << std::endl;
722 std::cout << "creditExpire=" << creditExpire << std::endl;
723 std::cout << "ips=" << ips << std::endl;
724 std::cout << "------------------------" << std::endl;
725 std::cout << "up=" << up << std::endl;
726 std::cout << "down=" << down << std::endl;
727 std::cout << "cash=" << cash << std::endl;
728 std::cout << "freeMb=" << freeMb << std::endl;
729 std::cout << "lastCashAdd=" << lastCashAdd << std::endl;
730 std::cout << "lastCashAddTime=" << lastCashAddTime << std::endl;
731 std::cout << "passiveTime=" << passiveTime << std::endl;
732 std::cout << "lastActivityTime=" << lastActivityTime << std::endl;
733 std::cout << "============================================================" << std::endl;
734 }
735 //-----------------------------------------------------------------------------
736 void USER_IMPL::Run()
737 {
738 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
739
740 if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
741     {
742     printfd(__FILE__, "USER::WriteStat user=%s\n", GetLogin().c_str());
743     WriteStat();
744     }
745 if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
746     {
747     WriteServLog("User: %s. Credit expired.", login.c_str());
748     credit = 0;
749     creditExpire = 0;
750     WriteConf();
751     }
752
753 if (passive.ConstData()
754     && (stgTime % 30 == 0)
755     && (passiveTime.ModificationTime() != stgTime))
756     {
757     passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
758     printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
759     }
760
761 if (!authorizedBy.empty())
762     {
763     if (connected)
764         {
765         property.Stat().lastActivityTime = stgTime;
766         }
767     if (!connected && IsInetable())
768         {
769         Connect();
770         }
771     if (connected && !IsInetable())
772         {
773         if (disabled)
774             Disconnect(false, "disabled");
775         else if (passive)
776             Disconnect(false, "passive");
777         else
778             Disconnect(false, "no cash");
779         }
780
781     if (stgTime - lastScanMessages > 10)
782         {
783         ScanMessage();
784         lastScanMessages = stgTime;
785         }
786     }
787 else
788     {
789     if (connected)
790         {
791         Disconnect(false, "not authorized");
792         }
793     }
794
795 }
796 //-----------------------------------------------------------------------------
797 void USER_IMPL::UpdatePingTime(time_t t)
798 {
799 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
800 //printfd(__FILE__, "UpdatePingTime(%d) %s\n", t, login.c_str());
801 if (t)
802     pingTime = t;
803 else
804     pingTime = stgTime;
805 }
806 //-----------------------------------------------------------------------------
807 bool USER_IMPL::IsInetable()
808 {
809 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
810
811 if (disabled || passive)
812     return false;
813
814 if (settings->GetFreeMbAllowInet())
815     {
816     if (freeMb >= 0)
817         return true;
818     }
819
820 if (settings->GetShowFeeInCash() || tariff == NULL)
821     {
822     return (cash >= -credit);
823     }
824
825 return (cash - tariff->GetFee() >= -credit);
826 }
827 //-----------------------------------------------------------------------------
828 std::string USER_IMPL::GetEnabledDirs()
829 {
830 //STG_LOCKER lock(&mutex, __FILE__, __LINE__);
831
832 std::string dirs = "";
833 for(int i = 0; i < DIR_NUM; i++)
834     dirs += enabledDirs[i] ? "1" : "0";
835 return dirs;
836 }
837 //-----------------------------------------------------------------------------
838 #ifdef TRAFF_STAT_WITH_PORTS
839 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
840 #else
841 void USER_IMPL::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
842 #endif
843 {
844 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
845
846 if (!connected || tariff == NULL)
847     return;
848
849 double cost = 0;
850 DIR_TRAFF dt(up);
851
852 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
853 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
854
855 dt[dir] += len;
856
857 int tt = tariff->GetTraffType();
858 if (tt == TRAFF_UP ||
859     tt == TRAFF_UP_DOWN ||
860     // Check NEW traff data
861     (tt == TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
862     {
863     double dc = 0;
864     if (traff < threshold &&
865         traff + len >= threshold)
866         {
867         // cash = partBeforeThreshold * priceBeforeThreshold +
868         //        partAfterThreshold * priceAfterThreshold
869         int64_t before = threshold - traff; // Chunk part before threshold
870         int64_t after = len - before; // Chunk part after threshold
871         dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
872                                            down.ConstData()[dir],
873                                            dir,
874                                            stgTime) * before +
875              tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
876                                            down.ConstData()[dir],
877                                            dir,
878                                            stgTime) * after;
879         }
880     else
881         {
882         dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
883                                            down.ConstData()[dir],
884                                            dir,
885                                            stgTime) * len;
886         }
887
888     if (freeMb.ConstData() <= 0) // FreeMb is exhausted
889         cost = dc;
890     else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
891         cost = dc - freeMb.ConstData();
892
893     // Direct access to internal data structures via friend-specifier
894     property.Stat().freeMb -= dc;
895     property.Stat().cash -= cost;
896     cash.ModifyTime();
897     freeMb.ModifyTime();
898     }
899
900 up = dt;
901 sessionUpload[dir] += len;
902
903 //Add detailed stat
904
905 if (!settings->GetWriteFreeMbTraffCost() &&
906      freeMb.ConstData() >= 0)
907     cost = 0;
908
909 #ifdef TRAFF_STAT_WITH_PORTS
910 IP_DIR_PAIR idp(ip, dir, port);
911 #else
912 IP_DIR_PAIR idp(ip, dir);
913 #endif
914
915 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
916 lb = traffStat.lower_bound(idp);
917 if (lb == traffStat.end() || lb->first != idp)
918     {
919     traffStat.insert(lb,
920                      std::make_pair(idp,
921                                     STAT_NODE(len, 0, cost)));
922     }
923 else
924     {
925     lb->second.cash += cost;
926     lb->second.up += len;
927     }
928 }
929 //-----------------------------------------------------------------------------
930 #ifdef TRAFF_STAT_WITH_PORTS
931 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
932 #else
933 void USER_IMPL::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
934 #endif
935 {
936 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
937
938 if (!connected || tariff == NULL)
939     return;
940
941 double cost = 0;
942 DIR_TRAFF dt(down);
943
944 int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
945 int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
946
947 dt[dir] += len;
948
949 int tt = tariff->GetTraffType();
950 if (tt == TRAFF_DOWN ||
951     tt == TRAFF_UP_DOWN ||
952     // Check NEW traff data
953     (tt == TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
954     {
955     double dc = 0;
956     if (traff < threshold &&
957         traff + len >= threshold)
958         {
959         // cash = partBeforeThreshold * priceBeforeThreshold +
960         //        partAfterThreshold * priceAfterThreshold
961         int64_t before = threshold - traff; // Chunk part before threshold
962         int64_t after = len - before; // Chunk part after threshold
963         dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
964                                            down.ConstData()[dir], // Traff before chunk
965                                            dir,
966                                            stgTime) * before +
967              tariff->GetPriceWithTraffType(up.ConstData()[dir],
968                                            dt[dir], // Traff after chunk
969                                            dir,
970                                            stgTime) * after;
971         }
972     else
973         {
974         dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
975                                            down.ConstData()[dir],
976                                            dir,
977                                            stgTime) * len;
978         }
979
980     if (freeMb.ConstData() <= 0) // FreeMb is exhausted
981         cost = dc;
982     else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
983         cost = dc - freeMb.ConstData();
984
985     property.Stat().freeMb -= dc;
986     property.Stat().cash -= cost;
987     cash.ModifyTime();
988     freeMb.ModifyTime();
989     }
990
991 down = dt;
992 sessionDownload[dir] += len;
993
994 //Add detailed stat
995
996 if (!settings->GetWriteFreeMbTraffCost() &&
997      freeMb.ConstData() >= 0)
998     cost = 0;
999
1000 #ifdef TRAFF_STAT_WITH_PORTS
1001 IP_DIR_PAIR idp(ip, dir, port);
1002 #else
1003 IP_DIR_PAIR idp(ip, dir);
1004 #endif
1005
1006 std::map<IP_DIR_PAIR, STAT_NODE>::iterator lb;
1007 lb = traffStat.lower_bound(idp);
1008 if (lb == traffStat.end() || lb->first != idp)
1009     {
1010     traffStat.insert(lb,
1011                      std::make_pair(idp,
1012                                     STAT_NODE(0, len, cost)));
1013     }
1014 else
1015     {
1016     lb->second.cash += cost;
1017     lb->second.down += len;
1018     }
1019 }
1020 //-----------------------------------------------------------------------------
1021 void USER_IMPL::AddCurrIPBeforeNotifier(CURR_IP_NOTIFIER * notifier)
1022 {
1023 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1024 currIP.AddBeforeNotifier(notifier);
1025 }
1026 //-----------------------------------------------------------------------------
1027 void USER_IMPL::DelCurrIPBeforeNotifier(const CURR_IP_NOTIFIER * notifier)
1028 {
1029 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1030 currIP.DelBeforeNotifier(notifier);
1031 }
1032 //-----------------------------------------------------------------------------
1033 void USER_IMPL::AddCurrIPAfterNotifier(CURR_IP_NOTIFIER * notifier)
1034 {
1035 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1036 currIP.AddAfterNotifier(notifier);
1037 }
1038 //-----------------------------------------------------------------------------
1039 void USER_IMPL::DelCurrIPAfterNotifier(const CURR_IP_NOTIFIER * notifier)
1040 {
1041 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1042 currIP.DelAfterNotifier(notifier);
1043 }
1044 //-----------------------------------------------------------------------------
1045 void USER_IMPL::AddConnectedBeforeNotifier(CONNECTED_NOTIFIER * notifier)
1046 {
1047 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1048 connected.AddBeforeNotifier(notifier);
1049 }
1050 //-----------------------------------------------------------------------------
1051 void USER_IMPL::DelConnectedBeforeNotifier(const CONNECTED_NOTIFIER * notifier)
1052 {
1053 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1054 connected.DelBeforeNotifier(notifier);
1055 }
1056 //-----------------------------------------------------------------------------
1057 void USER_IMPL::AddConnectedAfterNotifier(CONNECTED_NOTIFIER * notifier)
1058 {
1059 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1060 connected.AddAfterNotifier(notifier);
1061 }
1062 //-----------------------------------------------------------------------------
1063 void USER_IMPL::DelConnectedAfterNotifier(const CONNECTED_NOTIFIER * notifier)
1064 {
1065 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1066 connected.DelAfterNotifier(notifier);
1067 }
1068 //-----------------------------------------------------------------------------
1069 void USER_IMPL::OnAdd()
1070 {
1071 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1072
1073 std::string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
1074
1075 if (access(scriptOnAdd.c_str(), X_OK) == 0)
1076     {
1077     std::string scriptOnAddParams;
1078     strprintf(&scriptOnAddParams,
1079             "%s \"%s\"",
1080             scriptOnAdd.c_str(),
1081             login.c_str());
1082
1083     ScriptExec(scriptOnAddParams.c_str());
1084     }
1085 else
1086     {
1087     WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
1088     }
1089 }
1090 //-----------------------------------------------------------------------------
1091 void USER_IMPL::OnDelete()
1092 {
1093 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1094
1095 std::string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
1096
1097 if (access(scriptOnDel.c_str(), X_OK) == 0)
1098     {
1099     std::string scriptOnDelParams;
1100     strprintf(&scriptOnDelParams,
1101             "%s \"%s\"",
1102             scriptOnDel.c_str(),
1103             login.c_str());
1104
1105     ScriptExec(scriptOnDelParams.c_str());
1106     }
1107 else
1108     {
1109     WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
1110     }
1111
1112 Run();
1113 }
1114 //-----------------------------------------------------------------------------
1115 int USER_IMPL::WriteDetailStat(bool hard)
1116 {
1117 printfd(__FILE__, "USER::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
1118
1119 if (!traffStatSaved.second.empty())
1120     {
1121     if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
1122         {
1123         printfd(__FILE__, "USER::WriteDetailStat() - failed to write detail stat from queue\n");
1124         WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
1125         WriteServLog("%s", store->GetStrError().c_str());
1126         return -1;
1127         }
1128     traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
1129     }
1130
1131 TRAFF_STAT ts;
1132
1133     {
1134     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1135     ts.swap(traffStat);
1136     }
1137
1138 printfd(__FILE__, "USER::WriteDetailedStat() - size = %d\n", ts.size());
1139
1140 if (ts.size() && !disabledDetailStat)
1141     {
1142     if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
1143         {
1144         printfd(__FILE__, "USER::WriteDetailStat() - failed to write current detail stat\n");
1145         WriteServLog("Cannot write detail stat for user %s.", login.c_str());
1146         WriteServLog("%s", store->GetStrError().c_str());
1147         if (!hard)
1148             {
1149             printfd(__FILE__, "USER::WriteDetailStat() - pushing detail stat to queue\n");
1150             STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1151             traffStatSaved.second.swap(ts);
1152             traffStatSaved.first = lastWriteDetailedStat;
1153             }
1154         return -1;
1155         }
1156     }
1157 lastWriteDetailedStat = stgTime;
1158 return 0;
1159 }
1160 //-----------------------------------------------------------------------------
1161 double USER_IMPL::GetPassiveTimePart() const
1162 {
1163 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1164
1165 static int daysInMonth[12] =
1166 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1167
1168 struct tm tms;
1169 time_t t = stgTime;
1170 localtime_r(&t, &tms);
1171
1172 time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
1173
1174 if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
1175     {
1176     // Leap year
1177     secMonth += 24 * 3600;
1178     }
1179
1180 time_t dt = secMonth - passiveTime;
1181
1182 if (dt < 0)
1183     dt = 0;
1184
1185 return static_cast<double>(dt) / secMonth;
1186 }
1187 //-----------------------------------------------------------------------------
1188 void USER_IMPL::SetPassiveTimeAsNewUser()
1189 {
1190 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1191
1192 time_t t = stgTime;
1193 struct tm tm;
1194 localtime_r(&t, &tm);
1195 int daysCurrMon = DaysInCurrentMonth();
1196 double pt = tm.tm_mday - 1;
1197 pt /= daysCurrMon;
1198
1199 passiveTime = static_cast<time_t>(pt * 24 * 3600 * daysCurrMon);
1200 }
1201 //-----------------------------------------------------------------------------
1202 void USER_IMPL::MidnightResetSessionStat()
1203 {
1204 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1205
1206 if (connected)
1207     {
1208     Disconnect(true, "fake");
1209     Connect(true);
1210     }
1211 }
1212 //-----------------------------------------------------------------------------
1213 void USER_IMPL::ProcessNewMonth()
1214 {
1215 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1216 //  Reset traff
1217 if (connected)
1218     {
1219     Disconnect(true, "fake");
1220     }
1221 DIR_TRAFF zeroTarff;
1222
1223 WriteMonthStat();
1224
1225 up = zeroTarff;
1226 down = zeroTarff;
1227
1228 if (connected)
1229     {
1230     Connect(true);
1231     }
1232
1233 //  Set new tariff
1234 if (nextTariff.ConstData() != "")
1235     {
1236     const TARIFF * nt;
1237     nt = tariffs->FindByName(nextTariff);
1238     if (nt == NULL)
1239         {
1240         WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
1241                      login.c_str(), property.tariffName.Get().c_str());
1242         }
1243     else
1244         {
1245         property.tariffName.Set(nextTariff, sysAdmin, login, store);
1246         //tariff = nt;
1247         }
1248     ResetNextTariff();
1249     WriteConf();
1250     }
1251 }
1252 //-----------------------------------------------------------------------------
1253 void USER_IMPL::ProcessDayFeeSpread()
1254 {
1255 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1256
1257 if (passive.ConstData() || tariff == NULL)
1258     return;
1259
1260 double fee = tariff->GetFee() / DaysInCurrentMonth();
1261
1262 if (std::fabs(fee) < 1.0e-3)
1263     return;
1264
1265 double c = cash;
1266 switch (settings->GetFeeChargeType())
1267     {
1268     case 0:
1269         property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1270         break;
1271     case 1:
1272         if (c + credit >= 0)
1273             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1274         break;
1275     case 2:
1276         if (c + credit >= fee)
1277             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1278         break;
1279     case 3:
1280         if (c >= 0)
1281             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1282         break;
1283     }
1284 ResetPassiveTime();
1285 }
1286 //-----------------------------------------------------------------------------
1287 void USER_IMPL::ProcessDayFee()
1288 {
1289 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1290
1291 if (tariff == NULL)
1292     return;
1293
1294 double passiveTimePart = 1.0;
1295 if (!settings->GetFullFee())
1296     {
1297     passiveTimePart = GetPassiveTimePart();
1298     }
1299 else
1300     {
1301     if (passive.ConstData())
1302         {
1303         printfd(__FILE__, "Don't charge fee `cause we are passive\n");
1304         return;
1305         }
1306     }
1307 double fee = tariff->GetFee() * passiveTimePart;
1308
1309 ResetPassiveTime();
1310
1311 if (std::fabs(fee) < 1.0e-3)
1312     {
1313     SetPrepaidTraff();
1314     return;
1315     }
1316
1317 double c = cash;
1318 printfd(__FILE__, "login: %8s Cash=%f Credit=%f  Fee=%f PassiveTimePart=%f fee=%f\n",
1319         login.c_str(),
1320         cash.ConstData(),
1321         credit.ConstData(),
1322         tariff->GetFee(),
1323         passiveTimePart,
1324         fee);
1325 switch (settings->GetFeeChargeType())
1326     {
1327     case 0:
1328         property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1329         SetPrepaidTraff();
1330         break;
1331     case 1:
1332         if (c + credit >= 0)
1333             {
1334             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1335             SetPrepaidTraff();
1336             }
1337         break;
1338     case 2:
1339         if (c + credit >= fee)
1340             {
1341             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1342             SetPrepaidTraff();
1343             }
1344         break;
1345     case 3:
1346         if (c >= 0)
1347             {
1348             property.cash.Set(c - fee, sysAdmin, login, store, "Subscriber fee charge");
1349             SetPrepaidTraff();
1350             }
1351         break;
1352     }
1353 }
1354 //-----------------------------------------------------------------------------
1355 void USER_IMPL::SetPrepaidTraff()
1356 {
1357 if (tariff != NULL)
1358     property.freeMb.Set(tariff->GetFree(), sysAdmin, login, store, "Prepaid traffic");
1359 }
1360 //-----------------------------------------------------------------------------
1361 int USER_IMPL::AddMessage(STG_MSG * msg)
1362 {
1363 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1364
1365 if (SendMessage(*msg))
1366     {
1367     if (store->AddMessage(msg, login))
1368         {
1369         errorStr = store->GetStrError();
1370         WriteServLog("Error adding message: '%s'", errorStr.c_str());
1371         printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
1372         return -1;
1373         }
1374     messages.push_back(*msg);
1375     }
1376 else
1377     {
1378     if (msg->header.repeat > 0)
1379         {
1380         msg->header.repeat--;
1381         #ifndef DEBUG
1382         //TODO: gcc v. 4.x generate ICE on x86_64
1383         msg->header.lastSendTime = static_cast<int>(time(NULL));
1384         #else
1385         msg->header.lastSendTime = static_cast<int>(stgTime);
1386         #endif
1387         if (store->AddMessage(msg, login))
1388             {
1389             errorStr = store->GetStrError();
1390             WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
1391             printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
1392             return -1;
1393             }
1394         messages.push_back(*msg);
1395         }
1396     }
1397 return 0;
1398 }
1399 //-----------------------------------------------------------------------------
1400 int USER_IMPL::SendMessage(STG_MSG & msg) const
1401 {
1402 // No lock `cause we are already locked from caller
1403 int ret = -1;
1404 std::set<const AUTH*>::iterator it(authorizedBy.begin());
1405 while (it != authorizedBy.end())
1406     {
1407     if (!(*it++)->SendMessage(msg, currIP))
1408         ret = 0;
1409     }
1410 if (!ret)
1411     {
1412 #ifndef DEBUG
1413     //TODO: gcc v. 4.x generate ICE on x86_64
1414     msg.header.lastSendTime = static_cast<int>(time(NULL));
1415 #else
1416     msg.header.lastSendTime = static_cast<int>(stgTime);
1417 #endif
1418     msg.header.repeat--;
1419     }
1420 return ret;
1421 }
1422 //-----------------------------------------------------------------------------
1423 void USER_IMPL::ScanMessage()
1424 {
1425 // No lock `cause we are already locked from caller
1426 // We need not check for the authorizedBy `cause it has already checked by caller
1427
1428 std::list<STG_MSG>::iterator it(messages.begin());
1429 while (it != messages.end())
1430     {
1431     if (settings->GetMessageTimeout() > 0 &&
1432         difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
1433         {
1434         // Timeout exceeded
1435         if (store->DelMessage(it->header.id, login))
1436             {
1437             WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1438             printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1439             }
1440         messages.erase(it++);
1441         continue;
1442         }
1443     if (it->GetNextSendTime() <= stgTime)
1444         {
1445         if (SendMessage(*it))
1446             {
1447             // We need to check all messages in queue for timeout
1448             ++it;
1449             continue;
1450             }
1451         if (it->header.repeat < 0)
1452             {
1453             if (store->DelMessage(it->header.id, login))
1454                 {
1455                 WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
1456                 printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
1457                 }
1458             messages.erase(it++);
1459             }
1460         else
1461             {
1462             if (store->EditMessage(*it, login))
1463                 {
1464                 WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
1465                 printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
1466                 }
1467             ++it;
1468             }
1469         }
1470     else
1471         {
1472         ++it;
1473         }
1474     }
1475 }
1476 //-----------------------------------------------------------------------------
1477 std::string USER_IMPL::GetParamValue(const std::string & name) const
1478 {
1479 if (name == "freeMb")       return property.freeMb.ToString();
1480 if (name == "passive")      return property.passive.ToString();
1481 if (name == "disabled")     return property.disabled.ToString();
1482 if (name == "alwaysOnline") return property.alwaysOnline.ToString();
1483 if (name == "tariffName")   return property.tariffName;
1484 if (name == "nextTariff")   return property.nextTariff;
1485 if (name == "address")      return property.address;
1486 if (name == "note")         return property.note;
1487 if (name == "group")        return property.group;
1488 if (name == "email")        return property.email;
1489 if (name == "phone")        return property.phone;
1490 if (name == "realName")     return property.realName;
1491 if (name == "credit")       return property.credit.ToString();
1492 if (name == "userdata0")    return property.userdata0;
1493 if (name == "userdata1")    return property.userdata1;
1494 if (name == "userdata2")    return property.userdata2;
1495 if (name == "userdata3")    return property.userdata3;
1496 if (name == "userdata4")    return property.userdata4;
1497 if (name == "userdata5")    return property.userdata5;
1498 if (name == "userdata6")    return property.userdata6;
1499 if (name == "userdata7")    return property.userdata7;
1500 if (name == "userdata8")    return property.userdata8;
1501 if (name == "userdata9")    return property.userdata9;
1502 //if (name == "cash")         return property.cash.ToString();
1503 //if (name == "id")
1504 //    {
1505 //    std::stringstream stream;
1506 //    stream << id;
1507 //    return stream.str();;
1508 //    }
1509 //if (name == "login")        return login;
1510 //if (name == "ip")           return currIP.ToString();
1511 }
1512 //-----------------------------------------------------------------------------
1513 //-----------------------------------------------------------------------------
1514 //-----------------------------------------------------------------------------
1515 void CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
1516 {
1517 if (newPassive && !oldPassive && user->tariff != NULL)
1518     user->property.cash.Set(user->cash - user->tariff->GetPassiveCost(),
1519                             user->sysAdmin,
1520                             user->login,
1521                             user->store,
1522                             "Freeze");
1523 }
1524 //-----------------------------------------------------------------------------
1525 void CHG_DISABLED_NOTIFIER::Notify(const int & oldValue, const int & newValue)
1526 {
1527 if (oldValue && !newValue && user->GetConnected())
1528     {
1529     user->Disconnect(false, "disabled");
1530     }
1531 else if (!oldValue && newValue && user->IsInetable())
1532     {
1533     user->Connect(false);
1534     }
1535
1536 }
1537 //-----------------------------------------------------------------------------
1538 void CHG_TARIFF_NOTIFIER::Notify(const std::string &, const std::string & newTariff)
1539 {
1540 if (user->settings->GetReconnectOnTariffChange() && user->connected)
1541     user->Disconnect(false, "Change tariff");
1542 user->tariff = user->tariffs->FindByName(newTariff);
1543 if (user->settings->GetReconnectOnTariffChange() &&
1544     !user->authorizedBy.empty() &&
1545     user->IsInetable())
1546     user->Connect(false);
1547 }
1548 //-----------------------------------------------------------------------------
1549 void CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
1550 {
1551 user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
1552 user->lastCashAdd = newCash - oldCash;
1553 }
1554 //-----------------------------------------------------------------------------
1555 void CHG_IPS_NOTIFIER::Notify(const USER_IPS & from, const USER_IPS & to)
1556 {
1557     printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.GetIpStr().c_str(), to.GetIpStr().c_str());
1558     if (user->connected)
1559         user->Disconnect(false, "Change IP");
1560     if (!user->authorizedBy.empty() && user->IsInetable())
1561         user->Connect(false);
1562 }
1563 //-----------------------------------------------------------------------------