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