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