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