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