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