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