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