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