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