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