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