]> git.stg.codes - stg.git/blob - projects/stargazer/plugins/store/mysql/mysql_store.cpp
Added note about waiting rscriptd until message queue becomes empty
[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 "mysql_store.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 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 if (mysql_num_rows(res) != 1)
715 {
716     errorStr = "User not found";
717     mysql_close(sock);
718     return -1;
719 }
720
721 row = mysql_fetch_row(res);
722
723 string param;
724
725 conf->password = row[1];
726
727 if (conf->password.empty())
728     {
729     mysql_free_result(res);
730     errorStr = "User \'" + login + "\' password is blank.";
731     mysql_close(sock);
732     return -1;
733     }
734
735 if (GetInt(row[2],&conf->passive, 0) != 0)
736     {
737     mysql_free_result(res);
738     errorStr = "User \'" + login + "\' data not read. Parameter Passive.";
739     mysql_close(sock);
740     return -1;
741     }
742
743 if (GetInt(row[3], &conf->disabled, 0) != 0)
744     {
745     mysql_free_result(res);
746     errorStr = "User \'" + login + "\' data not read. Parameter Down.";
747     mysql_close(sock);
748     return -1;
749     }
750
751 if (GetInt(row[4], &conf->disabledDetailStat, 0) != 0)
752     {
753     mysql_free_result(res);
754     errorStr = "User \'" + login + "\' data not read. Parameter DisabledDetailStat.";
755     mysql_close(sock);
756     return -1;
757     }
758
759 if (GetInt(row[5], &conf->alwaysOnline, 0) != 0)
760     {
761     mysql_free_result(res);
762     errorStr = "User \'" + login + "\' data not read. Parameter AlwaysOnline.";
763     mysql_close(sock);
764     return -1;
765     }
766
767 conf->tariffName = row[6];
768
769 if (conf->tariffName.empty()) 
770     {
771     mysql_free_result(res);
772     errorStr = "User \'" + login + "\' tariff is blank.";
773     mysql_close(sock);
774     return -1;
775     }
776
777 conf->address = row[7];
778 conf->phone = row[8];
779 conf->email = row[9];
780 conf->note = row[10];
781 conf->realName = row[11];
782 conf->group = row[12];
783
784 if (GetDouble(row[13], &conf->credit, 0) != 0)
785     {
786     mysql_free_result(res);
787     errorStr = "User \'" + login + "\' data not read. Parameter Credit.";
788     mysql_close(sock);
789     return -1;
790     }
791
792 conf->nextTariff = row[14];
793
794 for (int i = 0; i < USERDATA_NUM; i++)
795     {
796     conf->userdata[i] = row[15+i];
797     }
798
799 GetTime(row[15+USERDATA_NUM], &conf->creditExpire, 0);
800     
801 string ipStr = row[16+USERDATA_NUM];
802 USER_IPS i;
803 try
804     {
805     i = StrToIPS(ipStr);
806     }
807 catch (const string & s)
808     {
809     mysql_free_result(res);
810     errorStr = "User \'" + login + "\' data not read. Parameter IP address. " + s;
811     mysql_close(sock);
812     return -1;
813     }
814 conf->ips = i;
815
816 mysql_free_result(res);
817 mysql_close(sock);
818
819 return 0;
820 }
821 //-----------------------------------------------------------------------------
822 int MYSQL_STORE::RestoreUserStat(USER_STAT * stat, const string & login) const
823 {
824 MYSQL_RES *res;
825 MYSQL_ROW row;
826 MYSQL * sock;
827
828 string query;
829
830 query = "SELECT ";
831
832 for (int i = 0; i < DIR_NUM; i++)
833 {
834     sprintf(qbuf, "D%d, U%d, ", i, i);
835     query += qbuf;
836 }
837
838 query += "Cash, FreeMb, LastCashAdd, LastCashAddTime, PassiveTime, LastActivityTime \
839           FROM users WHERE login = '";
840 query += login + "'";
841
842 //sprintf(qbuf,"SELECT * FROM users WHERE login='%s' LIMIT 1", login.c_str());
843     
844 if(MysqlGetQuery(query.c_str() ,sock))
845 {
846     errorStr = "Couldn't restore UserStat(on query):\n";
847     errorStr += mysql_error(sock);
848     mysql_close(sock);
849     return -1;
850 }
851
852 if (!(res=mysql_store_result(sock)))
853 {
854     errorStr = "Couldn't restore UserStat(on getting result):\n";
855     errorStr += mysql_error(sock);
856     mysql_close(sock);
857     return -1;
858 }
859
860 row = mysql_fetch_row(res);
861
862 unsigned int startPos=0;
863
864 char s[22];
865
866 for (int i = 0; i < DIR_NUM; i++)
867     {
868     uint64_t traff;
869     sprintf(s, "D%d", i);
870     if (GetULongLongInt(row[startPos+i*2], &traff, 0) != 0)
871         {
872         mysql_free_result(res);
873         errorStr = "User \'" + login + "\' stat not read. Parameter " + string(s);
874         mysql_close(sock);
875         return -1;
876         }
877     stat->down[i] = traff;
878
879     sprintf(s, "U%d", i);
880     if (GetULongLongInt(row[startPos+i*2+1], &traff, 0) != 0)
881         {
882         mysql_free_result(res);
883         errorStr =   "User \'" + login + "\' stat not read. Parameter " + string(s);
884         mysql_close(sock);
885         return -1;
886         }
887     stat->up[i] = traff;
888     }//for
889
890 startPos += (2*DIR_NUM);
891
892 if (GetDouble(row[startPos], &stat->cash, 0) != 0)
893     {
894     mysql_free_result(res);
895     errorStr =   "User \'" + login + "\' stat not read. Parameter Cash";
896     mysql_close(sock);
897     return -1;
898     }
899
900 if (GetDouble(row[startPos+1],&stat->freeMb, 0) != 0)
901     {
902     mysql_free_result(res);
903     errorStr =   "User \'" + login + "\' stat not read. Parameter FreeMb";
904     mysql_close(sock);
905     return -1;
906     }
907
908 if (GetDouble(row[startPos+2], &stat->lastCashAdd, 0) != 0)
909     {
910     mysql_free_result(res);
911     errorStr =   "User \'" + login + "\' stat not read. Parameter LastCashAdd";
912     mysql_close(sock);
913     return -1;
914     }
915
916 if (GetTime(row[startPos+3], &stat->lastCashAddTime, 0) != 0)
917     {
918     mysql_free_result(res);
919     errorStr =   "User \'" + login + "\' stat not read. Parameter LastCashAddTime";
920     mysql_close(sock);
921     return -1;
922     }
923
924 if (GetTime(row[startPos+4], &stat->passiveTime, 0) != 0)
925     {
926     mysql_free_result(res);
927     errorStr =   "User \'" + login + "\' stat not read. Parameter PassiveTime";
928     mysql_close(sock);
929     return -1;
930     }
931
932 if (GetTime(row[startPos+5], &stat->lastActivityTime, 0) != 0)
933     {
934     mysql_free_result(res);
935     errorStr =   "User \'" + login + "\' stat not read. Parameter LastActivityTime";
936     mysql_close(sock);
937     return -1;
938     }
939
940 mysql_free_result(res);
941 mysql_close(sock);
942 return 0;
943 }
944 //-----------------------------------------------------------------------------
945 int MYSQL_STORE::SaveUserConf(const USER_CONF & conf, const string & login) const
946 {
947 string param;
948 string res;
949
950 strprintf(&res,"UPDATE users SET Password='%s', Passive=%d, Down=%d, DisabledDetailStat = %d, "\
951     "AlwaysOnline=%d, Tariff='%s', Address='%s', Phone='%s', Email='%s', "\
952     "Note='%s', RealName='%s', StgGroup='%s', Credit=%f, TariffChange='%s', ", 
953     conf.password.c_str(),
954     conf.passive,
955     conf.disabled,
956     conf.disabledDetailStat,
957     conf.alwaysOnline,
958     conf.tariffName.c_str(),
959     (ReplaceStr(conf.address,badSyms,repSym)).c_str(),
960     (ReplaceStr(conf.phone,badSyms,repSym)).c_str(),
961     (ReplaceStr(conf.email,badSyms,repSym)).c_str(),
962     (ReplaceStr(conf.note,badSyms,repSym)).c_str(),
963     (ReplaceStr(conf.realName,badSyms,repSym)).c_str(),
964     (ReplaceStr(conf.group,badSyms,repSym)).c_str(),
965     conf.credit,
966     conf.nextTariff.c_str()
967     );
968
969 for (int i = 0; i < USERDATA_NUM; i++)
970     {
971     strprintf(&param, " Userdata%d='%s',", i, 
972         (ReplaceStr(conf.userdata[i],badSyms,repSym)).c_str());
973     res += param;
974     }
975     
976 strprintf(&param, " CreditExpire=%d,", conf.creditExpire);
977 res += param;
978
979 stringstream ipStr;
980 ipStr << conf.ips;
981
982 strprintf(&param, " IP='%s'", ipStr.str().c_str());
983 res += param;
984
985 strprintf(&param, " WHERE login='%s' LIMIT 1", login.c_str());
986 res += param;
987
988 if(MysqlSetQuery(res.c_str()))
989 {
990     errorStr = "Couldn't save user conf:\n";
991     //errorStr += mysql_error(sock);
992     return -1;
993 }
994
995 return 0;
996 }
997 //-----------------------------------------------------------------------------
998 int MYSQL_STORE::SaveUserStat(const USER_STAT & stat, const string & login) const
999 {
1000 string param;
1001 string res;
1002
1003 res = "UPDATE users SET";
1004
1005 for (int i = 0; i < DIR_NUM; i++)
1006     {
1007     strprintf(&param, " D%d=%lld,", i, stat.down[i]);
1008     res += param;
1009
1010     strprintf(&param, " U%d=%lld,", i, stat.up[i]);
1011     res += param;
1012     }
1013
1014 strprintf(&param, " Cash=%f, FreeMb=%f, LastCashAdd=%f, LastCashAddTime=%d,"\
1015     " PassiveTime=%d, LastActivityTime=%d", 
1016     stat.cash,
1017     stat.freeMb,
1018     stat.lastCashAdd,
1019     stat.lastCashAddTime,
1020     stat.passiveTime,
1021     stat.lastActivityTime
1022     );
1023 res += param;
1024
1025 strprintf(&param, " WHERE login='%s' LIMIT 1", login.c_str());
1026 res += param;
1027
1028 if(MysqlSetQuery(res.c_str()))
1029 {
1030     errorStr = "Couldn't save user stat:\n";
1031 //    errorStr += mysql_error(sock);
1032     return -1;
1033 }
1034
1035 return 0;
1036 }
1037 //-----------------------------------------------------------------------------
1038 int MYSQL_STORE::WriteLogString(const string & str, const string & login) const
1039 {
1040 string res, tempStr;
1041 time_t t;
1042 tm * lt;
1043
1044 t = time(NULL);
1045 lt = localtime(&t);
1046
1047 MYSQL_RES* result;
1048 MYSQL * sock;
1049 strprintf(&tempStr, "logs_%02d_%4d", lt->tm_mon+1, lt->tm_year+1900);
1050 if (!(sock=MysqlConnect())){
1051     errorStr = "Couldn't connect to Server";
1052     return -1;
1053 }
1054 if (!(result=mysql_list_tables(sock,tempStr.c_str() )))
1055 {
1056     errorStr = "Couldn't get table " + tempStr + ":\n";
1057     errorStr += mysql_error(sock);
1058     mysql_close(sock);
1059     return -1;
1060 }
1061
1062 unsigned int num_rows =  mysql_num_rows(result);
1063
1064 mysql_free_result(result);
1065
1066 if (num_rows < 1)
1067 {
1068     sprintf(qbuf,"CREATE TABLE logs_%02d_%4d (unid INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, login VARCHAR(40),text TEXT)",
1069     lt->tm_mon+1, lt->tm_year+1900);
1070     
1071     if(MysqlQuery(qbuf,sock))
1072     {
1073         errorStr = "Couldn't create WriteDetailedStat table:\n";
1074         errorStr += mysql_error(sock);
1075         mysql_close(sock);
1076         return -1;
1077     }
1078 }
1079
1080 strprintf(&res, "%s -- %s",LogDate(t), str.c_str());
1081
1082 string send;
1083
1084 strprintf(&send,"INSERT INTO logs_%02d_%4d SET login='%s', text='%s'",
1085         lt->tm_mon+1, lt->tm_year+1900,
1086     login.c_str(), (ReplaceStr(res,badSyms,repSym)).c_str());
1087
1088 if(MysqlQuery(send.c_str(),sock))
1089 {
1090     errorStr = "Couldn't write log string:\n";
1091     errorStr += mysql_error(sock);
1092     mysql_close(sock);
1093     return -1;
1094 }
1095 mysql_close(sock);
1096 return 0;
1097
1098 }
1099 //-----------------------------------------------------------------------------
1100 int MYSQL_STORE::WriteUserChgLog(const string & login,
1101                                  const string & admLogin,
1102                                  uint32_t       admIP,
1103                                  const string & paramName,
1104                                  const string & oldValue,
1105                                  const string & newValue,
1106                                  const string & message) const
1107 {
1108 string userLogMsg = "Admin \'" + admLogin + "\', " + inet_ntostring(admIP) + ": \'"
1109     + paramName + "\' parameter changed from \'" + oldValue +
1110     "\' to \'" + newValue + "\'. " + message;
1111
1112 return WriteLogString(userLogMsg, login);
1113 }
1114 //-----------------------------------------------------------------------------
1115 int MYSQL_STORE::WriteUserConnect(const string & login, uint32_t ip) const
1116 {
1117 string logStr = "Connect, " + inet_ntostring(ip);
1118 return WriteLogString(logStr, login);
1119 }
1120 //-----------------------------------------------------------------------------
1121 int MYSQL_STORE::WriteUserDisconnect(const string & login,
1122                                      const DIR_TRAFF & up,
1123                                      const DIR_TRAFF & down,
1124                                      const DIR_TRAFF & sessionUp,
1125                                      const DIR_TRAFF & sessionDown,
1126                                      double cash,
1127                                      double freeMb,
1128                                      const std::string & reason) const
1129 {
1130 string logStr = "Disconnect, ";
1131 stringstream sssu;
1132 stringstream sssd;
1133 stringstream ssmu;
1134 stringstream ssmd;
1135 stringstream sscash;
1136
1137 ssmu << up;
1138 ssmd << down;
1139
1140 sssu << sessionUp;
1141 sssd << sessionDown;
1142
1143 sscash << cash;
1144
1145 logStr += " session upload: \'";
1146 logStr += sssu.str();
1147 logStr += "\' session download: \'";
1148 logStr += sssd.str();
1149 logStr += "\' month upload: \'";
1150 logStr += ssmu.str();
1151 logStr += "\' month download: \'";
1152 logStr += ssmd.str();
1153 logStr += "\' cash: \'";
1154 logStr += sscash.str();
1155 logStr += "\'";
1156
1157 return WriteLogString(logStr, login);
1158 }
1159 //-----------------------------------------------------------------------------
1160 int MYSQL_STORE::SaveMonthStat(const USER_STAT & stat, int month, int year, 
1161                                 const string & login) const
1162 {
1163 string param, res;
1164
1165 strprintf(&res, "INSERT INTO stat SET login='%s', month=%d, year=%d,", 
1166     login.c_str(), month+1, year+1900);
1167     
1168 for (int i = 0; i < DIR_NUM; i++)
1169     {
1170     strprintf(&param, " U%d=%lld,", i, stat.up[i]); 
1171     res += param;
1172
1173     strprintf(&param, " D%d=%lld,", i, stat.down[i]);        
1174     res += param;
1175     }
1176     
1177 strprintf(&param, " cash=%f", stat.cash);        
1178 res += param;
1179
1180 if(MysqlSetQuery(res.c_str()))
1181 {
1182     errorStr = "Couldn't SaveMonthStat:\n";
1183     //errorStr += mysql_error(sock);
1184     return -1;
1185 }
1186
1187 return 0;
1188 }
1189 //-----------------------------------------------------------------------------*/
1190 int MYSQL_STORE::AddAdmin(const string & login) const
1191 {
1192 sprintf(qbuf,"INSERT INTO admins SET login='%s'", login.c_str());
1193     
1194 if(MysqlSetQuery(qbuf))
1195 {
1196     errorStr = "Couldn't add admin:\n";
1197     //errorStr += mysql_error(sock);
1198     return -1;
1199 }
1200
1201 return 0;
1202 }
1203 //-----------------------------------------------------------------------------*/
1204 int MYSQL_STORE::DelAdmin(const string & login) const
1205 {
1206 sprintf(qbuf,"DELETE FROM admins where login='%s' LIMIT 1", login.c_str());
1207     
1208 if(MysqlSetQuery(qbuf))
1209 {
1210     errorStr = "Couldn't delete admin:\n";
1211     //errorStr += mysql_error(sock);
1212     return -1;
1213 }
1214
1215 return 0;
1216 }
1217 //-----------------------------------------------------------------------------*/
1218 int MYSQL_STORE::SaveAdmin(const ADMIN_CONF & ac) const
1219 {
1220 char passwordE[2 * ADM_PASSWD_LEN + 2];
1221 char pass[ADM_PASSWD_LEN + 1];
1222 char adminPass[ADM_PASSWD_LEN + 1];
1223
1224 memset(pass, 0, sizeof(pass));
1225 memset(adminPass, 0, sizeof(adminPass));
1226
1227 BLOWFISH_CTX ctx;
1228 EnDecodeInit(adm_enc_passwd, strlen(adm_enc_passwd), &ctx);
1229
1230 strncpy(adminPass, ac.password.c_str(), ADM_PASSWD_LEN);
1231 adminPass[ADM_PASSWD_LEN - 1] = 0;
1232
1233 for (int i = 0; i < ADM_PASSWD_LEN/8; i++)
1234     {
1235     EncodeString(pass + 8*i, adminPass + 8*i, &ctx);
1236     }
1237
1238 pass[ADM_PASSWD_LEN - 1] = 0;
1239 Encode12(passwordE, pass, ADM_PASSWD_LEN);
1240
1241 sprintf(qbuf,"UPDATE admins SET password='%s', ChgConf=%d, ChgPassword=%d, "\
1242     "ChgStat=%d, ChgCash=%d, UsrAddDel=%d, ChgTariff=%d, ChgAdmin=%d "\
1243     "WHERE login='%s' LIMIT 1", 
1244     passwordE,
1245     ac.priv.userConf,
1246     ac.priv.userPasswd,
1247     ac.priv.userStat,
1248     ac.priv.userCash,
1249     ac.priv.userAddDel,
1250     ac.priv.tariffChg,
1251     ac.priv.adminChg,
1252     ac.login.c_str()
1253     );
1254
1255 if(MysqlSetQuery(qbuf))
1256 {
1257     errorStr = "Couldn't save admin:\n";
1258     //errorStr += mysql_error(sock);
1259     return -1;
1260 }
1261
1262 return 0;
1263 }
1264 //-----------------------------------------------------------------------------
1265 int MYSQL_STORE::RestoreAdmin(ADMIN_CONF * ac, const string & login) const
1266 {
1267 char pass[ADM_PASSWD_LEN + 1];
1268 char password[ADM_PASSWD_LEN + 1];
1269 char passwordE[2*ADM_PASSWD_LEN + 2];
1270 BLOWFISH_CTX ctx;
1271
1272 string p;
1273 MYSQL_RES *res;
1274 MYSQL_ROW row;
1275 MYSQL * sock;
1276 sprintf(qbuf,"SELECT * FROM admins WHERE login='%s' LIMIT 1", login.c_str());
1277     
1278 if(MysqlGetQuery(qbuf,sock))
1279 {
1280     errorStr = "Couldn't restore admin:\n";
1281     errorStr += mysql_error(sock);
1282     mysql_close(sock);
1283     return -1;
1284 }
1285
1286 if (!(res=mysql_store_result(sock)))
1287 {
1288     errorStr = "Couldn't restore admin:\n";
1289     errorStr += mysql_error(sock);
1290     mysql_close(sock);
1291     return -1;
1292 }
1293
1294 if ( mysql_num_rows(res) == 0)
1295 {
1296     mysql_free_result(res);
1297     errorStr = "Couldn't restore admin as couldn't found him in table.\n";
1298     mysql_close(sock);
1299     return -1;
1300 }
1301   
1302 row = mysql_fetch_row(res);
1303
1304 p = row[1];
1305 int a;
1306
1307 if(p.length() == 0)
1308 {
1309     mysql_free_result(res);
1310     errorStr = "Error in parameter password";
1311     mysql_close(sock);
1312     return -1;
1313 }
1314
1315 memset(passwordE, 0, sizeof(passwordE));
1316 strncpy(passwordE, p.c_str(), 2*ADM_PASSWD_LEN);
1317
1318 memset(pass, 0, sizeof(pass));
1319
1320 if (passwordE[0] != 0)
1321     {
1322     Decode21(pass, passwordE);
1323     EnDecodeInit(adm_enc_passwd, strlen(adm_enc_passwd), &ctx);
1324
1325     for (int i = 0; i < ADM_PASSWD_LEN/8; i++)
1326         {
1327         DecodeString(password + 8*i, pass + 8*i, &ctx);
1328         }
1329     }
1330 else
1331     {
1332     password[0] = 0;
1333     }
1334
1335 ac->password = password;
1336
1337 if (GetInt(row[2], &a, 0) == 0) 
1338     ac->priv.userConf = a;
1339 else
1340     {
1341     mysql_free_result(res);
1342     errorStr = "Error in parameter ChgConf";
1343     mysql_close(sock);
1344     return -1;
1345     }
1346
1347 if (GetInt(row[3], &a, 0) == 0) 
1348     ac->priv.userPasswd = a;
1349 else
1350     {
1351     mysql_free_result(res);
1352     errorStr = "Error in parameter ChgPassword";
1353     mysql_close(sock);
1354     return -1;
1355     }
1356
1357 if (GetInt(row[4], &a, 0) == 0) 
1358     ac->priv.userStat = a;
1359 else
1360     {
1361     mysql_free_result(res);
1362     errorStr = "Error in parameter ChgStat";
1363     mysql_close(sock);
1364     return -1;
1365     }
1366
1367 if (GetInt(row[5], &a, 0) == 0) 
1368     ac->priv.userCash = a;
1369 else
1370     {
1371     mysql_free_result(res);
1372     errorStr = "Error in parameter ChgCash";
1373     mysql_close(sock);
1374     return -1;
1375     }
1376
1377 if (GetInt(row[6], &a, 0) == 0) 
1378     ac->priv.userAddDel = a;
1379 else
1380     {
1381     mysql_free_result(res);
1382     errorStr = "Error in parameter UsrAddDel";
1383     mysql_close(sock);
1384     return -1;
1385     }
1386
1387 if (GetInt(row[7], &a, 0) == 0) 
1388     ac->priv.tariffChg = a;
1389 else
1390     {
1391     mysql_free_result(res);
1392     errorStr = "Error in parameter ChgTariff";
1393     mysql_close(sock);
1394     return -1;
1395     }
1396
1397 if (GetInt(row[8], &a, 0) == 0) 
1398     ac->priv.adminChg = a;
1399 else
1400     {
1401     mysql_free_result(res);
1402     errorStr = "Error in parameter ChgAdmin";
1403     mysql_close(sock);
1404     return -1;
1405     }
1406
1407 mysql_free_result(res);
1408 mysql_close(sock);
1409 return 0;
1410 }
1411 //-----------------------------------------------------------------------------
1412 int MYSQL_STORE::AddTariff(const string & name) const
1413 {
1414 sprintf(qbuf,"INSERT INTO tariffs SET name='%s'", name.c_str());
1415     
1416 if(MysqlSetQuery(qbuf))
1417 {
1418     errorStr = "Couldn't add tariff:\n";
1419 //    errorStr += mysql_error(sock);
1420     return -1;
1421 }
1422
1423 return 0;
1424 }
1425 //-----------------------------------------------------------------------------
1426 int MYSQL_STORE::DelTariff(const string & name) const
1427 {
1428 sprintf(qbuf,"DELETE FROM tariffs WHERE name='%s' LIMIT 1", name.c_str());
1429     
1430 if(MysqlSetQuery(qbuf))
1431 {
1432     errorStr = "Couldn't delete tariff: ";
1433 //    errorStr += mysql_error(sock);
1434     return -1;
1435 }
1436
1437 return 0;
1438 }
1439 //-----------------------------------------------------------------------------
1440 int MYSQL_STORE::RestoreTariff(TARIFF_DATA * td, const string & tariffName) const
1441 {
1442 MYSQL_RES *res;
1443 MYSQL_ROW row;
1444 MYSQL * sock;
1445 sprintf(qbuf,"SELECT * FROM tariffs WHERE name='%s' LIMIT 1", tariffName.c_str());
1446     
1447 if(MysqlGetQuery(qbuf,sock))
1448 {
1449     errorStr = "Couldn't restore Tariff:\n";
1450     errorStr += mysql_error(sock);
1451     mysql_close(sock);
1452     return -1;
1453 }
1454
1455 if (!(res=mysql_store_result(sock)))
1456 {
1457     errorStr = "Couldn't restore Tariff:\n";
1458     errorStr += mysql_error(sock);
1459     mysql_close(sock);
1460     return -1;
1461 }
1462
1463 string str;
1464 td->tariffConf.name = tariffName;
1465
1466 row = mysql_fetch_row(res);
1467
1468 string param;
1469 for (int i = 0; i<DIR_NUM; i++)
1470     {
1471     strprintf(&param, "Time%d", i);
1472     str = row[6+i*8];
1473     if (str.length() == 0)
1474         {
1475         mysql_free_result(res);
1476         errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
1477         mysql_close(sock);
1478         return -1;
1479         }
1480
1481     ParseTariffTimeStr(str.c_str(), 
1482                        td->dirPrice[i].hDay, 
1483                        td->dirPrice[i].mDay, 
1484                        td->dirPrice[i].hNight, 
1485                        td->dirPrice[i].mNight);
1486
1487     strprintf(&param, "PriceDayA%d", i);
1488     if (GetDouble(row[1+i*8], &td->dirPrice[i].priceDayA, 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].priceDayA /= (1024*1024);
1496
1497     strprintf(&param, "PriceDayB%d", i);
1498     if (GetDouble(row[2+i*8], &td->dirPrice[i].priceDayB, 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].priceDayB /= (1024*1024);
1506
1507     strprintf(&param, "PriceNightA%d", i);
1508     if (GetDouble(row[3+i*8], &td->dirPrice[i].priceNightA, 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].priceNightA /= (1024*1024);
1516
1517     strprintf(&param, "PriceNightB%d", i);
1518     if (GetDouble(row[4+i*8], &td->dirPrice[i].priceNightB, 0.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     td->dirPrice[i].priceNightB /= (1024*1024);
1526
1527     strprintf(&param, "Threshold%d", i);
1528     if (GetInt(row[5+i*8], &td->dirPrice[i].threshold, 0) < 0)
1529         {
1530         mysql_free_result(res);
1531         errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
1532         mysql_close(sock);
1533         return -1;
1534         }
1535
1536     strprintf(&param, "SinglePrice%d", i);
1537     if (GetInt(row[8+i*8], &td->dirPrice[i].singlePrice, 0) < 0)
1538         {
1539         mysql_free_result(res);
1540         errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
1541         mysql_close(sock);
1542         return -1;
1543         }
1544
1545     strprintf(&param, "NoDiscount%d", i);
1546     if (GetInt(row[7+i*8], &td->dirPrice[i].noDiscount, 0) < 0)
1547         {
1548         mysql_free_result(res);
1549         errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
1550         mysql_close(sock);
1551         return -1;
1552         }
1553     }//main for
1554
1555 if (GetDouble(row[2+8*DIR_NUM], &td->tariffConf.fee, 0.0) < 0)
1556     {
1557     mysql_free_result(res);
1558     errorStr = "Cannot read tariff " + tariffName + ". Parameter Fee";
1559     mysql_close(sock);
1560     return -1;
1561     }
1562
1563 if (GetDouble(row[3+8*DIR_NUM], &td->tariffConf.free, 0.0) < 0)
1564     {
1565     mysql_free_result(res);
1566     errorStr = "Cannot read tariff " + tariffName + ". Parameter Free";
1567     mysql_close(sock);
1568     return -1;
1569     }
1570
1571 if (GetDouble(row[1+8*DIR_NUM], &td->tariffConf.passiveCost, 0.0) < 0)
1572     {
1573     mysql_free_result(res);
1574     errorStr = "Cannot read tariff " + tariffName + ". Parameter PassiveCost";
1575     mysql_close(sock);
1576     return -1;
1577     }
1578
1579     str = row[4+8*DIR_NUM];
1580     param = "TraffType";
1581     
1582     if (str.length() == 0)
1583         {
1584         mysql_free_result(res);
1585         errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
1586         mysql_close(sock);
1587         return -1;
1588         }
1589
1590 if (!strcasecmp(str.c_str(), "up"))
1591     td->tariffConf.traffType = TRAFF_UP;
1592 else
1593     if (!strcasecmp(str.c_str(), "down"))
1594         td->tariffConf.traffType = TRAFF_DOWN;
1595     else
1596         if (!strcasecmp(str.c_str(), "up+down"))
1597             td->tariffConf.traffType = TRAFF_UP_DOWN;
1598         else
1599             if (!strcasecmp(str.c_str(), "max"))
1600                 td->tariffConf.traffType = TRAFF_MAX;
1601             else
1602                 {
1603                 mysql_free_result(res);
1604                 errorStr = "Cannot read tariff " + tariffName + ". Parameter TraffType incorrect";
1605                 mysql_close(sock);
1606                 return -1;
1607                 }
1608
1609 mysql_free_result(res);
1610 mysql_close(sock);
1611 return 0;
1612 }
1613 //-----------------------------------------------------------------------------
1614 int MYSQL_STORE::SaveTariff(const TARIFF_DATA & td, const string & tariffName) const
1615 {
1616 string param;
1617
1618 string res="UPDATE tariffs SET";
1619
1620 for (int i = 0; i < DIR_NUM; i++)
1621     {
1622     strprintf(&param, " PriceDayA%d=%f,", i, 
1623         td.dirPrice[i].priceDayA * pt_mega);
1624     res += param;
1625
1626     strprintf(&param, " PriceDayB%d=%f,", i, 
1627         td.dirPrice[i].priceDayB * pt_mega);        
1628     res += param;
1629         
1630     strprintf(&param, " PriceNightA%d=%f,", i,
1631         td.dirPrice[i].priceNightA * pt_mega);
1632     res += param;
1633
1634     strprintf(&param, " PriceNightB%d=%f,", i, 
1635         td.dirPrice[i].priceNightB * pt_mega);
1636     res += param;
1637         
1638     strprintf(&param, " Threshold%d=%d,", i, 
1639         td.dirPrice[i].threshold);
1640     res += param;
1641
1642     string s;
1643     strprintf(&param, " Time%d", i);
1644
1645     strprintf(&s, "%0d:%0d-%0d:%0d", 
1646             td.dirPrice[i].hDay,
1647             td.dirPrice[i].mDay,
1648             td.dirPrice[i].hNight,
1649             td.dirPrice[i].mNight);
1650
1651     res += (param + "='" + s + "',");
1652
1653     strprintf(&param, " NoDiscount%d=%d,", i, 
1654         td.dirPrice[i].noDiscount);
1655     res += param;
1656
1657     strprintf(&param, " SinglePrice%d=%d,", i, 
1658         td.dirPrice[i].singlePrice);
1659     res += param;
1660     }
1661
1662 strprintf(&param, " PassiveCost=%f,", td.tariffConf.passiveCost);
1663 res += param;
1664
1665 strprintf(&param, " Fee=%f,", td.tariffConf.fee);
1666 res += param;
1667
1668 strprintf(&param, " Free=%f,", td.tariffConf.free);
1669 res += param;
1670
1671 switch (td.tariffConf.traffType)
1672     {
1673     case TRAFF_UP:
1674         res += " TraffType='up'";
1675         break;
1676     case TRAFF_DOWN:
1677         res += " TraffType='down'";
1678         break;
1679     case TRAFF_UP_DOWN:
1680         res += " TraffType='up+down'";
1681         break;
1682     case TRAFF_MAX:
1683         res += " TraffType='max'";
1684         break;
1685     }
1686 strprintf(&param, " WHERE name='%s' LIMIT 1", tariffName.c_str());
1687 res += param;
1688
1689 if(MysqlSetQuery(res.c_str()))
1690 {
1691     errorStr = "Couldn't save admin:\n";
1692     //errorStr += mysql_error(sock);
1693     return -1;
1694 }
1695
1696 return 0;
1697 }
1698 //-----------------------------------------------------------------------------
1699 int MYSQL_STORE::WriteDetailedStat(const map<IP_DIR_PAIR, STAT_NODE> & statTree, 
1700                                    time_t lastStat, 
1701                                    const string & login) const
1702 {
1703 string res, stTime, endTime, tempStr;
1704 time_t t;
1705 tm * lt;
1706
1707 t = time(NULL);
1708 lt = localtime(&t);
1709
1710 if (lt->tm_hour == 0 && lt->tm_min <= 5)
1711     {
1712         t -= 3600 * 24;
1713         lt = localtime(&t);
1714     }
1715
1716 MYSQL_RES* result;
1717 MYSQL * sock;
1718 strprintf(&tempStr, "detailstat_%02d_%4d", lt->tm_mon+1, lt->tm_year+1900);
1719
1720 if (!(sock=MysqlConnect())){
1721     mysql_close(sock);
1722     return -1;
1723 }
1724
1725 if (!(result=mysql_list_tables(sock,tempStr.c_str() )))
1726 {
1727     errorStr = "Couldn't get table " + tempStr + ":\n";
1728     errorStr += mysql_error(sock);
1729     mysql_close(sock);
1730     return -1;
1731 }
1732
1733 unsigned int num_rows =  mysql_num_rows(result);
1734
1735 mysql_free_result(result);
1736
1737 if (num_rows < 1)
1738 {
1739     sprintf(qbuf,"CREATE TABLE detailstat_%02d_%4d (login VARCHAR(40) DEFAULT '',"\
1740         "day TINYINT DEFAULT 0,startTime TIME,endTime TIME,"\
1741         "IP VARCHAR(17) DEFAULT '',dir INT DEFAULT 0,"\
1742         "down BIGINT DEFAULT 0,up BIGINT DEFAULT 0, cash DOUBLE DEFAULT 0.0, INDEX (login), INDEX(dir), INDEX(day), INDEX(IP))",
1743     lt->tm_mon+1, lt->tm_year+1900);
1744     
1745     if(MysqlQuery(qbuf,sock))
1746     {
1747         errorStr = "Couldn't create WriteDetailedStat table:\n";
1748         errorStr += mysql_error(sock);
1749         mysql_close(sock);
1750         return -1;
1751     }
1752 }
1753
1754 struct tm * lt1;
1755 struct tm * lt2;
1756
1757 lt1 = localtime(&lastStat);
1758
1759 int h1, m1, s1;
1760 int h2, m2, s2;
1761
1762 h1 = lt1->tm_hour;
1763 m1 = lt1->tm_min;
1764 s1 = lt1->tm_sec;
1765
1766 lt2 = localtime(&t);
1767
1768 h2 = lt2->tm_hour;
1769 m2 = lt2->tm_min;
1770 s2 = lt2->tm_sec;
1771     
1772 strprintf(&stTime, "%02d:%02d:%02d", h1, m1, s1);
1773 strprintf(&endTime, "%02d:%02d:%02d", h2, m2, s2);
1774
1775 strprintf(&res,"INSERT INTO detailstat_%02d_%4d SET login='%s',"\
1776     "day=%d,startTime='%s',endTime='%s',", 
1777     lt->tm_mon+1, lt->tm_year+1900,
1778     login.c_str(),
1779     lt->tm_mday,
1780     stTime.c_str(),
1781     endTime.c_str()
1782     );
1783
1784 map<IP_DIR_PAIR, STAT_NODE>::const_iterator stIter;
1785 stIter = statTree.begin();
1786
1787 while (stIter != statTree.end())
1788     {
1789         strprintf(&tempStr,"IP='%s', dir=%d, down=%lld, up=%lld, cash=%f", 
1790                 inet_ntostring(stIter->first.ip).c_str(),
1791                 stIter->first.dir, 
1792                 stIter->second.down, 
1793                 stIter->second.up, 
1794                 stIter->second.cash
1795             );
1796     
1797         if( MysqlQuery((res+tempStr).c_str(),sock) )
1798         {
1799             errorStr = "Couldn't insert data in WriteDetailedStat:\n";
1800             errorStr += mysql_error(sock);
1801             mysql_close(sock);
1802             return -1;
1803         }
1804
1805         result=mysql_store_result(sock);
1806         if(result)
1807             mysql_free_result(result);
1808
1809         ++stIter;
1810     }
1811 mysql_close(sock);
1812 return 0;
1813 }
1814 //-----------------------------------------------------------------------------
1815 int MYSQL_STORE::AddMessage(STG_MSG * msg, const string & login) const
1816 {
1817 struct timeval tv;
1818
1819 gettimeofday(&tv, NULL);
1820
1821 msg->header.id = ((long long)tv.tv_sec) * 1000000 + ((long long)tv.tv_usec);
1822
1823 sprintf(qbuf,"INSERT INTO messages SET login='%s', id=%lld", 
1824     login.c_str(),
1825     (long long)msg->header.id
1826     );
1827     
1828 if(MysqlSetQuery(qbuf))
1829 {
1830     errorStr = "Couldn't add message:\n";
1831     //errorStr += mysql_error(sock);
1832     return -1;
1833 }
1834
1835 return EditMessage(*msg, login);
1836 }
1837 //-----------------------------------------------------------------------------
1838 int MYSQL_STORE::EditMessage(const STG_MSG & msg, const string & login) const
1839 {
1840 string res;
1841
1842 strprintf(&res,"UPDATE messages SET type=%d, lastSendTime=%u, creationTime=%u, "\
1843     "showTime=%u, stgRepeat=%d, repeatPeriod=%u, text='%s' "\
1844     "WHERE login='%s' AND id=%lld LIMIT 1", 
1845     msg.header.type,
1846     msg.header.lastSendTime,
1847     msg.header.creationTime,
1848     msg.header.showTime,
1849     msg.header.repeat,
1850     msg.header.repeatPeriod,
1851     (ReplaceStr(msg.text,badSyms,repSym)).c_str(),
1852     login.c_str(),
1853     (long long)msg.header.id
1854     );
1855
1856 if(MysqlSetQuery(res.c_str()))
1857 {
1858     errorStr = "Couldn't edit message:\n";
1859     //errorStr += mysql_error(sock);
1860     return -1;
1861 }
1862
1863 return 0;
1864 }
1865 //-----------------------------------------------------------------------------
1866 int MYSQL_STORE::GetMessage(uint64_t id, STG_MSG * msg, const string & login) const
1867 {
1868 MYSQL_RES *res;
1869 MYSQL_ROW row;
1870 MYSQL * sock;
1871
1872 sprintf(qbuf,"SELECT * FROM messages WHERE login='%s' AND id=%lld LIMIT 1",
1873     login.c_str(), id);
1874     
1875 if(MysqlGetQuery(qbuf,sock))
1876 {
1877     errorStr = "Couldn't GetMessage:\n";
1878     errorStr += mysql_error(sock);
1879     mysql_close(sock);
1880     return -1;
1881 }
1882
1883 if (!(res=mysql_store_result(sock)))
1884 {
1885     errorStr = "Couldn't GetMessage:\n";
1886     errorStr += mysql_error(sock);
1887     mysql_close(sock);
1888     return -1;
1889 }
1890
1891 row = mysql_fetch_row(res);
1892
1893 if(row[2]&&str2x(row[2], msg->header.type))
1894 {
1895     mysql_free_result(res);
1896     errorStr = "Invalid value in message header for user: " + login;
1897     mysql_close(sock);
1898     return -1;
1899 }
1900
1901 if(row[3] && str2x(row[3], msg->header.lastSendTime))
1902 {
1903     mysql_free_result(res);
1904     errorStr = "Invalid value in message header for user: " + login;
1905     mysql_close(sock);
1906     return -1;
1907 }
1908
1909 if(row[4] && str2x(row[4], msg->header.creationTime))
1910 {
1911     mysql_free_result(res);
1912     errorStr = "Invalid value in message header for user: " + login;
1913     mysql_close(sock);
1914     return -1;
1915 }
1916
1917 if(row[5] && str2x(row[5], msg->header.showTime))
1918 {
1919     mysql_free_result(res);
1920     errorStr = "Invalid value in message header for user: " + login;
1921     mysql_close(sock);
1922     return -1;
1923 }
1924
1925 if(row[6] && str2x(row[6], msg->header.repeat))
1926 {
1927     mysql_free_result(res);
1928     errorStr = "Invalid value in message header for user: " + login;
1929     mysql_close(sock);
1930     return -1;
1931 }
1932
1933 if(row[7] && str2x(row[7], msg->header.repeatPeriod))
1934 {
1935     mysql_free_result(res);
1936     errorStr = "Invalid value in message header for user: " + login;
1937     mysql_close(sock);
1938     return -1;
1939 }
1940
1941 msg->header.id = id;
1942 msg->text = row[8];
1943
1944 mysql_free_result(res);
1945 mysql_close(sock);
1946 return 0;
1947 }
1948 //-----------------------------------------------------------------------------
1949 int MYSQL_STORE::DelMessage(uint64_t id, const string & login) const
1950 {
1951 sprintf(qbuf,"DELETE FROM messages WHERE login='%s' AND id=%lld LIMIT 1", 
1952     login.c_str(),(long long)id);
1953     
1954 if(MysqlSetQuery(qbuf))
1955 {
1956     errorStr = "Couldn't delete Message:\n";
1957     //errorStr += mysql_error(sock);
1958     return -1;
1959 }
1960
1961 return 0;
1962 }
1963 //-----------------------------------------------------------------------------
1964 int MYSQL_STORE::GetMessageHdrs(vector<STG_MSG_HDR> * hdrsList, const string & login) const
1965 {
1966 MYSQL_RES *res;
1967 MYSQL_ROW row;
1968 MYSQL * sock;
1969 sprintf(qbuf,"SELECT * FROM messages WHERE login='%s'", login.c_str());
1970     
1971 if(MysqlGetQuery(qbuf,sock))
1972 {
1973     errorStr = "Couldn't GetMessageHdrs:\n";
1974     errorStr += mysql_error(sock);
1975     mysql_close(sock);
1976     return -1;
1977 }
1978
1979 if (!(res=mysql_store_result(sock)))
1980 {
1981     errorStr = "Couldn't GetMessageHdrs:\n";
1982     errorStr += mysql_error(sock);
1983     mysql_close(sock);
1984     return -1;
1985 }
1986
1987 unsigned int i, num_rows =  mysql_num_rows(res);
1988 long long int unsigned id = 0;
1989
1990 for (i=0; i<num_rows; i++)
1991 {
1992     row = mysql_fetch_row(res);
1993     if (str2x(row[1], id))
1994         continue;
1995     
1996     STG_MSG_HDR hdr;
1997     if (row[2]) 
1998         if(str2x(row[2], hdr.type))
1999             continue;
2000
2001     if (row[3])
2002         if(str2x(row[3], hdr.lastSendTime))
2003             continue;
2004
2005     if (row[4])
2006         if(str2x(row[4], hdr.creationTime))
2007             continue;
2008
2009     if (row[5])
2010         if(str2x(row[5], hdr.showTime))
2011             continue;
2012
2013     if (row[6])
2014         if(str2x(row[6], hdr.repeat))
2015             continue;
2016
2017     if (row[7])
2018         if(str2x(row[7], hdr.repeatPeriod))
2019             continue;
2020
2021     hdr.id = id;
2022     hdrsList->push_back(hdr);
2023 }
2024
2025 mysql_free_result(res);
2026 mysql_close(sock);
2027 return 0;
2028 }
2029 //-----------------------------------------------------------------------------
2030
2031 int MYSQL_STORE::MysqlSetQuery(const char * Query) const {
2032
2033     MYSQL * sock;
2034     int ret=MysqlGetQuery(Query,sock);
2035     mysql_close(sock);
2036     return ret;
2037 }
2038 //-----------------------------------------------------------------------------
2039 int  MYSQL_STORE::MysqlGetQuery(const char * Query,MYSQL * & sock) const {
2040     if (!(sock=MysqlConnect())) {
2041         return -1;
2042     }
2043     return   MysqlQuery(Query,sock);
2044 }
2045 //-----------------------------------------------------------------------------
2046 MYSQL *  MYSQL_STORE::MysqlConnect() const {
2047     MYSQL * sock;
2048     if ( !(sock=mysql_init(NULL)) ){
2049         errorStr= "mysql init susck\n";
2050         return NULL;
2051     }
2052     if (!(sock = mysql_real_connect(sock,storeSettings.GetDBHost().c_str(),
2053             storeSettings.GetDBUser().c_str(),storeSettings.GetDBPassword().c_str(),
2054             0,0,NULL,0)))
2055         {
2056             errorStr = "Couldn't connect to mysql engine! With error:\n";
2057             errorStr += mysql_error(sock);
2058             return NULL;
2059         }
2060     else{
2061          if(mysql_select_db(sock, storeSettings.GetDBName().c_str())){
2062              errorStr = "Database lost !\n";
2063              return NULL;
2064          }
2065     }
2066     return sock;
2067 }
2068 //-----------------------------------------------------------------------------