]> git.stg.codes - stg.git/blob - projects/stargazer/plugins/store/files/file_store.cpp
Fix tariff and user subscription in SMUX
[stg.git] / projects / stargazer / plugins / store / files / file_store.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  *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
19  */
20
21 /*
22  $Revision: 1.67 $
23  $Date: 2010/10/07 19:53:11 $
24  $Author: faust $
25  */
26
27 #ifndef _GNU_SOURCE
28 #define _GNU_SOURCE
29 #endif
30
31 #include <pwd.h>
32 #include <grp.h>
33 #include <sys/stat.h>
34 #include <unistd.h>
35 #include <sys/time.h>
36 #include <fcntl.h>
37 #include <dirent.h>
38
39 #include <cstdio>
40 #include <ctime>
41 #include <cerrno>
42 #include <cstring>
43 #include <sstream>
44 #include <algorithm>
45
46 #include "stg/common.h"
47 #include "stg/user_ips.h"
48 #include "stg/user_conf.h"
49 #include "stg/user_stat.h"
50 #include "stg/const.h"
51 #include "stg/blowfish.h"
52 #include "stg/logger.h"
53 #include "stg/locker.h"
54 #include "stg/plugin_creator.h"
55 #include "file_store.h"
56
57 #define DELETED_USERS_DIR   "deleted_users"
58
59 #define adm_enc_passwd "cjeifY8m3"
60
61 using namespace std;
62
63 int GetFileList(vector<string> * fileList, const string & directory, mode_t mode, const string & ext);
64
65 const int pt_mega = 1024 * 1024;
66 //-----------------------------------------------------------------------------
67 //-----------------------------------------------------------------------------
68 //-----------------------------------------------------------------------------
69 PLUGIN_CREATOR<FILES_STORE> fsc;
70 //-----------------------------------------------------------------------------
71 //-----------------------------------------------------------------------------
72 //-----------------------------------------------------------------------------
73 STORE * GetStore()
74 {
75 return fsc.GetPlugin();
76 }
77 //-----------------------------------------------------------------------------
78 FILES_STORE_SETTINGS::FILES_STORE_SETTINGS()
79     : settings(NULL),
80       removeBak(true),
81       readBak(true)
82 {
83 }
84 //-----------------------------------------------------------------------------
85 FILES_STORE_SETTINGS::~FILES_STORE_SETTINGS()
86 {
87 }
88 //-----------------------------------------------------------------------------
89 int FILES_STORE_SETTINGS::ParseOwner(const vector<PARAM_VALUE> & moduleParams, const string & owner, uid_t * uid)
90 {
91 PARAM_VALUE pv;
92 pv.param = owner;
93 vector<PARAM_VALUE>::const_iterator pvi;
94 pvi = find(moduleParams.begin(), moduleParams.end(), pv);
95 if (pvi == moduleParams.end())
96     {
97     errorStr = "Parameter \'" + owner + "\' not found.";
98     printfd(__FILE__, "%s\n", errorStr.c_str());
99     return -1;
100     }
101 if (User2UID(pvi->value[0].c_str(), uid) < 0)
102     {
103     errorStr = "Parameter \'" + owner + "\': Unknown user \'" + pvi->value[0] + "\'";
104     printfd(__FILE__, "%s\n", errorStr.c_str());
105     return -1;
106     }
107 return 0;
108 }
109 //-----------------------------------------------------------------------------
110 int FILES_STORE_SETTINGS::ParseGroup(const vector<PARAM_VALUE> & moduleParams, const string & group, gid_t * gid)
111 {
112 PARAM_VALUE pv;
113 pv.param = group;
114 vector<PARAM_VALUE>::const_iterator pvi;
115 pvi = find(moduleParams.begin(), moduleParams.end(), pv);
116 if (pvi == moduleParams.end())
117     {
118     errorStr = "Parameter \'" + group + "\' not found.";
119     printfd(__FILE__, "%s\n", errorStr.c_str());
120     return -1;
121     }
122 if (Group2GID(pvi->value[0].c_str(), gid) < 0)
123     {
124     errorStr = "Parameter \'" + group + "\': Unknown group \'" + pvi->value[0] + "\'";
125     printfd(__FILE__, "%s\n", errorStr.c_str());
126     return -1;
127     }
128 return 0;
129 }
130 //-----------------------------------------------------------------------------
131 int FILES_STORE_SETTINGS::ParseYesNo(const string & value, bool * val)
132 {
133 if (0 == strcasecmp(value.c_str(), "yes"))
134     {
135     *val = true;
136     return 0;
137     }
138 if (0 == strcasecmp(value.c_str(), "no"))
139     {
140     *val = false;
141     return 0;
142     }
143
144 errorStr = "Incorrect value \'" + value + "\'.";
145 return -1;
146 }
147 //-----------------------------------------------------------------------------
148 int FILES_STORE_SETTINGS::ParseMode(const vector<PARAM_VALUE> & moduleParams, const string & modeStr, mode_t * mode)
149 {
150 PARAM_VALUE pv;
151 pv.param = modeStr;
152 vector<PARAM_VALUE>::const_iterator pvi;
153 pvi = find(moduleParams.begin(), moduleParams.end(), pv);
154 if (pvi == moduleParams.end())
155     {
156     errorStr = "Parameter \'" + modeStr + "\' not found.";
157     printfd(__FILE__, "%s\n", errorStr.c_str());
158     return -1;
159     }
160 if (Str2Mode(pvi->value[0].c_str(), mode) < 0)
161     {
162     errorStr = "Parameter \'" + modeStr + "\': Incorrect mode \'" + pvi->value[0] + "\'";
163     printfd(__FILE__, "%s\n", errorStr.c_str());
164     return -1;
165     }
166 return 0;
167 }
168 //-----------------------------------------------------------------------------
169 int FILES_STORE_SETTINGS::ParseSettings(const MODULE_SETTINGS & s)
170 {
171 if (ParseOwner(s.moduleParams, "StatOwner", &statUID) < 0)
172     return -1;
173 if (ParseGroup(s.moduleParams, "StatGroup", &statGID) < 0)
174     return -1;
175 if (ParseMode(s.moduleParams, "StatMode", &statMode) < 0)
176     return -1;
177
178 if (ParseOwner(s.moduleParams, "ConfOwner", &confUID) < 0)
179     return -1;
180 if (ParseGroup(s.moduleParams, "ConfGroup", &confGID) < 0)
181     return -1;
182 if (ParseMode(s.moduleParams, "ConfMode", &confMode) < 0)
183     return -1;
184
185 if (ParseOwner(s.moduleParams, "UserLogOwner", &userLogUID) < 0)
186     return -1;
187 if (ParseGroup(s.moduleParams, "UserLogGroup", &userLogGID) < 0)
188     return -1;
189 if (ParseMode(s.moduleParams, "UserLogMode", &userLogMode) < 0)
190     return -1;
191
192 vector<PARAM_VALUE>::const_iterator pvi;
193 PARAM_VALUE pv;
194 pv.param = "RemoveBak";
195 pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
196 if (pvi == s.moduleParams.end())
197     {
198     removeBak = true;
199     }
200 else
201     {
202     if (ParseYesNo(pvi->value[0], &removeBak))
203         {
204         printfd(__FILE__, "Cannot parse parameter 'RemoveBak'\n");
205         return -1;
206         }
207     }
208
209 pv.param = "ReadBak";
210 pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
211 if (pvi == s.moduleParams.end())
212     {
213     readBak = false;
214     }
215 else
216     {
217     if (ParseYesNo(pvi->value[0], &readBak))
218         {
219         printfd(__FILE__, "Cannot parse parameter 'ReadBak'\n");
220         return -1;
221         }
222     }
223
224 pv.param = "WorkDir";
225 pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
226 if (pvi == s.moduleParams.end())
227     {
228     errorStr = "Parameter \'WorkDir\' not found.";
229     printfd(__FILE__, "Parameter 'WorkDir' not found\n");
230     return -1;
231     }
232
233 workDir = pvi->value[0];
234 if (workDir.size() && workDir[workDir.size() - 1] == '/')
235     {
236     workDir.resize(workDir.size() - 1);
237     }
238 usersDir = workDir + "/users/";
239 tariffsDir = workDir + "/tariffs/";
240 adminsDir = workDir + "/admins/";
241
242 return 0;
243 }
244 //-----------------------------------------------------------------------------
245 const string & FILES_STORE_SETTINGS::GetStrError() const
246 {
247 return errorStr;
248 }
249 //-----------------------------------------------------------------------------
250 int FILES_STORE_SETTINGS::User2UID(const char * user, uid_t * uid)
251 {
252 struct passwd * pw;
253 pw = getpwnam(user);
254 if (!pw)
255     {
256     errorStr = string("User \'") + string(user) + string("\' not found in system.");
257     printfd(__FILE__, "%s\n", errorStr.c_str());
258     return -1;
259     }
260
261 *uid = pw->pw_uid;
262 return 0;
263 }
264 //-----------------------------------------------------------------------------
265 int FILES_STORE_SETTINGS::Group2GID(const char * gr, gid_t * gid)
266 {
267 struct group * grp;
268 grp = getgrnam(gr);
269 if (!grp)
270     {
271     errorStr = string("Group \'") + string(gr) + string("\' not found in system.");
272     printfd(__FILE__, "%s\n", errorStr.c_str());
273     return -1;
274     }
275
276 *gid = grp->gr_gid;
277 return 0;
278 }
279 //-----------------------------------------------------------------------------
280 int FILES_STORE_SETTINGS::Str2Mode(const char * str, mode_t * mode)
281 {
282 char a;
283 char b;
284 char c;
285 if (strlen(str) > 3)
286     {
287     errorStr = string("Error parsing mode \'") + str + string("\'");
288     printfd(__FILE__, "%s\n", errorStr.c_str());
289     return -1;
290     }
291
292 for (int i = 0; i < 3; i++)
293     if (str[i] > '7' || str[i] < '0')
294         {
295         errorStr = string("Error parsing mode \'") + str + string("\'");
296         printfd(__FILE__, "%s\n", errorStr.c_str());
297         return -1;
298         }
299
300 a = str[0] - '0';
301 b = str[1] - '0';
302 c = str[2] - '0';
303
304 *mode = ((mode_t)c) + ((mode_t)b << 3) + ((mode_t)a << 6);
305
306 return 0;
307 }
308 //-----------------------------------------------------------------------------
309 string FILES_STORE_SETTINGS::GetWorkDir() const
310 {
311 return workDir;
312 }
313 //-----------------------------------------------------------------------------
314 string FILES_STORE_SETTINGS::GetUsersDir() const
315 {
316 return usersDir;
317 }
318 //-----------------------------------------------------------------------------
319 string FILES_STORE_SETTINGS::GetAdminsDir() const
320 {
321 return adminsDir;
322 }
323 //-----------------------------------------------------------------------------
324 string FILES_STORE_SETTINGS::GetTariffsDir() const
325 {
326 return tariffsDir;
327 }
328 //-----------------------------------------------------------------------------
329 mode_t FILES_STORE_SETTINGS::GetStatMode() const
330 {
331 return statMode;
332 }
333 //-----------------------------------------------------------------------------
334 mode_t FILES_STORE_SETTINGS::GetStatModeDir() const
335 {
336 mode_t mode = statMode;
337 if (statMode & S_IRUSR) mode |= S_IXUSR;
338 if (statMode & S_IRGRP) mode |= S_IXGRP;
339 if (statMode & S_IROTH) mode |= S_IXOTH;
340 return mode;
341 }
342 //-----------------------------------------------------------------------------
343 uid_t  FILES_STORE_SETTINGS::GetStatUID() const
344 {
345 return statUID;
346 }
347 //-----------------------------------------------------------------------------
348 gid_t  FILES_STORE_SETTINGS::GetStatGID() const
349 {
350 return statGID;
351 }
352 //-----------------------------------------------------------------------------
353 mode_t FILES_STORE_SETTINGS::GetConfMode() const
354 {
355 return confMode;
356 }
357 //-----------------------------------------------------------------------------
358 mode_t FILES_STORE_SETTINGS::GetConfModeDir() const
359 {
360 mode_t mode = confMode;
361 if (confMode & S_IRUSR) mode |= S_IXUSR;
362 if (confMode & S_IRGRP) mode |= S_IXGRP;
363 if (confMode & S_IROTH) mode |= S_IXOTH;
364 return mode;
365 }
366 //-----------------------------------------------------------------------------
367 uid_t  FILES_STORE_SETTINGS::GetConfUID() const
368 {
369 return confUID;
370 }
371 //-----------------------------------------------------------------------------
372 gid_t  FILES_STORE_SETTINGS::GetConfGID() const
373 {
374 return confGID;
375 }
376 //-----------------------------------------------------------------------------
377 mode_t FILES_STORE_SETTINGS::GetLogMode() const
378 {
379 return userLogMode;
380 }
381 //-----------------------------------------------------------------------------
382 uid_t  FILES_STORE_SETTINGS::GetLogUID() const
383 {
384 return userLogUID;
385 }
386 //-----------------------------------------------------------------------------
387 gid_t FILES_STORE_SETTINGS::GetLogGID() const
388 {
389 return userLogGID;
390 }
391 //-----------------------------------------------------------------------------
392 bool FILES_STORE_SETTINGS::GetRemoveBak() const
393 {
394 return removeBak;
395 }
396 //-----------------------------------------------------------------------------
397 bool FILES_STORE_SETTINGS::GetReadBak() const
398 {
399 return readBak;
400 }
401 //-----------------------------------------------------------------------------
402 //-----------------------------------------------------------------------------
403 //-----------------------------------------------------------------------------
404 FILES_STORE::FILES_STORE()
405 {
406 version = "file_store v.1.04";
407
408 pthread_mutexattr_t attr;
409 pthread_mutexattr_init(&attr);
410 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
411 pthread_mutex_init(&mutex, &attr);
412 };
413 //-----------------------------------------------------------------------------
414 FILES_STORE::~FILES_STORE()
415 {
416
417 };
418 //-----------------------------------------------------------------------------
419 void FILES_STORE::SetSettings(const MODULE_SETTINGS & s)
420 {
421 settings = s;
422 }
423 //-----------------------------------------------------------------------------
424 int FILES_STORE::ParseSettings()
425 {
426 int ret = storeSettings.ParseSettings(settings);
427 if (ret)
428     {
429     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
430     errorStr = storeSettings.GetStrError();
431     }
432 return ret;
433 }
434 //-----------------------------------------------------------------------------
435 const string & FILES_STORE::GetStrError() const
436 {
437 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
438 return errorStr;
439 }
440 //-----------------------------------------------------------------------------
441 const string & FILES_STORE::GetVersion() const
442 {
443 return version;
444 }
445 //-----------------------------------------------------------------------------
446 int FILES_STORE::GetUsersList(vector<string> * userList) const
447 {
448 vector<string> files;
449
450 if (GetFileList(&files, storeSettings.GetUsersDir(), S_IFDIR, ""))
451     {
452     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
453     errorStr = "Failed to open '" + storeSettings.GetUsersDir() + "': " + string(strerror(errno));
454     return -1;
455     }
456
457 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
458
459 userList->swap(files);
460
461 return 0;
462 }
463 //-----------------------------------------------------------------------------
464 int FILES_STORE::GetAdminsList(vector<string> * adminList) const
465 {
466 vector<string> files;
467
468 if (GetFileList(&files, storeSettings.GetAdminsDir(), S_IFREG, ".adm"))
469     {
470     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
471     errorStr = "Failed to open '" + storeSettings.GetAdminsDir() + "': " + string(strerror(errno));
472     return -1;
473     }
474
475 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
476
477 adminList->swap(files);
478
479 return 0;
480 }
481 //-----------------------------------------------------------------------------
482 int FILES_STORE::GetTariffsList(vector<string> * tariffList) const
483 {
484 vector<string> files;
485
486 if (GetFileList(&files, storeSettings.GetTariffsDir(), S_IFREG, ".tf"))
487     {
488     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
489     errorStr = "Failed to open '" + storeSettings.GetTariffsDir() + "': " + string(strerror(errno));
490     return -1;
491     }
492
493 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
494
495 tariffList->swap(files);
496
497 return 0;
498 }
499 //-----------------------------------------------------------------------------
500 int FILES_STORE::RemoveDir(const char * path) const
501 {
502 DIR * d = opendir(path);
503
504 if (!d)
505     {
506     errorStr = "failed to open dir. Message: '";
507     errorStr += strerror(errno);
508     errorStr += "'";
509     printfd(__FILE__, "FILE_STORE::RemoveDir() - Failed to open dir '%s': '%s'\n", path, strerror(errno));
510     return -1;
511     }
512
513 dirent * entry;
514 while ((entry = readdir(d)))
515     {
516     if (!(strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..")))
517         continue;
518
519     string str = path;
520     str += "/" + string(entry->d_name);
521
522     struct stat st;
523     if (stat(str.c_str(), &st))
524         continue;
525
526     if ((st.st_mode & S_IFREG))
527         {
528         if (unlink(str.c_str()))
529             {
530             STG_LOCKER lock(&mutex, __FILE__, __LINE__);
531             errorStr = "unlink failed. Message: '";
532             errorStr += strerror(errno);
533             errorStr += "'";
534             printfd(__FILE__, "FILES_STORE::RemoveDir() - unlink failed. Message: '%s'\n", strerror(errno));
535             closedir(d);
536             return -1;
537             }
538         }
539
540     if (!(st.st_mode & S_IFDIR))
541         {
542         if (RemoveDir(str.c_str()))
543             {
544             closedir(d);
545             return -1;
546             }
547
548         }
549     }
550
551 closedir(d);
552
553 if (rmdir(path))
554     {
555     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
556     errorStr = "rmdir failed. Message: '";
557     errorStr += strerror(errno);
558     errorStr += "'";
559     printfd(__FILE__, "FILES_STORE::RemoveDir() - rmdir failed. Message: '%s'\n", strerror(errno));
560     return -1;
561     }
562
563 return 0;
564 }
565 //-----------------------------------------------------------------------------
566 int FILES_STORE::AddUser(const string & login) const
567 {
568 string fileName;
569
570 strprintf(&fileName, "%s%s", storeSettings.GetUsersDir().c_str(), login.c_str());
571
572 if (mkdir(fileName.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == -1)
573     {
574     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
575     errorStr = string("mkdir failed. Message: '") + strerror(errno) + "'";
576     printfd(__FILE__, "FILES_STORE::AddUser - mkdir failed. Message: '%s'\n", strerror(errno));
577     return -1;
578     }
579
580 strprintf(&fileName, "%s%s/conf", storeSettings.GetUsersDir().c_str(), login.c_str());
581 if (Touch(fileName))
582     {
583     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
584     errorStr = "Cannot create file \"" + fileName + "\'";
585     printfd(__FILE__, "FILES_STORE::AddUser - fopen failed. Message: '%s'\n", strerror(errno));
586     return -1;
587     }
588 /*f = fopen(fileName.c_str(), "wt");
589 if (f)
590     {
591     if (fprintf(f, "\n") < 0)
592         {
593         STG_LOCKER lock(&mutex, __FILE__, __LINE__);
594         errorStr = "fprintf failed. Message: '";
595         errorStr += strerror(errno);
596         errorStr += "'";
597         printfd(__FILE__, "FILES_STORE::AddUser - fprintf failed. Message: '%s'\n", strerror(errno));
598         return -1;
599         }
600     fclose(f);
601     }
602 else
603     {
604     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
605     errorStr = "Cannot create file \"" + fileName + "\'";
606     printfd(__FILE__, "FILES_STORE::AddUser - fopen failed. Message: '%s'\n", strerror(errno));
607     return -1;
608     }*/
609
610 strprintf(&fileName, "%s%s/stat", storeSettings.GetUsersDir().c_str(), login.c_str());
611 if (Touch(fileName))
612     {
613     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
614     errorStr = "Cannot create file \"" + fileName + "\'";
615     printfd(__FILE__, "FILES_STORE::AddUser - fopen failed. Message: '%s'\n", strerror(errno));
616     return -1;
617     }
618 /*f = fopen(fileName.c_str(), "wt");
619 if (f)
620     {
621     if (fprintf(f, "\n") < 0)
622         {
623         STG_LOCKER lock(&mutex, __FILE__, __LINE__);
624         errorStr = "fprintf failed. Message: '";
625         errorStr += strerror(errno);
626         errorStr += "'";
627         printfd(__FILE__, "FILES_STORE::AddUser - fprintf failed. Message: '%s'\n", strerror(errno));
628         return -1;
629         }
630     fclose(f);
631     }
632 else
633     {
634     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
635     errorStr = "Cannot create file \"" + fileName + "\'";
636     printfd(__FILE__, "FILES_STORE::AddUser - fopen failed. Message: '%s'\n", strerror(errno));
637     return -1;
638     }*/
639 return 0;
640 }
641 //-----------------------------------------------------------------------------
642 int FILES_STORE::DelUser(const string & login) const
643 {
644 string dirName;
645 string dirName1;
646
647 strprintf(&dirName, "%s/"DELETED_USERS_DIR, storeSettings.GetWorkDir().c_str());
648 if (access(dirName.c_str(), F_OK) != 0)
649     {
650     if (mkdir(dirName.c_str(), 0700) != 0)
651         {
652         STG_LOCKER lock(&mutex, __FILE__, __LINE__);
653         errorStr = "Directory '" + dirName + "' cannot be created.";
654         printfd(__FILE__, "FILES_STORE::DelUser - mkdir failed. Message: '%s'\n", strerror(errno));
655         return -1;
656         }
657     }
658
659 if (access(dirName.c_str(), F_OK) == 0)
660     {
661     strprintf(&dirName, "%s/"DELETED_USERS_DIR"/%s.%lu", storeSettings.GetWorkDir().c_str(), login.c_str(), time(NULL));
662     strprintf(&dirName1, "%s/%s", storeSettings.GetUsersDir().c_str(), login.c_str());
663     if (rename(dirName1.c_str(), dirName.c_str()))
664         {
665         STG_LOCKER lock(&mutex, __FILE__, __LINE__);
666         errorStr = "Error moving dir from " + dirName1 + " to " + dirName;
667         printfd(__FILE__, "FILES_STORE::DelUser - rename failed. Message: '%s'\n", strerror(errno));
668         return -1;
669         }
670     }
671 else
672     {
673     strprintf(&dirName, "%s/%s", storeSettings.GetUsersDir().c_str(), login.c_str());
674     if (RemoveDir(dirName.c_str()))
675         {
676         return -1;
677         }
678     }
679 return 0;
680 }
681 //-----------------------------------------------------------------------------
682 int FILES_STORE::RestoreUserConf(USER_CONF * conf, const string & login) const
683 {
684 string fileName;
685 fileName = storeSettings.GetUsersDir() + "/" + login + "/conf";
686 if (RestoreUserConf(conf, login, fileName))
687     {
688     if (!storeSettings.GetReadBak())
689         {
690         return -1;
691         }
692     return RestoreUserConf(conf, login, fileName + ".bak");
693     }
694 return 0;
695 }
696 //-----------------------------------------------------------------------------
697 int FILES_STORE::RestoreUserConf(USER_CONF * conf, const string & login, const string & fileName) const
698 {
699 CONFIGFILE cf(fileName);
700 int e = cf.Error();
701 string str;
702
703 if (e)
704     {
705     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
706     errorStr = "User \'" + login + "\' data not read.";
707     printfd(__FILE__, "FILES_STORE::RestoreUserConf - conf read failed for user '%s'\n", login.c_str());
708     return -1;
709     }
710
711 if (cf.ReadString("Password", &conf->password, "") < 0)
712     {
713     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
714     errorStr = "User \'" + login + "\' data not read. Parameter Password.";
715     printfd(__FILE__, "FILES_STORE::RestoreUserConf - password read failed for user '%s'\n", login.c_str());
716     return -1;
717     }
718 if (conf->password.empty())
719     {
720     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
721     errorStr = "User \'" + login + "\' password is blank.";
722     printfd(__FILE__, "FILES_STORE::RestoreUserConf - password is blank for user '%s'\n", login.c_str());
723     return -1;
724     }
725
726 if (cf.ReadString("tariff", &conf->tariffName, "") < 0)
727     {
728     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
729     errorStr = "User \'" + login + "\' data not read. Parameter Tariff.";
730     printfd(__FILE__, "FILES_STORE::RestoreUserConf - tariff read failed for user '%s'\n", login.c_str());
731     return -1;
732     }
733 if (conf->tariffName.empty())
734     {
735     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
736     errorStr = "User \'" + login + "\' tariff is blank.";
737     printfd(__FILE__, "FILES_STORE::RestoreUserConf - tariff is blank for user '%s'\n", login.c_str());
738     return -1;
739     }
740
741 string ipStr;
742 cf.ReadString("IP", &ipStr, "?");
743 USER_IPS i;
744 try
745     {
746     i = StrToIPS(ipStr);
747     }
748 catch (const string & s)
749     {
750     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
751     errorStr = "User \'" + login + "\' data not read. Parameter IP address. " + s;
752     printfd(__FILE__, "FILES_STORE::RestoreUserConf - ip read failed for user '%s'\n", login.c_str());
753     return -1;
754     }
755 conf->ips = i;
756
757 if (cf.ReadInt("alwaysOnline", &conf->alwaysOnline, 0) != 0)
758     {
759     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
760     errorStr = "User \'" + login + "\' data not read. Parameter AlwaysOnline.";
761     printfd(__FILE__, "FILES_STORE::RestoreUserConf - alwaysonline read failed for user '%s'\n", login.c_str());
762     return -1;
763     }
764
765 if (cf.ReadInt("down", &conf->disabled, 0) != 0)
766     {
767     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
768     errorStr = "User \'" + login + "\' data not read. Parameter Down.";
769     printfd(__FILE__, "FILES_STORE::RestoreUserConf - down read failed for user '%s'\n", login.c_str());
770     return -1;
771     }
772
773 if (cf.ReadInt("passive", &conf->passive, 0) != 0)
774     {
775     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
776     errorStr = "User \'" + login + "\' data not read. Parameter Passive.";
777     printfd(__FILE__, "FILES_STORE::RestoreUserConf - passive read failed for user '%s'\n", login.c_str());
778     return -1;
779     }
780
781 cf.ReadInt("DisabledDetailStat", &conf->disabledDetailStat, 0);
782 cf.ReadTime("CreditExpire", &conf->creditExpire, 0);
783 cf.ReadString("TariffChange", &conf->nextTariff, "");
784 cf.ReadString("Group", &conf->group, "");
785 cf.ReadString("RealName", &conf->realName, "");
786 cf.ReadString("Address", &conf->address, "");
787 cf.ReadString("Phone", &conf->phone, "");
788 cf.ReadString("Note", &conf->note, "");
789 cf.ReadString("email", &conf->email, "");
790
791 char userdataName[12];
792 for (int i = 0; i < USERDATA_NUM; i++)
793     {
794     snprintf(userdataName, 12, "Userdata%d", i);
795     cf.ReadString(userdataName, &conf->userdata[i], "");
796     }
797
798 if (cf.ReadDouble("Credit", &conf->credit, 0) != 0)
799     {
800     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
801     errorStr = "User \'" + login + "\' data not read. Parameter Credit.";
802     printfd(__FILE__, "FILES_STORE::RestoreUserConf - credit read failed for user '%s'\n", login.c_str());
803     return -1;
804     }
805
806 return 0;
807 }
808 //-----------------------------------------------------------------------------
809 int FILES_STORE::RestoreUserStat(USER_STAT * stat, const string & login) const
810 {
811 string fileName;
812 fileName = storeSettings.GetUsersDir() + "/" + login + "/stat";
813
814 if (RestoreUserStat(stat, login, fileName))
815     {
816     if (!storeSettings.GetReadBak())
817         {
818         return -1;
819         }
820     return RestoreUserStat(stat, login, fileName + ".bak");
821     }
822 return 0;
823 }
824 //-----------------------------------------------------------------------------
825 int FILES_STORE::RestoreUserStat(USER_STAT * stat, const string & login, const string & fileName) const
826 {
827 CONFIGFILE cf(fileName);
828
829 int e = cf.Error();
830
831 if (e)
832     {
833     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
834     errorStr = "User \'" + login + "\' stat not read. Cannot open file " + fileName + ".";
835     printfd(__FILE__, "FILES_STORE::RestoreUserStat - stat read failed for user '%s'\n", login.c_str());
836     return -1;
837     }
838
839 char s[22];
840
841 for (int i = 0; i < DIR_NUM; i++)
842     {
843     uint64_t traff;
844     snprintf(s, 22, "D%d", i);
845     if (cf.ReadULongLongInt(s, &traff, 0) != 0)
846         {
847         STG_LOCKER lock(&mutex, __FILE__, __LINE__);
848         errorStr = "User \'" + login + "\' stat not read. Parameter " + string(s);
849         printfd(__FILE__, "FILES_STORE::RestoreUserStat - download stat read failed for user '%s'\n", login.c_str());
850         return -1;
851         }
852     stat->down[i] = traff;
853
854     snprintf(s, 22, "U%d", i);
855     if (cf.ReadULongLongInt(s, &traff, 0) != 0)
856         {
857         STG_LOCKER lock(&mutex, __FILE__, __LINE__);
858         errorStr =   "User \'" + login + "\' stat not read. Parameter " + string(s);
859         printfd(__FILE__, "FILES_STORE::RestoreUserStat - upload stat read failed for user '%s'\n", login.c_str());
860         return -1;
861         }
862     stat->up[i] = traff;
863     }
864
865 if (cf.ReadDouble("Cash", &stat->cash, 0) != 0)
866     {
867     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
868     errorStr =   "User \'" + login + "\' stat not read. Parameter Cash";
869     printfd(__FILE__, "FILES_STORE::RestoreUserStat - cash read failed for user '%s'\n", login.c_str());
870     return -1;
871     }
872
873 if (cf.ReadDouble("FreeMb", &stat->freeMb, 0) != 0)
874     {
875     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
876     errorStr =   "User \'" + login + "\' stat not read. Parameter FreeMb";
877     printfd(__FILE__, "FILES_STORE::RestoreUserStat - freemb read failed for user '%s'\n", login.c_str());
878     return -1;
879     }
880
881 if (cf.ReadTime("LastCashAddTime", &stat->lastCashAddTime, 0) != 0)
882     {
883     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
884     errorStr =   "User \'" + login + "\' stat not read. Parameter LastCashAddTime";
885     printfd(__FILE__, "FILES_STORE::RestoreUserStat - lastcashaddtime read failed for user '%s'\n", login.c_str());
886     return -1;
887     }
888
889 if (cf.ReadTime("PassiveTime", &stat->passiveTime, 0) != 0)
890     {
891     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
892     errorStr =   "User \'" + login + "\' stat not read. Parameter PassiveTime";
893     printfd(__FILE__, "FILES_STORE::RestoreUserStat - passivetime read failed for user '%s'\n", login.c_str());
894     return -1;
895     }
896
897 if (cf.ReadDouble("LastCashAdd", &stat->lastCashAdd, 0) != 0)
898     {
899     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
900     errorStr =   "User \'" + login + "\' stat not read. Parameter LastCashAdd";
901     printfd(__FILE__, "FILES_STORE::RestoreUserStat - lastcashadd read failed for user '%s'\n", login.c_str());
902     return -1;
903     }
904
905 if (cf.ReadTime("LastActivityTime", &stat->lastActivityTime, 0) != 0)
906     {
907     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
908     errorStr =   "User \'" + login + "\' stat not read. Parameter LastActivityTime";
909     printfd(__FILE__, "FILES_STORE::RestoreUserStat - lastactivitytime read failed for user '%s'\n", login.c_str());
910     return -1;
911     }
912
913 return 0;
914 }
915 //-----------------------------------------------------------------------------
916 int FILES_STORE::SaveUserConf(const USER_CONF & conf, const string & login) const
917 {
918 string fileName;
919 fileName = storeSettings.GetUsersDir() + "/" + login + "/conf";
920
921 CONFIGFILE cfstat(fileName, true);
922
923 int e = cfstat.Error();
924
925 if (e)
926     {
927     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
928     errorStr = string("User \'") + login + "\' conf not written\n";
929     printfd(__FILE__, "FILES_STORE::SaveUserConf - conf write failed for user '%s'\n", login.c_str());
930     return -1;
931     }
932
933 e = chmod(fileName.c_str(), storeSettings.GetConfMode());
934 e += chown(fileName.c_str(), storeSettings.GetConfUID(), storeSettings.GetConfGID());
935
936 if (e)
937     {
938     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
939     printfd(__FILE__, "FILES_STORE::SaveUserConf - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
940     }
941
942 cfstat.WriteString("Password",     conf.password);
943 cfstat.WriteInt   ("Passive",      conf.passive);
944 cfstat.WriteInt   ("Down",         conf.disabled);
945 cfstat.WriteInt("DisabledDetailStat", conf.disabledDetailStat);
946 cfstat.WriteInt   ("AlwaysOnline", conf.alwaysOnline);
947 cfstat.WriteString("Tariff",       conf.tariffName);
948 cfstat.WriteString("Address",      conf.address);
949 cfstat.WriteString("Phone",        conf.phone);
950 cfstat.WriteString("Email",        conf.email);
951 cfstat.WriteString("Note",         conf.note);
952 cfstat.WriteString("RealName",     conf.realName);
953 cfstat.WriteString("Group",        conf.group);
954 cfstat.WriteDouble("Credit",       conf.credit);
955 cfstat.WriteString("TariffChange", conf.nextTariff);
956
957 char userdataName[12];
958 for (int i = 0; i < USERDATA_NUM; i++)
959     {
960     snprintf(userdataName, 12, "Userdata%d", i);
961     cfstat.WriteString(userdataName, conf.userdata[i]);
962     }
963 cfstat.WriteInt("CreditExpire",    conf.creditExpire);
964
965 stringstream ipStr;
966 ipStr << conf.ips;
967 cfstat.WriteString("IP", ipStr.str());
968
969 return 0;
970 }
971 //-----------------------------------------------------------------------------
972 int FILES_STORE::SaveUserStat(const USER_STAT & stat, const string & login) const
973 {
974 char s[22];
975 string fileName;
976 fileName = storeSettings.GetUsersDir() + "/" + login + "/stat";
977
978     {
979     CONFIGFILE cfstat(fileName, true);
980     int e = cfstat.Error();
981
982     if (e)
983         {
984         STG_LOCKER lock(&mutex, __FILE__, __LINE__);
985         errorStr = string("User \'") + login + "\' stat not written\n";
986         printfd(__FILE__, "FILES_STORE::SaveUserStat - stat write failed for user '%s'\n", login.c_str());
987         return -1;
988         }
989
990     for (int i = 0; i < DIR_NUM; i++)
991         {
992         snprintf(s, 22, "D%d", i);
993         cfstat.WriteInt(s, stat.down[i]);
994         snprintf(s, 22, "U%d", i);
995         cfstat.WriteInt(s, stat.up[i]);
996         }
997
998     cfstat.WriteDouble("Cash", stat.cash);
999     cfstat.WriteDouble("FreeMb", stat.freeMb);
1000     cfstat.WriteDouble("LastCashAdd", stat.lastCashAdd);
1001     cfstat.WriteInt("LastCashAddTime", stat.lastCashAddTime);
1002     cfstat.WriteInt("PassiveTime", stat.passiveTime);
1003     cfstat.WriteInt("LastActivityTime", stat.lastActivityTime);
1004     }
1005
1006 int e = chmod(fileName.c_str(), storeSettings.GetStatMode());
1007 e += chown(fileName.c_str(), storeSettings.GetStatUID(), storeSettings.GetStatGID());
1008
1009 if (e)
1010     {
1011     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1012     printfd(__FILE__, "FILES_STORE::SaveUserStat - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
1013     }
1014
1015 return 0;
1016 }
1017 //-----------------------------------------------------------------------------
1018 int FILES_STORE::WriteLogString(const string & str, const string & login) const
1019 {
1020 FILE * f;
1021 time_t tm = time(NULL);
1022 string fileName;
1023 fileName = storeSettings.GetUsersDir() + "/" + login + "/log";
1024 f = fopen(fileName.c_str(), "at");
1025
1026 if (f)
1027     {
1028     fprintf(f, "%s", LogDate(tm));
1029     fprintf(f, " -- ");
1030     fprintf(f, "%s", str.c_str());
1031     fprintf(f, "\n");
1032     fclose(f);
1033     }
1034 else
1035     {
1036     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1037     errorStr = "Cannot open \'" + fileName + "\'";
1038     printfd(__FILE__, "FILES_STORE::WriteLogString - log write failed for user '%s'\n", login.c_str());
1039     return -1;
1040     }
1041
1042 int e = chmod(fileName.c_str(), storeSettings.GetLogMode());
1043 e += chown(fileName.c_str(), storeSettings.GetLogUID(), storeSettings.GetLogGID());
1044
1045 if (e)
1046     {
1047     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1048     printfd(__FILE__, "FILES_STORE::WriteLogString - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
1049     }
1050
1051 return 0;
1052 }
1053 //-----------------------------------------------------------------------------
1054 int FILES_STORE::WriteLog2String(const string & str, const string & login) const
1055 {
1056 FILE * f;
1057 time_t tm = time(NULL);
1058 string fileName;
1059 fileName = storeSettings.GetUsersDir() + "/" + login + "/log2";
1060 f = fopen(fileName.c_str(), "at");
1061
1062 if (f)
1063     {
1064     fprintf(f, "%s", LogDate(tm));
1065     fprintf(f, " -- ");
1066     fprintf(f, "%s", str.c_str());
1067     fprintf(f, "\n");
1068     fclose(f);
1069     }
1070 else
1071     {
1072     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1073     errorStr = "Cannot open \'" + fileName + "\'";
1074     printfd(__FILE__, "FILES_STORE::WriteLogString - log write failed for user '%s'\n", login.c_str());
1075     return -1;
1076     }
1077
1078 int e = chmod(fileName.c_str(), storeSettings.GetLogMode());
1079 e += chown(fileName.c_str(), storeSettings.GetLogUID(), storeSettings.GetLogGID());
1080
1081 if (e)
1082     {
1083     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1084     printfd(__FILE__, "FILES_STORE::WriteLogString - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
1085     }
1086
1087 return 0;
1088 }
1089 //-----------------------------------------------------------------------------
1090 int FILES_STORE::WriteUserChgLog(const string & login,
1091                                  const string & admLogin,
1092                                  uint32_t       admIP,
1093                                  const string & paramName,
1094                                  const string & oldValue,
1095                                  const string & newValue,
1096                                  const string & message) const
1097 {
1098 string userLogMsg = "Admin \'" + admLogin + "\', " + inet_ntostring(admIP) + ": \'"
1099     + paramName + "\' parameter changed from \'" + oldValue +
1100     "\' to \'" + newValue + "\'. " + message;
1101
1102 return WriteLogString(userLogMsg, login);
1103 }
1104 //-----------------------------------------------------------------------------
1105 int FILES_STORE::WriteUserConnect(const string & login, uint32_t ip) const
1106 {
1107 string logStr = "Connect, " + inet_ntostring(ip);
1108 if (WriteLogString(logStr, login))
1109     return -1;
1110 return WriteLog2String(logStr, login);
1111 }
1112 //-----------------------------------------------------------------------------
1113 int FILES_STORE::WriteUserDisconnect(const string & login,
1114                                      const DIR_TRAFF & up,
1115                                      const DIR_TRAFF & down,
1116                                      const DIR_TRAFF & sessionUp,
1117                                      const DIR_TRAFF & sessionDown,
1118                                      double cash,
1119                                      double freeMb,
1120                                      const std::string & reason) const
1121 {
1122 stringstream logStr;
1123 logStr << "Disconnect, "
1124        << " session upload: \'"
1125        << sessionUp
1126        << "\' session download: \'"
1127        << sessionDown
1128        << "\' month upload: \'"
1129        << up
1130        << "\' month download: \'"
1131        << down
1132        << "\' cash: \'"
1133        << cash
1134        << "\'";
1135
1136 if (WriteLogString(logStr.str(), login))
1137     return -1;
1138
1139 logStr << " freeMb: \'"
1140        << freeMb
1141        << "\'"
1142        << " reason: \'"
1143        << reason
1144        << "\'";
1145
1146 return WriteLog2String(logStr.str(), login);
1147 }
1148 //-----------------------------------------------------------------------------
1149 int FILES_STORE::SaveMonthStat(const USER_STAT & stat, int month, int year, const string & login) const
1150 {
1151 // Classic stats
1152 string stat1;
1153 strprintf(&stat1,"%s/%s/stat.%d.%02d",
1154         storeSettings.GetUsersDir().c_str(), login.c_str(), year + 1900, month + 1);
1155
1156 CONFIGFILE s(stat1, true);
1157
1158 if (s.Error())
1159     {
1160     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1161     errorStr = "Cannot create file '" + stat1 + "'";
1162     printfd(__FILE__, "FILES_STORE::SaveMonthStat - month stat write failed for user '%s'\n", login.c_str());
1163     return -1;
1164     }
1165
1166 // New stats
1167 string stat2;
1168 strprintf(&stat2,"%s/%s/stat2.%d.%02d",
1169         storeSettings.GetUsersDir().c_str(), login.c_str(), year + 1900, month + 1);
1170
1171 CONFIGFILE s2(stat2, true);
1172
1173 if (s2.Error())
1174     {
1175     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1176     errorStr = "Cannot create file '" + stat2 + "'";
1177     printfd(__FILE__, "FILES_STORE::SaveMonthStat - month stat write failed for user '%s'\n", login.c_str());
1178     return -1;
1179     }
1180
1181 for (size_t i = 0; i < DIR_NUM; i++)
1182     {
1183     char dirName[3];
1184     snprintf(dirName, 3, "U%llu", (unsigned long long)i);
1185     s.WriteInt(dirName, stat.up[i]); // Classic
1186     s2.WriteInt(dirName, stat.up[i]); // New
1187     snprintf(dirName, 3, "D%llu", (unsigned long long)i);
1188     s.WriteInt(dirName, stat.down[i]); // Classic
1189     s2.WriteInt(dirName, stat.down[i]); // New
1190     }
1191
1192 // Classic
1193 s.WriteDouble("cash", stat.cash);
1194
1195 // New
1196 s2.WriteDouble("Cash", stat.cash);
1197 s2.WriteDouble("FreeMb", stat.freeMb);
1198 s2.WriteDouble("LastCashAdd", stat.lastCashAdd);
1199 s2.WriteInt("LastCashAddTime", stat.lastCashAddTime);
1200 s2.WriteInt("PassiveTime", stat.passiveTime);
1201 s2.WriteInt("LastActivityTime", stat.lastActivityTime);
1202
1203 return 0;
1204 }
1205 //-----------------------------------------------------------------------------*/
1206 int FILES_STORE::AddAdmin(const string & login) const
1207 {
1208 string fileName;
1209 strprintf(&fileName, "%s/%s.adm", storeSettings.GetAdminsDir().c_str(), login.c_str());
1210
1211 if (Touch(fileName))
1212     {
1213     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1214     errorStr = "Cannot create file " + fileName;
1215     printfd(__FILE__, "FILES_STORE::AddAdmin - failed to add admin '%s'\n", login.c_str());
1216     return -1;
1217     }
1218
1219 return 0;
1220 }
1221 //-----------------------------------------------------------------------------*/
1222 int FILES_STORE::DelAdmin(const string & login) const
1223 {
1224 string fileName;
1225 strprintf(&fileName, "%s/%s.adm", storeSettings.GetAdminsDir().c_str(), login.c_str());
1226 if (unlink(fileName.c_str()))
1227     {
1228     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1229     errorStr = "unlink failed. Message: '";
1230     errorStr += strerror(errno);
1231     errorStr += "'";
1232     printfd(__FILE__, "FILES_STORE::DelAdmin - unlink failed. Message: '%s'\n", strerror(errno));
1233     }
1234 return 0;
1235 }
1236 //-----------------------------------------------------------------------------*/
1237 int FILES_STORE::SaveAdmin(const ADMIN_CONF & ac) const
1238 {
1239 char passwordE[2 * ADM_PASSWD_LEN + 2];
1240 char pass[ADM_PASSWD_LEN + 1];
1241 char adminPass[ADM_PASSWD_LEN + 1];
1242
1243 string fileName;
1244
1245 strprintf(&fileName, "%s/%s.adm", storeSettings.GetAdminsDir().c_str(), ac.login.c_str());
1246
1247     {
1248     CONFIGFILE cf(fileName, true);
1249
1250     int e = cf.Error();
1251
1252     if (e)
1253         {
1254         STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1255         errorStr = "Cannot write admin " + ac.login + ". " + fileName;
1256         printfd(__FILE__, "FILES_STORE::SaveAdmin - failed to save admin '%s'\n", ac.login.c_str());
1257         return -1;
1258         }
1259
1260     memset(pass, 0, sizeof(pass));
1261     memset(adminPass, 0, sizeof(adminPass));
1262
1263     BLOWFISH_CTX ctx;
1264     EnDecodeInit(adm_enc_passwd, strlen(adm_enc_passwd), &ctx);
1265
1266     strncpy(adminPass, ac.password.c_str(), ADM_PASSWD_LEN);
1267     adminPass[ADM_PASSWD_LEN - 1] = 0;
1268
1269     for (int i = 0; i < ADM_PASSWD_LEN/8; i++)
1270         {
1271         EncodeString(pass + 8*i, adminPass + 8*i, &ctx);
1272         }
1273
1274     pass[ADM_PASSWD_LEN - 1] = 0;
1275     Encode12(passwordE, pass, ADM_PASSWD_LEN);
1276
1277     cf.WriteString("password", passwordE);
1278     cf.WriteInt("ChgConf",     ac.priv.userConf);
1279     cf.WriteInt("ChgPassword", ac.priv.userPasswd);
1280     cf.WriteInt("ChgStat",     ac.priv.userStat);
1281     cf.WriteInt("ChgCash",     ac.priv.userCash);
1282     cf.WriteInt("UsrAddDel",   ac.priv.userAddDel);
1283     cf.WriteInt("ChgTariff",   ac.priv.tariffChg);
1284     cf.WriteInt("ChgAdmin",    ac.priv.adminChg);
1285     cf.WriteInt("ChgService",  ac.priv.serviceChg);
1286     cf.WriteInt("ChgCorp",     ac.priv.corpChg);
1287     }
1288
1289 return 0;
1290 }
1291 //-----------------------------------------------------------------------------
1292 int FILES_STORE::RestoreAdmin(ADMIN_CONF * ac, const string & login) const
1293 {
1294 string fileName;
1295 strprintf(&fileName, "%s/%s.adm", storeSettings.GetAdminsDir().c_str(), login.c_str());
1296 CONFIGFILE cf(fileName);
1297 char pass[ADM_PASSWD_LEN + 1];
1298 char password[ADM_PASSWD_LEN + 1];
1299 char passwordE[2 * ADM_PASSWD_LEN + 2];
1300 BLOWFISH_CTX ctx;
1301
1302 string p;
1303
1304 if (cf.Error())
1305     {
1306     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1307     errorStr = "Cannot open " + fileName;
1308     printfd(__FILE__, "FILES_STORE::RestoreAdmin - failed to restore admin '%s'\n", ac->login.c_str());
1309     return -1;
1310     }
1311
1312 int a;
1313
1314 if (cf.ReadString("password", &p, "*"))
1315     {
1316     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1317     errorStr = "Error in parameter password";
1318     printfd(__FILE__, "FILES_STORE::RestoreAdmin - password read failed for admin '%s'\n", ac->login.c_str());
1319     return -1;
1320     }
1321
1322 memset(passwordE, 0, sizeof(passwordE));
1323 strncpy(passwordE, p.c_str(), 2*ADM_PASSWD_LEN);
1324
1325 memset(pass, 0, sizeof(pass));
1326
1327 if (passwordE[0] != 0)
1328     {
1329     Decode21(pass, passwordE);
1330     EnDecodeInit(adm_enc_passwd, strlen(adm_enc_passwd), &ctx);
1331
1332     for (int i = 0; i < ADM_PASSWD_LEN/8; i++)
1333         {
1334         DecodeString(password + 8*i, pass + 8*i, &ctx);
1335         }
1336     }
1337 else
1338     {
1339     password[0] = 0;
1340     }
1341
1342 ac->password = password;
1343
1344 if (cf.ReadInt("ChgConf", &a, 0) == 0)
1345     ac->priv.userConf = a;
1346 else
1347     {
1348     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1349     errorStr = "Error in parameter ChgConf";
1350     printfd(__FILE__, "FILES_STORE::RestoreAdmin - chgconf read failed for admin '%s'\n", ac->login.c_str());
1351     return -1;
1352     }
1353
1354 if (cf.ReadInt("ChgPassword", &a, 0) == 0)
1355     ac->priv.userPasswd = a;
1356 else
1357     {
1358     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1359     errorStr = "Error in parameter ChgPassword";
1360     printfd(__FILE__, "FILES_STORE::RestoreAdmin - chgpassword read failed for admin '%s'\n", ac->login.c_str());
1361     return -1;
1362     }
1363
1364 if (cf.ReadInt("ChgStat", &a, 0) == 0)
1365     ac->priv.userStat = a;
1366 else
1367     {
1368     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1369     errorStr = "Error in parameter ChgStat";
1370     printfd(__FILE__, "FILES_STORE::RestoreAdmin - chgstat read failed for admin '%s'\n", ac->login.c_str());
1371     return -1;
1372     }
1373
1374 if (cf.ReadInt("ChgCash", &a, 0) == 0)
1375     ac->priv.userCash = a;
1376 else
1377     {
1378     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1379     errorStr = "Error in parameter ChgCash";
1380     printfd(__FILE__, "FILES_STORE::RestoreAdmin - chgcash read failed for admin '%s'\n", ac->login.c_str());
1381     return -1;
1382     }
1383
1384 if (cf.ReadInt("UsrAddDel", &a, 0) == 0)
1385     ac->priv.userAddDel = a;
1386 else
1387     {
1388     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1389     errorStr = "Error in parameter UsrAddDel";
1390     printfd(__FILE__, "FILES_STORE::RestoreAdmin - usradddel read failed for admin '%s'\n", ac->login.c_str());
1391     return -1;
1392     }
1393
1394 if (cf.ReadInt("ChgAdmin", &a, 0) == 0)
1395     ac->priv.adminChg = a;
1396 else
1397     {
1398     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1399     errorStr = "Error in parameter ChgAdmin";
1400     printfd(__FILE__, "FILES_STORE::RestoreAdmin - chgadmin read failed for admin '%s'\n", ac->login.c_str());
1401     return -1;
1402     }
1403
1404 if (cf.ReadInt("ChgTariff", &a, 0) == 0)
1405     ac->priv.tariffChg = a;
1406 else
1407     {
1408     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1409     errorStr = "Error in parameter ChgTariff";
1410     printfd(__FILE__, "FILES_STORE::RestoreAdmin - chgtariff read failed for admin '%s'\n", ac->login.c_str());
1411     return -1;
1412     }
1413
1414 if (cf.ReadInt("ChgService", &a, 0) == 0)
1415     ac->priv.serviceChg = a;
1416 else
1417     ac->priv.serviceChg = 0;
1418
1419 if (cf.ReadInt("ChgCorp", &a, 0) == 0)
1420     ac->priv.corpChg = a;
1421 else
1422     ac->priv.corpChg = 0;
1423
1424 return 0;
1425 }
1426 //-----------------------------------------------------------------------------
1427 int FILES_STORE::AddTariff(const string & name) const
1428 {
1429 string fileName;
1430 strprintf(&fileName, "%s/%s.tf", storeSettings.GetTariffsDir().c_str(), name.c_str());
1431 if (Touch(fileName))
1432     {
1433     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1434     errorStr = "Cannot create file " + fileName;
1435     printfd(__FILE__, "FILES_STORE::AddTariff - failed to add tariff '%s'\n", name.c_str());
1436     return -1;
1437     }
1438 return 0;
1439 }
1440 //-----------------------------------------------------------------------------
1441 int FILES_STORE::DelTariff(const string & name) const
1442 {
1443 string fileName;
1444 strprintf(&fileName, "%s/%s.tf", storeSettings.GetTariffsDir().c_str(), name.c_str());
1445 if (unlink(fileName.c_str()))
1446     {
1447     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1448     errorStr = "unlink failed. Message: '";
1449     errorStr += strerror(errno);
1450     errorStr += "'";
1451     printfd(__FILE__, "FILES_STORE::DelTariff - unlink failed. Message: '%s'\n", strerror(errno));
1452     }
1453 return 0;
1454 }
1455 //-----------------------------------------------------------------------------
1456 int FILES_STORE::RestoreTariff(TARIFF_DATA * td, const string & tariffName) const
1457 {
1458 string fileName = storeSettings.GetTariffsDir() + "/" + tariffName + ".tf";
1459 CONFIGFILE conf(fileName);
1460 string str;
1461 td->tariffConf.name = tariffName;
1462
1463 if (conf.Error() != 0)
1464     {
1465     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1466     errorStr = "Cannot read file " + fileName;
1467     printfd(__FILE__, "FILES_STORE::RestoreTariff - failed to read tariff '%s'\n", tariffName.c_str());
1468     return -1;
1469     }
1470
1471 string param;
1472 for (int i = 0; i<DIR_NUM; i++)
1473     {
1474     strprintf(&param, "Time%d", i);
1475     if (conf.ReadString(param, &str, "00:00-00:00") < 0)
1476         {
1477         STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1478         errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
1479         printfd(__FILE__, "FILES_STORE::RestoreTariff - time%d read failed for tariff '%s'\n", i, tariffName.c_str());
1480         return -1;
1481         }
1482
1483     ParseTariffTimeStr(str.c_str(),
1484                        td->dirPrice[i].hDay,
1485                        td->dirPrice[i].mDay,
1486                        td->dirPrice[i].hNight,
1487                        td->dirPrice[i].mNight);
1488
1489     strprintf(&param, "PriceDayA%d", i);
1490     if (conf.ReadDouble(param, &td->dirPrice[i].priceDayA, 0.0) < 0)
1491         {
1492         STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1493         errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
1494         printfd(__FILE__, "FILES_STORE::RestoreTariff - pricedaya read failed for tariff '%s'\n", tariffName.c_str());
1495         return -1;
1496         }
1497     td->dirPrice[i].priceDayA /= (1024*1024);
1498
1499     strprintf(&param, "PriceDayB%d", i);
1500     if (conf.ReadDouble(param, &td->dirPrice[i].priceDayB, 0.0) < 0)
1501         {
1502         STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1503         errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
1504         printfd(__FILE__, "FILES_STORE::RestoreTariff - pricedayb read failed for tariff '%s'\n", tariffName.c_str());
1505         return -1;
1506         }
1507     td->dirPrice[i].priceDayB /= (1024*1024);
1508
1509     strprintf(&param, "PriceNightA%d", i);
1510     if (conf.ReadDouble(param, &td->dirPrice[i].priceNightA, 0.0) < 0)
1511         {
1512         STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1513         errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
1514         printfd(__FILE__, "FILES_STORE::RestoreTariff - pricenighta read failed for tariff '%s'\n", tariffName.c_str());
1515         return -1;
1516         }
1517     td->dirPrice[i].priceNightA /= (1024*1024);
1518
1519     strprintf(&param, "PriceNightB%d", i);
1520     if (conf.ReadDouble(param, &td->dirPrice[i].priceNightB, 0.0) < 0)
1521         {
1522         STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1523         errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
1524         printfd(__FILE__, "FILES_STORE::RestoreTariff - pricenightb read failed for tariff '%s'\n", tariffName.c_str());
1525         return -1;
1526         }
1527     td->dirPrice[i].priceNightB /= (1024*1024);
1528
1529     strprintf(&param, "Threshold%d", i);
1530     if (conf.ReadInt(param, &td->dirPrice[i].threshold, 0) < 0)
1531         {
1532         STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1533         errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
1534         printfd(__FILE__, "FILES_STORE::RestoreTariff - threshold read failed for tariff '%s'\n", tariffName.c_str());
1535         return -1;
1536         }
1537
1538     strprintf(&param, "SinglePrice%d", i);
1539     if (conf.ReadInt(param, &td->dirPrice[i].singlePrice, 0) < 0)
1540         {
1541         STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1542         errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
1543         printfd(__FILE__, "FILES_STORE::RestoreTariff - singleprice read failed for tariff '%s'\n", tariffName.c_str());
1544         return -1;
1545         }
1546
1547     strprintf(&param, "NoDiscount%d", i);
1548     if (conf.ReadInt(param, &td->dirPrice[i].noDiscount, 0) < 0)
1549         {
1550         STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1551         errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
1552         printfd(__FILE__, "FILES_STORE::RestoreTariff - nodiscount read failed for tariff '%s'\n", tariffName.c_str());
1553         return -1;
1554         }
1555     }
1556
1557 if (conf.ReadDouble("Fee", &td->tariffConf.fee, 0) < 0)
1558     {
1559     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1560     errorStr = "Cannot read tariff " + tariffName + ". Parameter Fee";
1561     printfd(__FILE__, "FILES_STORE::RestoreTariff - fee read failed for tariff '%s'\n", tariffName.c_str());
1562     return -1;
1563     }
1564
1565 if (conf.ReadDouble("Free", &td->tariffConf.free, 0) < 0)
1566     {
1567     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1568     errorStr = "Cannot read tariff " + tariffName + ". Parameter Free";
1569     printfd(__FILE__, "FILES_STORE::RestoreTariff - free read failed for tariff '%s'\n", tariffName.c_str());
1570     return -1;
1571     }
1572
1573 if (conf.ReadDouble("PassiveCost", &td->tariffConf.passiveCost, 0) < 0)
1574     {
1575     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1576     errorStr = "Cannot read tariff " + tariffName + ". Parameter PassiveCost";
1577     printfd(__FILE__, "FILES_STORE::RestoreTariff - passivecost read failed for tariff '%s'\n", tariffName.c_str());
1578     return -1;
1579     }
1580
1581 if (conf.ReadString("TraffType", &str, "") < 0)
1582     {
1583     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1584     errorStr = "Cannot read tariff " + tariffName + ". Parameter TraffType";
1585     printfd(__FILE__, "FILES_STORE::RestoreTariff - trafftype read failed for tariff '%s'\n", tariffName.c_str());
1586     return -1;
1587     }
1588
1589 if (!strcasecmp(str.c_str(), "up"))
1590     td->tariffConf.traffType = TRAFF_UP;
1591 else
1592     if (!strcasecmp(str.c_str(), "down"))
1593         td->tariffConf.traffType = TRAFF_DOWN;
1594     else
1595         if (!strcasecmp(str.c_str(), "up+down"))
1596             td->tariffConf.traffType = TRAFF_UP_DOWN;
1597         else
1598             if (!strcasecmp(str.c_str(), "max"))
1599                 td->tariffConf.traffType = TRAFF_MAX;
1600             else
1601                 {
1602                 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1603                 errorStr = "Cannot read tariff " + tariffName + ". Parameter TraffType incorrect";
1604                 printfd(__FILE__, "FILES_STORE::RestoreTariff - invalid trafftype for tariff '%s'\n", tariffName.c_str());
1605                 return -1;
1606                 }
1607 return 0;
1608 }
1609 //-----------------------------------------------------------------------------
1610 int FILES_STORE::SaveTariff(const TARIFF_DATA & td, const string & tariffName) const
1611 {
1612 string fileName = storeSettings.GetTariffsDir() + "/" + tariffName + ".tf";
1613
1614     {
1615     CONFIGFILE cf(fileName, true);
1616
1617     int e = cf.Error();
1618
1619     if (e)
1620         {
1621         STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1622         errorStr = "Error writing tariff " + tariffName;
1623         printfd(__FILE__, "FILES_STORE::RestoreTariff - failed to save tariff '%s'\n", tariffName.c_str());
1624         return e;
1625         }
1626
1627     string param;
1628     for (int i = 0; i < DIR_NUM; i++)
1629         {
1630         strprintf(&param, "PriceDayA%d", i);
1631         cf.WriteDouble(param, td.dirPrice[i].priceDayA * pt_mega);
1632
1633         strprintf(&param, "PriceDayB%d", i);
1634         cf.WriteDouble(param, td.dirPrice[i].priceDayB * pt_mega);
1635
1636         strprintf(&param, "PriceNightA%d", i);
1637         cf.WriteDouble(param, td.dirPrice[i].priceNightA * pt_mega);
1638
1639         strprintf(&param, "PriceNightB%d", i);
1640         cf.WriteDouble(param, td.dirPrice[i].priceNightB * pt_mega);
1641
1642         strprintf(&param, "Threshold%d", i);
1643         cf.WriteInt(param, td.dirPrice[i].threshold);
1644
1645         string s;
1646         strprintf(&param, "Time%d", i);
1647
1648         strprintf(&s, "%0d:%0d-%0d:%0d",
1649                 td.dirPrice[i].hDay,
1650                 td.dirPrice[i].mDay,
1651                 td.dirPrice[i].hNight,
1652                 td.dirPrice[i].mNight);
1653
1654         cf.WriteString(param, s);
1655
1656         strprintf(&param, "NoDiscount%d", i);
1657         cf.WriteInt(param, td.dirPrice[i].noDiscount);
1658
1659         strprintf(&param, "SinglePrice%d", i);
1660         cf.WriteInt(param, td.dirPrice[i].singlePrice);
1661         }
1662
1663     cf.WriteDouble("PassiveCost", td.tariffConf.passiveCost);
1664     cf.WriteDouble("Fee", td.tariffConf.fee);
1665     cf.WriteDouble("Free", td.tariffConf.free);
1666
1667     switch (td.tariffConf.traffType)
1668         {
1669         case TRAFF_UP:
1670             cf.WriteString("TraffType", "up");
1671             break;
1672         case TRAFF_DOWN:
1673             cf.WriteString("TraffType", "down");
1674             break;
1675         case TRAFF_UP_DOWN:
1676             cf.WriteString("TraffType", "up+down");
1677             break;
1678         case TRAFF_MAX:
1679             cf.WriteString("TraffType", "max");
1680             break;
1681         }
1682     }
1683
1684 return 0;
1685 }
1686 //-----------------------------------------------------------------------------
1687 int FILES_STORE::WriteDetailedStat(const map<IP_DIR_PAIR, STAT_NODE> & statTree,
1688                                    time_t lastStat,
1689                                    const string & login) const
1690 {
1691 char fn[FN_STR_LEN];
1692 char dn[FN_STR_LEN];
1693 FILE * statFile;
1694 time_t t;
1695 tm * lt;
1696
1697 t = time(NULL);
1698
1699 snprintf(dn, FN_STR_LEN, "%s/%s/detail_stat", storeSettings.GetUsersDir().c_str(), login.c_str());
1700 if (access(dn, F_OK) != 0)
1701     {
1702     if (mkdir(dn, 0700) != 0)
1703         {
1704         STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1705         errorStr = "Directory \'" + string(dn) + "\' cannot be created.";
1706         printfd(__FILE__, "FILES_STORE::WriteDetailStat - mkdir failed. Message: '%s'\n", strerror(errno));
1707         return -1;
1708         }
1709     }
1710
1711 int e = chown(dn, storeSettings.GetStatUID(), storeSettings.GetStatGID());
1712 e += chmod(dn, storeSettings.GetStatModeDir());
1713
1714 if (e)
1715     {
1716     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1717     printfd(__FILE__, "FILES_STORE::WriteDetailStat - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
1718     }
1719
1720 lt = localtime(&t);
1721
1722 if (lt->tm_hour == 0 && lt->tm_min <= 5)
1723     {
1724     t -= 3600 * 24;
1725     lt = localtime(&t);
1726     }
1727
1728 snprintf(dn, FN_STR_LEN, "%s/%s/detail_stat/%d",
1729          storeSettings.GetUsersDir().c_str(),
1730          login.c_str(),
1731          lt->tm_year+1900);
1732
1733 if (access(dn, F_OK) != 0)
1734     {
1735     if (mkdir(dn, 0700) != 0)
1736         {
1737         STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1738         errorStr = "Directory \'" + string(dn) + "\' cannot be created.";
1739         printfd(__FILE__, "FILES_STORE::WriteDetailStat - mkdir failed. Message: '%s'\n", strerror(errno));
1740         return -1;
1741         }
1742     }
1743
1744 e = chown(dn, storeSettings.GetStatUID(), storeSettings.GetStatGID());
1745 e += chmod(dn, storeSettings.GetStatModeDir());
1746
1747 if (e)
1748     {
1749     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1750     printfd(__FILE__, "FILES_STORE::WriteDetailStat - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
1751     }
1752
1753 snprintf(dn, FN_STR_LEN, "%s/%s/detail_stat/%d/%s%d", 
1754          storeSettings.GetUsersDir().c_str(),
1755          login.c_str(),
1756          lt->tm_year+1900,
1757          lt->tm_mon+1 < 10 ? "0" : "",
1758          lt->tm_mon+1);
1759 if (access(dn, F_OK) != 0)
1760     {
1761     if (mkdir(dn, 0700) != 0)
1762         {
1763         STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1764         errorStr = "Directory \'" + string(dn) + "\' cannot be created.";
1765         printfd(__FILE__, "FILES_STORE::WriteDetailStat - mkdir failed. Message: '%s'\n", strerror(errno));
1766         return -1;
1767         }
1768     }
1769
1770 e = chown(dn, storeSettings.GetStatUID(), storeSettings.GetStatGID());
1771 e += chmod(dn, storeSettings.GetStatModeDir());
1772
1773 if (e)
1774     {
1775     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1776     printfd(__FILE__, "FILES_STORE::WriteDetailStat - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
1777     }
1778
1779 snprintf(fn, FN_STR_LEN, "%s/%s%d", dn, lt->tm_mday < 10 ? "0" : "", lt->tm_mday);
1780
1781 statFile = fopen (fn, "at");
1782
1783 if (!statFile)
1784     {
1785     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1786     errorStr = "File \'" + string(fn) + "\' cannot be written.";
1787     printfd(__FILE__, "FILES_STORE::WriteDetailStat - fopen failed. Message: '%s'\n", strerror(errno));
1788     return -1;
1789     }
1790
1791 struct tm * lt1;
1792 struct tm * lt2;
1793
1794 lt1 = localtime(&lastStat);
1795
1796 int h1, m1, s1;
1797 int h2, m2, s2;
1798
1799 h1 = lt1->tm_hour;
1800 m1 = lt1->tm_min;
1801 s1 = lt1->tm_sec;
1802
1803 lt2 = localtime(&t);
1804
1805 h2 = lt2->tm_hour;
1806 m2 = lt2->tm_min;
1807 s2 = lt2->tm_sec;
1808
1809 if (fprintf(statFile, "-> %02d.%02d.%02d - %02d.%02d.%02d\n",
1810             h1, m1, s1, h2, m2, s2) < 0)
1811     {
1812     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1813     errorStr = string("fprint failed. Message: '") + strerror(errno) + "'";
1814     printfd(__FILE__, "FILES_STORE::WriteDetailStat - fprintf failed. Message: '%s'\n", strerror(errno));
1815     fclose(statFile);
1816     return -1;
1817     }
1818
1819 map<IP_DIR_PAIR, STAT_NODE>::const_iterator stIter;
1820 stIter = statTree.begin();
1821
1822 while (stIter != statTree.end())
1823     {
1824     string u, d;
1825     x2str(stIter->second.up, u);
1826     x2str(stIter->second.down, d);
1827     #ifdef TRAFF_STAT_WITH_PORTS
1828     if (fprintf(statFile, "%17s:%hu\t%15d\t%15s\t%15s\t%f\n",
1829                 inet_ntostring(stIter->first.ip).c_str(),
1830                 stIter->first.port,
1831                 stIter->first.dir,
1832                 d.c_str(),
1833                 u.c_str(),
1834                 stIter->second.cash) < 0)
1835         {
1836         STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1837         errorStr = "fprint failed. Message: '";
1838         errorStr += strerror(errno);
1839         errorStr += "'";
1840         printfd(__FILE__, "FILES_STORE::WriteDetailStat - fprintf failed. Message: '%s'\n", strerror(errno));
1841         fclose(statFile);
1842         return -1;
1843         }
1844     #else
1845     if (fprintf(statFile, "%17s\t%15d\t%15s\t%15s\t%f\n",
1846                 inet_ntostring(stIter->first.ip).c_str(),
1847                 stIter->first.dir,
1848                 d.c_str(),
1849                 u.c_str(),
1850                 stIter->second.cash) < 0)
1851         {
1852         STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1853         errorStr = string("fprint failed. Message: '");
1854         errorStr += strerror(errno);
1855         errorStr += "'";
1856         printfd(__FILE__, "FILES_STORE::WriteDetailStat - fprintf failed. Message: '%s'\n", strerror(errno));
1857         fclose(statFile);
1858         return -1;
1859         }
1860     #endif
1861
1862     ++stIter;
1863     }
1864
1865 fclose(statFile);
1866
1867 e = chown(fn, storeSettings.GetStatUID(), storeSettings.GetStatGID());
1868 e += chmod(fn, storeSettings.GetStatMode());
1869
1870 if (e)
1871     {
1872     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1873     printfd(__FILE__, "FILES_STORE::WriteDetailStat - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
1874     }
1875
1876 return 0;
1877 }
1878 //-----------------------------------------------------------------------------
1879 int FILES_STORE::AddMessage(STG_MSG * msg, const string & login) const
1880 {
1881 //ðÒÏ×ÅÒÉÔØ ÅÓÔØ ÌÉ ÄÉÒÅËÔÏÒÉÑ ÄÌÑ ÓÏÏÂÝÅÎÉÊ. åÓÌÉ ÎÅÔ - ÓÏÚÄÁÔØ.
1882 //úÁÔÅÍ ÐÏÌÏÖÉÔØ ÓÏÏÂÝÅÎÉÅ Ó ÉÍÅÎÅÍ ÆÁÊÌÁ - ×ÒÅÍÅÎÎOÊ ÍÅÔËÏÊ. úÁÐÉÓÁÔØ ÔÕÄÁ
1883 //ÔÅËÓÔ É ÐÒÉÏÒÉÔÅÔ.
1884
1885 string fn;
1886 string dn;
1887 struct timeval tv;
1888
1889 strprintf(&dn, "%s/%s/messages", storeSettings.GetUsersDir().c_str(), login.c_str());
1890 if (access(dn.c_str(), F_OK) != 0)
1891     {
1892     if (mkdir(dn.c_str(), 0700) != 0)
1893         {
1894         STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1895         errorStr = "Directory \'";
1896         errorStr += dn;
1897         errorStr += "\' cannot be created.";
1898         printfd(__FILE__, "FILES_STORE::AddMessage - mkdir failed. Message: '%s'\n", strerror(errno));
1899         return -1;
1900         }
1901     }
1902
1903 chmod(dn.c_str(), storeSettings.GetConfModeDir());
1904
1905 gettimeofday(&tv, NULL);
1906
1907 msg->header.id = ((long long)tv.tv_sec) * 1000000 + ((long long)tv.tv_usec);
1908 strprintf(&fn, "%s/%lld", dn.c_str(), msg->header.id);
1909
1910 if (Touch(fn))
1911     {
1912     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1913     errorStr = "File \'";
1914     errorStr += fn;
1915     errorStr += "\' cannot be writen.";
1916     printfd(__FILE__, "FILES_STORE::AddMessage - fopen failed. Message: '%s'\n", strerror(errno));
1917     return -1;
1918     }
1919
1920 return EditMessage(*msg, login);
1921 }
1922 //-----------------------------------------------------------------------------
1923 int FILES_STORE::EditMessage(const STG_MSG & msg, const string & login) const
1924 {
1925 //ðÒÏ×ÅÒÉÔØ ÅÓÌÔØ ÌÉ ÄÉÒÅËÔÏÒÉÑ ÄÌÑ ÓÏÏÂÝÅÎÉÊ. åÓÌÉ ÎÅÔ - ÓÏÚÄÁÔØ.
1926 //úÁÔÅÍ ÐÏÌÏÖÉÔØ ÓÏÏÂÝÅÎÉÅ Ó ÉÍÅÎÅÍ ÆÁÊÌÁ - ×ÒÅÍÅÎÎOÊ ÍÅÔËÏÊ. úÁÐÉÓÁÔØ ÔÕÄÁ
1927 //ÔÅËÓÔ É ÐÒÉÏÒÉÔÅÔ.
1928
1929 string fileName;
1930
1931 FILE * msgFile;
1932 strprintf(&fileName, "%s/%s/messages/%lld", storeSettings.GetUsersDir().c_str(), login.c_str(), msg.header.id);
1933
1934 if (access(fileName.c_str(), F_OK) != 0)
1935     {
1936     string idstr;
1937     x2str(msg.header.id, idstr);
1938     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1939     errorStr = "Message for user \'";
1940     errorStr += login + "\' with ID \'";
1941     errorStr += idstr + "\' does not exist.";
1942     printfd(__FILE__, "FILES_STORE::EditMessage - %s\n", errorStr.c_str());
1943     return -1;
1944     }
1945
1946 Touch(fileName + ".new");
1947
1948 msgFile = fopen((fileName + ".new").c_str(), "wt");
1949 if (!msgFile)
1950     {
1951     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1952     errorStr = "File \'" + fileName + "\' cannot be writen.";
1953     printfd(__FILE__, "FILES_STORE::EditMessage - fopen failed. Message: '%s'\n", strerror(errno));
1954     return -1;
1955     }
1956
1957 bool res = true;
1958 res &= (fprintf(msgFile, "%d\n", msg.header.type) >= 0);
1959 res &= (fprintf(msgFile, "%u\n", msg.header.lastSendTime) >= 0);
1960 res &= (fprintf(msgFile, "%u\n", msg.header.creationTime) >= 0);
1961 res &= (fprintf(msgFile, "%u\n", msg.header.showTime) >= 0);
1962 res &= (fprintf(msgFile, "%d\n", msg.header.repeat) >= 0);
1963 res &= (fprintf(msgFile, "%u\n", msg.header.repeatPeriod) >= 0);
1964 res &= (fprintf(msgFile, "%s", msg.text.c_str()) >= 0);
1965
1966 if (!res)
1967     {
1968     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1969     errorStr = string("fprintf failed. Message: '") + strerror(errno) + "'";
1970     printfd(__FILE__, "FILES_STORE::EditMessage - fprintf failed. Message: '%s'\n", strerror(errno));
1971     fclose(msgFile);
1972     return -1;
1973     }
1974
1975 fclose(msgFile);
1976
1977 chmod((fileName + ".new").c_str(), storeSettings.GetConfMode());
1978
1979 if (rename((fileName + ".new").c_str(), fileName.c_str()) < 0)
1980     {
1981     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
1982     errorStr = "Error moving dir from " + fileName + ".new to " + fileName;
1983     printfd(__FILE__, "FILES_STORE::SaveTariff - rename failed. Message: '%s'\n", strerror(errno));
1984     return -1;
1985     }
1986
1987 return 0;
1988 }
1989 //-----------------------------------------------------------------------------
1990 int FILES_STORE::GetMessage(uint64_t id, STG_MSG * msg, const string & login) const
1991 {
1992 string fn;
1993 strprintf(&fn, "%s/%s/messages/%lld", storeSettings.GetUsersDir().c_str(), login.c_str(), id);
1994 msg->header.id = id;
1995 return ReadMessage(fn, &msg->header, &msg->text);
1996 }
1997 //-----------------------------------------------------------------------------
1998 int FILES_STORE::DelMessage(uint64_t id, const string & login) const
1999 {
2000 string fn;
2001 strprintf(&fn, "%s/%s/messages/%lld", storeSettings.GetUsersDir().c_str(), login.c_str(), id);
2002
2003 return unlink(fn.c_str());
2004 }
2005 //-----------------------------------------------------------------------------
2006 int FILES_STORE::GetMessageHdrs(vector<STG_MSG_HDR> * hdrsList, const string & login) const
2007 {
2008 string dn(storeSettings.GetUsersDir() + "/" + login + "/messages/");
2009
2010 //hdrsList->resize(messages.size());
2011
2012 if (access(dn.c_str(), F_OK) != 0)
2013     {
2014     return 0;
2015     }
2016
2017 vector<string> messages;
2018 GetFileList(&messages, dn, S_IFREG, "");
2019
2020 for (unsigned i = 0; i < messages.size(); i++)
2021     {
2022     unsigned long long id = 0;
2023
2024     if (str2x(messages[i].c_str(), id))
2025         {
2026         if (unlink((dn + messages[i]).c_str()))
2027             {
2028             STG_LOCKER lock(&mutex, __FILE__, __LINE__);
2029             errorStr = string("unlink failed. Message: '") + strerror(errno) + "'";
2030             printfd(__FILE__, "FILES_STORE::GetMessageHdrs - unlink failed. Message: '%s'\n", strerror(errno));
2031             return -1;
2032             }
2033         continue;
2034         }
2035
2036     STG_MSG_HDR hdr;
2037     if (ReadMessage(dn + messages[i], &hdr, NULL))
2038         {
2039         return -1;
2040         }
2041
2042     if (hdr.repeat < 0)
2043         {
2044         if (unlink((dn + messages[i]).c_str()))
2045             {
2046             STG_LOCKER lock(&mutex, __FILE__, __LINE__);
2047             errorStr = string("unlink failed. Message: '") + strerror(errno) + "'";
2048             printfd(__FILE__, "FILES_STORE::GetMessageHdrs - unlink failed. Message: '%s'\n", strerror(errno));
2049             return -1;
2050             }
2051         continue;
2052         }
2053
2054     hdr.id = id;
2055     hdrsList->push_back(hdr);
2056     }
2057 return 0;
2058 }
2059 //-----------------------------------------------------------------------------
2060 int FILES_STORE::ReadMessage(const string & fileName,
2061                              STG_MSG_HDR * hdr,
2062                              string * text) const
2063 {
2064 FILE * msgFile;
2065 msgFile = fopen(fileName.c_str(), "rt");
2066 if (!msgFile)
2067     {
2068     STG_LOCKER lock(&mutex, __FILE__, __LINE__);
2069     errorStr = "File \'";
2070     errorStr += fileName;
2071     errorStr += "\' cannot be openned.";
2072     printfd(__FILE__, "FILES_STORE::ReadMessage - fopen failed. Message: '%s'\n", strerror(errno));
2073     return -1;
2074     }
2075 char p[20];
2076 unsigned * d[6];
2077 d[0] = &hdr->type;
2078 d[1] = &hdr->lastSendTime;
2079 d[2] = &hdr->creationTime;
2080 d[3] = &hdr->showTime;
2081 d[4] = (unsigned*)(&hdr->repeat);
2082 d[5] = &hdr->repeatPeriod;
2083
2084 memset(p, 0, sizeof(p));
2085
2086 for (int pos = 0; pos < 6; pos++)
2087     {
2088     if (fgets(p, sizeof(p) - 1, msgFile) == NULL) {
2089         STG_LOCKER lock(&mutex, __FILE__, __LINE__);
2090         errorStr = "Cannot read file \'";
2091         errorStr += fileName;
2092         errorStr += "\'. Missing data.";
2093         printfd(__FILE__, "FILES_STORE::ReadMessage - cannot read file (missing data)\n");
2094         printfd(__FILE__, "FILES_STORE::ReadMessage - position: %d\n", pos);
2095         fclose(msgFile);
2096         return -1;
2097     }
2098
2099     char * ep;
2100     ep = strrchr(p, '\r');
2101     if (ep) *ep = 0;
2102     ep = strrchr(p, '\n');
2103     if (ep) *ep = 0;
2104
2105     if (feof(msgFile))
2106         {
2107         STG_LOCKER lock(&mutex, __FILE__, __LINE__);
2108         errorStr = "Cannot read file \'";
2109         errorStr += fileName;
2110         errorStr += "\'. Missing data.";
2111         printfd(__FILE__, "FILES_STORE::ReadMessage - cannot read file (feof)\n");
2112         printfd(__FILE__, "FILES_STORE::ReadMessage - position: %d\n", pos);
2113         fclose(msgFile);
2114         return -1;
2115         }
2116
2117     if (str2x(p, *(d[pos])))
2118         {
2119         STG_LOCKER lock(&mutex, __FILE__, __LINE__);
2120         errorStr = "Cannot read file \'";
2121         errorStr += fileName;
2122         errorStr += "\'. Incorrect value. \'";
2123         errorStr += p;
2124         errorStr += "\'";
2125         printfd(__FILE__, "FILES_STORE::ReadMessage - incorrect value\n");
2126         fclose(msgFile);
2127         return -1;
2128         }
2129     }
2130
2131 char txt[2048];
2132 memset(txt, 0, sizeof(txt));
2133 if (text)
2134     {
2135     text->erase(text->begin(), text->end());
2136     while (!feof(msgFile))
2137         {
2138         txt[0] = 0;
2139         if (fgets(txt, sizeof(txt) - 1, msgFile) == NULL) {
2140             break;
2141         }
2142
2143         (*text) += txt;
2144         }
2145     }
2146 fclose(msgFile);
2147 return 0;
2148 }
2149 //-----------------------------------------------------------------------------
2150 int FILES_STORE::Touch(const std::string & path) const
2151 {
2152 FILE * f = fopen(path.c_str(), "wb");
2153 if (f)
2154     {
2155     fclose(f);
2156     return 0;
2157     }
2158 return -1;
2159 }
2160 //-----------------------------------------------------------------------------
2161 int GetFileList(vector<string> * fileList, const string & directory, mode_t mode, const string & ext)
2162 {
2163 // æÕÎËÃÉÑ ÐÒÏÓÍÁÔÒÉ×ÁÅÔ ÓÏÄÅÒÖÉÍÏÅ ÄÉÒÅËÔÏÒÉÉ
2164
2165 DIR * d = opendir(directory.c_str());
2166
2167 if (!d)
2168     {
2169     printfd(__FILE__, "GetFileList - Failed to open dir '%s': '%s'\n", directory.c_str(), strerror(errno));
2170     return -1;
2171     }
2172
2173 dirent * entry;
2174 while ((entry = readdir(d)))
2175     {
2176     if (!(strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..")))
2177         continue;
2178
2179     string str = directory + "/" + string(entry->d_name);
2180
2181     struct stat st;
2182     if (stat(str.c_str(), &st))
2183         continue;
2184
2185     if (!(st.st_mode & mode)) // Filter by mode
2186         continue;
2187
2188     if (!ext.empty())
2189         {
2190         // Check extension
2191         size_t d_nameLen = strlen(entry->d_name);
2192         if (d_nameLen <= ext.size())
2193             continue;
2194
2195         if (ext == entry->d_name + (d_nameLen - ext.size()))
2196             {
2197             entry->d_name[d_nameLen - ext.size()] = 0;
2198             fileList->push_back(entry->d_name);
2199             }
2200         }
2201     else
2202         {
2203         fileList->push_back(entry->d_name);
2204         }
2205     }
2206
2207 closedir(d);
2208
2209 return 0;
2210 }
2211 //-----------------------------------------------------------------------------