]> git.stg.codes - stg.git/blob - projects/stargazer/plugins/store/files/file_store.cpp
Ticket 37. WriteTime() changed to WriteString() and formatTime() added
[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
1474 if (conf.ReadString("ChangePolicyTimeout", &str, "1970-01-01 00:00:00") < 0)
1475     td->tariffConf.changePolicyTimeout = 0;
1476 else
1477     td->tariffConf.changePolicyTimeout = readTime(str);
1478 return 0;
1479 }
1480 //-----------------------------------------------------------------------------
1481 int FILES_STORE::SaveTariff(const TARIFF_DATA & td, const std::string & tariffName) const
1482 {
1483 std::string fileName = storeSettings.GetTariffsDir() + "/" + tariffName + ".tf";
1484
1485     {
1486     CONFIGFILE cf(fileName, true);
1487
1488     int e = cf.Error();
1489
1490     if (e)
1491         {
1492         STG_LOCKER lock(&mutex);
1493         errorStr = "Error writing tariff " + tariffName;
1494         printfd(__FILE__, "FILES_STORE::RestoreTariff - failed to save tariff '%s'\n", tariffName.c_str());
1495         return e;
1496         }
1497
1498     std::string param;
1499     for (int i = 0; i < DIR_NUM; i++)
1500         {
1501         strprintf(&param, "PriceDayA%d", i);
1502         cf.WriteDouble(param, td.dirPrice[i].priceDayA * pt_mega);
1503
1504         strprintf(&param, "PriceDayB%d", i);
1505         cf.WriteDouble(param, td.dirPrice[i].priceDayB * pt_mega);
1506
1507         strprintf(&param, "PriceNightA%d", i);
1508         cf.WriteDouble(param, td.dirPrice[i].priceNightA * pt_mega);
1509
1510         strprintf(&param, "PriceNightB%d", i);
1511         cf.WriteDouble(param, td.dirPrice[i].priceNightB * pt_mega);
1512
1513         strprintf(&param, "Threshold%d", i);
1514         cf.WriteInt(param, td.dirPrice[i].threshold);
1515
1516         std::string s;
1517         strprintf(&param, "Time%d", i);
1518
1519         strprintf(&s, "%0d:%0d-%0d:%0d",
1520                 td.dirPrice[i].hDay,
1521                 td.dirPrice[i].mDay,
1522                 td.dirPrice[i].hNight,
1523                 td.dirPrice[i].mNight);
1524
1525         cf.WriteString(param, s);
1526
1527         strprintf(&param, "NoDiscount%d", i);
1528         cf.WriteInt(param, td.dirPrice[i].noDiscount);
1529
1530         strprintf(&param, "SinglePrice%d", i);
1531         cf.WriteInt(param, td.dirPrice[i].singlePrice);
1532         }
1533
1534     cf.WriteDouble("PassiveCost", td.tariffConf.passiveCost);
1535     cf.WriteDouble("Fee", td.tariffConf.fee);
1536     cf.WriteDouble("Free", td.tariffConf.free);
1537     cf.WriteString("TraffType", TARIFF::TraffTypeToString(td.tariffConf.traffType));
1538     cf.WriteString("Period", TARIFF::PeriodToString(td.tariffConf.period));
1539     cf.WriteString("ChangePolicy", TARIFF::ChangePolicyToString(td.tariffConf.changePolicy));
1540     cf.WriteString("ChangePolicyTimeout", formatTime(td.tariffConf.changePolicyTimeout));
1541     }
1542
1543 return 0;
1544 }
1545 //-----------------------------------------------------------------------------
1546 int FILES_STORE::WriteDetailedStat(const std::map<IP_DIR_PAIR, STAT_NODE> & statTree,
1547                                    time_t lastStat,
1548                                    const std::string & login) const
1549 {
1550 char fn[FN_STR_LEN];
1551 char dn[FN_STR_LEN];
1552 FILE * statFile;
1553 time_t t;
1554 tm * lt;
1555
1556 t = time(NULL);
1557
1558 snprintf(dn, FN_STR_LEN, "%s/%s/detail_stat", storeSettings.GetUsersDir().c_str(), login.c_str());
1559 if (access(dn, F_OK) != 0)
1560     {
1561     if (mkdir(dn, 0700) != 0)
1562         {
1563         STG_LOCKER lock(&mutex);
1564         errorStr = "Directory \'" + std::string(dn) + "\' cannot be created.";
1565         printfd(__FILE__, "FILES_STORE::WriteDetailStat - mkdir failed. Message: '%s'\n", strerror(errno));
1566         return -1;
1567         }
1568     }
1569
1570 int e = chown(dn, storeSettings.GetStatUID(), storeSettings.GetStatGID());
1571 e += chmod(dn, storeSettings.GetStatModeDir());
1572
1573 if (e)
1574     {
1575     STG_LOCKER lock(&mutex);
1576     printfd(__FILE__, "FILES_STORE::WriteDetailStat - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
1577     }
1578
1579 lt = localtime(&t);
1580
1581 if (lt->tm_hour == 0 && lt->tm_min <= 5)
1582     {
1583     t -= 3600 * 24;
1584     lt = localtime(&t);
1585     }
1586
1587 snprintf(dn, FN_STR_LEN, "%s/%s/detail_stat/%d",
1588          storeSettings.GetUsersDir().c_str(),
1589          login.c_str(),
1590          lt->tm_year+1900);
1591
1592 if (access(dn, F_OK) != 0)
1593     {
1594     if (mkdir(dn, 0700) != 0)
1595         {
1596         STG_LOCKER lock(&mutex);
1597         errorStr = "Directory \'" + std::string(dn) + "\' cannot be created.";
1598         printfd(__FILE__, "FILES_STORE::WriteDetailStat - mkdir failed. Message: '%s'\n", strerror(errno));
1599         return -1;
1600         }
1601     }
1602
1603 e = chown(dn, storeSettings.GetStatUID(), storeSettings.GetStatGID());
1604 e += chmod(dn, storeSettings.GetStatModeDir());
1605
1606 if (e)
1607     {
1608     STG_LOCKER lock(&mutex);
1609     printfd(__FILE__, "FILES_STORE::WriteDetailStat - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
1610     }
1611
1612 snprintf(dn, FN_STR_LEN, "%s/%s/detail_stat/%d/%s%d", 
1613          storeSettings.GetUsersDir().c_str(),
1614          login.c_str(),
1615          lt->tm_year+1900,
1616          lt->tm_mon+1 < 10 ? "0" : "",
1617          lt->tm_mon+1);
1618 if (access(dn, F_OK) != 0)
1619     {
1620     if (mkdir(dn, 0700) != 0)
1621         {
1622         STG_LOCKER lock(&mutex);
1623         errorStr = "Directory \'" + std::string(dn) + "\' cannot be created.";
1624         printfd(__FILE__, "FILES_STORE::WriteDetailStat - mkdir failed. Message: '%s'\n", strerror(errno));
1625         return -1;
1626         }
1627     }
1628
1629 e = chown(dn, storeSettings.GetStatUID(), storeSettings.GetStatGID());
1630 e += chmod(dn, storeSettings.GetStatModeDir());
1631
1632 if (e)
1633     {
1634     STG_LOCKER lock(&mutex);
1635     printfd(__FILE__, "FILES_STORE::WriteDetailStat - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
1636     }
1637
1638 snprintf(fn, FN_STR_LEN, "%s/%s%d", dn, lt->tm_mday < 10 ? "0" : "", lt->tm_mday);
1639
1640 statFile = fopen (fn, "at");
1641
1642 if (!statFile)
1643     {
1644     STG_LOCKER lock(&mutex);
1645     errorStr = "File \'" + std::string(fn) + "\' cannot be written.";
1646     printfd(__FILE__, "FILES_STORE::WriteDetailStat - fopen failed. Message: '%s'\n", strerror(errno));
1647     return -1;
1648     }
1649
1650 struct tm * lt1;
1651 struct tm * lt2;
1652
1653 lt1 = localtime(&lastStat);
1654
1655 int h1, m1, s1;
1656 int h2, m2, s2;
1657
1658 h1 = lt1->tm_hour;
1659 m1 = lt1->tm_min;
1660 s1 = lt1->tm_sec;
1661
1662 lt2 = localtime(&t);
1663
1664 h2 = lt2->tm_hour;
1665 m2 = lt2->tm_min;
1666 s2 = lt2->tm_sec;
1667
1668 if (fprintf(statFile, "-> %02d.%02d.%02d - %02d.%02d.%02d\n",
1669             h1, m1, s1, h2, m2, s2) < 0)
1670     {
1671     STG_LOCKER lock(&mutex);
1672     errorStr = std::string("fprint failed. Message: '") + strerror(errno) + "'";
1673     printfd(__FILE__, "FILES_STORE::WriteDetailStat - fprintf failed. Message: '%s'\n", strerror(errno));
1674     fclose(statFile);
1675     return -1;
1676     }
1677
1678 std::map<IP_DIR_PAIR, STAT_NODE>::const_iterator stIter;
1679 stIter = statTree.begin();
1680
1681 while (stIter != statTree.end())
1682     {
1683     std::string u, d;
1684     x2str(stIter->second.up, u);
1685     x2str(stIter->second.down, d);
1686     #ifdef TRAFF_STAT_WITH_PORTS
1687     if (fprintf(statFile, "%17s:%hu\t%15d\t%15s\t%15s\t%f\n",
1688                 inet_ntostring(stIter->first.ip).c_str(),
1689                 stIter->first.port,
1690                 stIter->first.dir,
1691                 d.c_str(),
1692                 u.c_str(),
1693                 stIter->second.cash) < 0)
1694         {
1695         STG_LOCKER lock(&mutex);
1696         errorStr = "fprint failed. Message: '";
1697         errorStr += strerror(errno);
1698         errorStr += "'";
1699         printfd(__FILE__, "FILES_STORE::WriteDetailStat - fprintf failed. Message: '%s'\n", strerror(errno));
1700         fclose(statFile);
1701         return -1;
1702         }
1703     #else
1704     if (fprintf(statFile, "%17s\t%15d\t%15s\t%15s\t%f\n",
1705                 inet_ntostring(stIter->first.ip).c_str(),
1706                 stIter->first.dir,
1707                 d.c_str(),
1708                 u.c_str(),
1709                 stIter->second.cash) < 0)
1710         {
1711         STG_LOCKER lock(&mutex);
1712         errorStr = std::string("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     #endif
1720
1721     ++stIter;
1722     }
1723
1724 fclose(statFile);
1725
1726 e = chown(fn, storeSettings.GetStatUID(), storeSettings.GetStatGID());
1727 e += chmod(fn, storeSettings.GetStatMode());
1728
1729 if (e)
1730     {
1731     STG_LOCKER lock(&mutex);
1732     printfd(__FILE__, "FILES_STORE::WriteDetailStat - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
1733     }
1734
1735 return 0;
1736 }
1737 //-----------------------------------------------------------------------------
1738 int FILES_STORE::AddMessage(STG_MSG * msg, const std::string & login) const
1739 {
1740 std::string fn;
1741 std::string dn;
1742 struct timeval tv;
1743
1744 strprintf(&dn, "%s/%s/messages", storeSettings.GetUsersDir().c_str(), login.c_str());
1745 if (access(dn.c_str(), F_OK) != 0)
1746     {
1747     if (mkdir(dn.c_str(), 0700) != 0)
1748         {
1749         STG_LOCKER lock(&mutex);
1750         errorStr = "Directory \'";
1751         errorStr += dn;
1752         errorStr += "\' cannot be created.";
1753         printfd(__FILE__, "FILES_STORE::AddMessage - mkdir failed. Message: '%s'\n", strerror(errno));
1754         return -1;
1755         }
1756     }
1757
1758 chmod(dn.c_str(), storeSettings.GetConfModeDir());
1759
1760 gettimeofday(&tv, NULL);
1761
1762 msg->header.id = ((long long)tv.tv_sec) * 1000000 + ((long long)tv.tv_usec);
1763 strprintf(&fn, "%s/%lld", dn.c_str(), msg->header.id);
1764
1765 if (Touch(fn))
1766     {
1767     STG_LOCKER lock(&mutex);
1768     errorStr = "File \'";
1769     errorStr += fn;
1770     errorStr += "\' cannot be writen.";
1771     printfd(__FILE__, "FILES_STORE::AddMessage - fopen failed. Message: '%s'\n", strerror(errno));
1772     return -1;
1773     }
1774
1775 return EditMessage(*msg, login);
1776 }
1777 //-----------------------------------------------------------------------------
1778 int FILES_STORE::EditMessage(const STG_MSG & msg, const std::string & login) const
1779 {
1780 std::string fileName;
1781
1782 FILE * msgFile;
1783 strprintf(&fileName, "%s/%s/messages/%lld", storeSettings.GetUsersDir().c_str(), login.c_str(), msg.header.id);
1784
1785 if (access(fileName.c_str(), F_OK) != 0)
1786     {
1787     std::string idstr;
1788     x2str(msg.header.id, idstr);
1789     STG_LOCKER lock(&mutex);
1790     errorStr = "Message for user \'";
1791     errorStr += login + "\' with ID \'";
1792     errorStr += idstr + "\' does not exist.";
1793     printfd(__FILE__, "FILES_STORE::EditMessage - %s\n", errorStr.c_str());
1794     return -1;
1795     }
1796
1797 Touch(fileName + ".new");
1798
1799 msgFile = fopen((fileName + ".new").c_str(), "wt");
1800 if (!msgFile)
1801     {
1802     STG_LOCKER lock(&mutex);
1803     errorStr = "File \'" + fileName + "\' cannot be writen.";
1804     printfd(__FILE__, "FILES_STORE::EditMessage - fopen failed. Message: '%s'\n", strerror(errno));
1805     return -1;
1806     }
1807
1808 bool res = true;
1809 res &= (fprintf(msgFile, "%u\n", msg.header.type) >= 0);
1810 res &= (fprintf(msgFile, "%u\n", msg.header.lastSendTime) >= 0);
1811 res &= (fprintf(msgFile, "%u\n", msg.header.creationTime) >= 0);
1812 res &= (fprintf(msgFile, "%u\n", msg.header.showTime) >= 0);
1813 res &= (fprintf(msgFile, "%d\n", msg.header.repeat) >= 0);
1814 res &= (fprintf(msgFile, "%u\n", msg.header.repeatPeriod) >= 0);
1815 res &= (fprintf(msgFile, "%s", msg.text.c_str()) >= 0);
1816
1817 if (!res)
1818     {
1819     STG_LOCKER lock(&mutex);
1820     errorStr = std::string("fprintf failed. Message: '") + strerror(errno) + "'";
1821     printfd(__FILE__, "FILES_STORE::EditMessage - fprintf failed. Message: '%s'\n", strerror(errno));
1822     fclose(msgFile);
1823     return -1;
1824     }
1825
1826 fclose(msgFile);
1827
1828 chmod((fileName + ".new").c_str(), storeSettings.GetConfMode());
1829
1830 if (rename((fileName + ".new").c_str(), fileName.c_str()) < 0)
1831     {
1832     STG_LOCKER lock(&mutex);
1833     errorStr = "Error moving dir from " + fileName + ".new to " + fileName;
1834     printfd(__FILE__, "FILES_STORE::EditMessage - rename failed. Message: '%s'\n", strerror(errno));
1835     return -1;
1836     }
1837
1838 return 0;
1839 }
1840 //-----------------------------------------------------------------------------
1841 int FILES_STORE::GetMessage(uint64_t id, STG_MSG * msg, const std::string & login) const
1842 {
1843 std::string fn;
1844 strprintf(&fn, "%s/%s/messages/%lld", storeSettings.GetUsersDir().c_str(), login.c_str(), id);
1845 msg->header.id = id;
1846 return ReadMessage(fn, &msg->header, &msg->text);
1847 }
1848 //-----------------------------------------------------------------------------
1849 int FILES_STORE::DelMessage(uint64_t id, const std::string & login) const
1850 {
1851 std::string fn;
1852 strprintf(&fn, "%s/%s/messages/%lld", storeSettings.GetUsersDir().c_str(), login.c_str(), id);
1853
1854 return unlink(fn.c_str());
1855 }
1856 //-----------------------------------------------------------------------------
1857 int FILES_STORE::GetMessageHdrs(std::vector<STG_MSG_HDR> * hdrsList, const std::string & login) const
1858 {
1859 std::string dn(storeSettings.GetUsersDir() + "/" + login + "/messages/");
1860
1861 if (access(dn.c_str(), F_OK) != 0)
1862     {
1863     return 0;
1864     }
1865
1866 std::vector<std::string> messages;
1867 GetFileList(&messages, dn, S_IFREG, "");
1868
1869 for (unsigned i = 0; i < messages.size(); i++)
1870     {
1871     unsigned long long id = 0;
1872
1873     if (str2x(messages[i].c_str(), id))
1874         {
1875         if (unlink((dn + messages[i]).c_str()))
1876             {
1877             STG_LOCKER lock(&mutex);
1878             errorStr = std::string("unlink failed. Message: '") + strerror(errno) + "'";
1879             printfd(__FILE__, "FILES_STORE::GetMessageHdrs - unlink failed. Message: '%s'\n", strerror(errno));
1880             return -1;
1881             }
1882         continue;
1883         }
1884
1885     STG_MSG_HDR hdr;
1886     if (ReadMessage(dn + messages[i], &hdr, NULL))
1887         {
1888         return -1;
1889         }
1890
1891     if (hdr.repeat < 0)
1892         {
1893         if (unlink((dn + messages[i]).c_str()))
1894             {
1895             STG_LOCKER lock(&mutex);
1896             errorStr = std::string("unlink failed. Message: '") + strerror(errno) + "'";
1897             printfd(__FILE__, "FILES_STORE::GetMessageHdrs - unlink failed. Message: '%s'\n", strerror(errno));
1898             return -1;
1899             }
1900         continue;
1901         }
1902
1903     hdr.id = id;
1904     hdrsList->push_back(hdr);
1905     }
1906 return 0;
1907 }
1908 //-----------------------------------------------------------------------------
1909 int FILES_STORE::ReadMessage(const std::string & fileName,
1910                              STG_MSG_HDR * hdr,
1911                              std::string * text) const
1912 {
1913 FILE * msgFile;
1914 msgFile = fopen(fileName.c_str(), "rt");
1915 if (!msgFile)
1916     {
1917     STG_LOCKER lock(&mutex);
1918     errorStr = "File \'";
1919     errorStr += fileName;
1920     errorStr += "\' cannot be openned.";
1921     printfd(__FILE__, "FILES_STORE::ReadMessage - fopen failed. Message: '%s'\n", strerror(errno));
1922     return -1;
1923     }
1924 char p[20];
1925 unsigned * d[6];
1926 d[0] = &hdr->type;
1927 d[1] = &hdr->lastSendTime;
1928 d[2] = &hdr->creationTime;
1929 d[3] = &hdr->showTime;
1930 d[4] = (unsigned*)(&hdr->repeat);
1931 d[5] = &hdr->repeatPeriod;
1932
1933 memset(p, 0, sizeof(p));
1934
1935 for (int pos = 0; pos < 6; pos++)
1936     {
1937     if (fgets(p, sizeof(p) - 1, msgFile) == NULL) {
1938         STG_LOCKER lock(&mutex);
1939         errorStr = "Cannot read file \'";
1940         errorStr += fileName;
1941         errorStr += "\'. Missing data.";
1942         printfd(__FILE__, "FILES_STORE::ReadMessage - cannot read file (missing data)\n");
1943         printfd(__FILE__, "FILES_STORE::ReadMessage - position: %d\n", pos);
1944         fclose(msgFile);
1945         return -1;
1946     }
1947
1948     char * ep;
1949     ep = strrchr(p, '\r');
1950     if (ep) *ep = 0;
1951     ep = strrchr(p, '\n');
1952     if (ep) *ep = 0;
1953
1954     if (feof(msgFile))
1955         {
1956         STG_LOCKER lock(&mutex);
1957         errorStr = "Cannot read file \'";
1958         errorStr += fileName;
1959         errorStr += "\'. Missing data.";
1960         printfd(__FILE__, "FILES_STORE::ReadMessage - cannot read file (feof)\n");
1961         printfd(__FILE__, "FILES_STORE::ReadMessage - position: %d\n", pos);
1962         fclose(msgFile);
1963         return -1;
1964         }
1965
1966     if (str2x(p, *(d[pos])))
1967         {
1968         STG_LOCKER lock(&mutex);
1969         errorStr = "Cannot read file \'";
1970         errorStr += fileName;
1971         errorStr += "\'. Incorrect value. \'";
1972         errorStr += p;
1973         errorStr += "\'";
1974         printfd(__FILE__, "FILES_STORE::ReadMessage - incorrect value\n");
1975         fclose(msgFile);
1976         return -1;
1977         }
1978     }
1979
1980 char txt[2048];
1981 memset(txt, 0, sizeof(txt));
1982 if (text)
1983     {
1984     text->erase(text->begin(), text->end());
1985     while (!feof(msgFile))
1986         {
1987         txt[0] = 0;
1988         if (fgets(txt, sizeof(txt) - 1, msgFile) == NULL) {
1989             break;
1990         }
1991
1992         (*text) += txt;
1993         }
1994     }
1995 fclose(msgFile);
1996 return 0;
1997 }
1998 //-----------------------------------------------------------------------------
1999 int FILES_STORE::Touch(const std::string & path) const
2000 {
2001 FILE * f = fopen(path.c_str(), "wb");
2002 if (f)
2003     {
2004     fclose(f);
2005     return 0;
2006     }
2007 return -1;
2008 }
2009 //-----------------------------------------------------------------------------
2010 int GetFileList(std::vector<std::string> * fileList, const std::string & directory, mode_t mode, const std::string & ext)
2011 {
2012 DIR * d = opendir(directory.c_str());
2013
2014 if (!d)
2015     {
2016     printfd(__FILE__, "GetFileList - Failed to open dir '%s': '%s'\n", directory.c_str(), strerror(errno));
2017     return -1;
2018     }
2019
2020 dirent * entry;
2021 while ((entry = readdir(d)))
2022     {
2023     if (!(strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..")))
2024         continue;
2025
2026     std::string str = directory + "/" + std::string(entry->d_name);
2027
2028     struct stat st;
2029     if (stat(str.c_str(), &st))
2030         continue;
2031
2032     if (!(st.st_mode & mode)) // Filter by mode
2033         continue;
2034
2035     if (!ext.empty())
2036         {
2037         // Check extension
2038         size_t d_nameLen = strlen(entry->d_name);
2039         if (d_nameLen <= ext.size())
2040             continue;
2041
2042         if (ext == entry->d_name + (d_nameLen - ext.size()))
2043             {
2044             entry->d_name[d_nameLen - ext.size()] = 0;
2045             fileList->push_back(entry->d_name);
2046             }
2047         }
2048     else
2049         {
2050         fileList->push_back(entry->d_name);
2051         }
2052     }
2053
2054 closedir(d);
2055
2056 return 0;
2057 }
2058 //-----------------------------------------------------------------------------