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