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