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