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