]> git.stg.codes - stg.git/blob - projects/stargazer/plugins/store/mysql/mysql_store.cpp
Fix the STG-MIB
[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 memset(pass, 0, sizeof(pass));
1277 memset(password, 0, sizeof(password));
1278 memset(passwordE, 0, sizeof(passwordE));
1279
1280 string p;
1281 MYSQL_RES *res;
1282 MYSQL_ROW row;
1283 MYSQL * sock;
1284 sprintf(qbuf,"SELECT * FROM admins WHERE login='%s' LIMIT 1", login.c_str());
1285     
1286 if(MysqlGetQuery(qbuf,sock))
1287 {
1288     errorStr = "Couldn't restore admin:\n";
1289     errorStr += mysql_error(sock);
1290     mysql_close(sock);
1291     return -1;
1292 }
1293
1294 if (!(res=mysql_store_result(sock)))
1295 {
1296     errorStr = "Couldn't restore admin:\n";
1297     errorStr += mysql_error(sock);
1298     mysql_close(sock);
1299     return -1;
1300 }
1301
1302 if ( mysql_num_rows(res) == 0)
1303 {
1304     mysql_free_result(res);
1305     errorStr = "Couldn't restore admin as couldn't found him in table.\n";
1306     mysql_close(sock);
1307     return -1;
1308 }
1309   
1310 row = mysql_fetch_row(res);
1311
1312 p = row[1];
1313 int a;
1314
1315 if(p.length() == 0)
1316 {
1317     mysql_free_result(res);
1318     errorStr = "Error in parameter password";
1319     mysql_close(sock);
1320     return -1;
1321 }
1322
1323 memset(passwordE, 0, sizeof(passwordE));
1324 strncpy(passwordE, p.c_str(), 2*ADM_PASSWD_LEN);
1325
1326 memset(pass, 0, sizeof(pass));
1327
1328 if (passwordE[0] != 0)
1329     {
1330     Decode21(pass, passwordE);
1331     EnDecodeInit(adm_enc_passwd, strlen(adm_enc_passwd), &ctx);
1332
1333     for (int i = 0; i < ADM_PASSWD_LEN/8; i++)
1334         {
1335         DecodeString(password + 8*i, pass + 8*i, &ctx);
1336         }
1337     }
1338 else
1339     {
1340     password[0] = 0;
1341     }
1342
1343 ac->password = password;
1344
1345 if (GetInt(row[2], &a, 0) == 0) 
1346     ac->priv.userConf = a;
1347 else
1348     {
1349     mysql_free_result(res);
1350     errorStr = "Error in parameter ChgConf";
1351     mysql_close(sock);
1352     return -1;
1353     }
1354
1355 if (GetInt(row[3], &a, 0) == 0) 
1356     ac->priv.userPasswd = a;
1357 else
1358     {
1359     mysql_free_result(res);
1360     errorStr = "Error in parameter ChgPassword";
1361     mysql_close(sock);
1362     return -1;
1363     }
1364
1365 if (GetInt(row[4], &a, 0) == 0) 
1366     ac->priv.userStat = a;
1367 else
1368     {
1369     mysql_free_result(res);
1370     errorStr = "Error in parameter ChgStat";
1371     mysql_close(sock);
1372     return -1;
1373     }
1374
1375 if (GetInt(row[5], &a, 0) == 0) 
1376     ac->priv.userCash = a;
1377 else
1378     {
1379     mysql_free_result(res);
1380     errorStr = "Error in parameter ChgCash";
1381     mysql_close(sock);
1382     return -1;
1383     }
1384
1385 if (GetInt(row[6], &a, 0) == 0) 
1386     ac->priv.userAddDel = a;
1387 else
1388     {
1389     mysql_free_result(res);
1390     errorStr = "Error in parameter UsrAddDel";
1391     mysql_close(sock);
1392     return -1;
1393     }
1394
1395 if (GetInt(row[7], &a, 0) == 0) 
1396     ac->priv.tariffChg = a;
1397 else
1398     {
1399     mysql_free_result(res);
1400     errorStr = "Error in parameter ChgTariff";
1401     mysql_close(sock);
1402     return -1;
1403     }
1404
1405 if (GetInt(row[8], &a, 0) == 0) 
1406     ac->priv.adminChg = a;
1407 else
1408     {
1409     mysql_free_result(res);
1410     errorStr = "Error in parameter ChgAdmin";
1411     mysql_close(sock);
1412     return -1;
1413     }
1414
1415 mysql_free_result(res);
1416 mysql_close(sock);
1417 return 0;
1418 }
1419 //-----------------------------------------------------------------------------
1420 int MYSQL_STORE::AddTariff(const string & name) const
1421 {
1422 sprintf(qbuf,"INSERT INTO tariffs SET name='%s'", name.c_str());
1423     
1424 if(MysqlSetQuery(qbuf))
1425 {
1426     errorStr = "Couldn't add tariff:\n";
1427 //    errorStr += mysql_error(sock);
1428     return -1;
1429 }
1430
1431 return 0;
1432 }
1433 //-----------------------------------------------------------------------------
1434 int MYSQL_STORE::DelTariff(const string & name) const
1435 {
1436 sprintf(qbuf,"DELETE FROM tariffs WHERE name='%s' LIMIT 1", name.c_str());
1437     
1438 if(MysqlSetQuery(qbuf))
1439 {
1440     errorStr = "Couldn't delete tariff: ";
1441 //    errorStr += mysql_error(sock);
1442     return -1;
1443 }
1444
1445 return 0;
1446 }
1447 //-----------------------------------------------------------------------------
1448 int MYSQL_STORE::RestoreTariff(TARIFF_DATA * td, const string & tariffName) const
1449 {
1450 MYSQL_RES *res;
1451 MYSQL_ROW row;
1452 MYSQL * sock;
1453 sprintf(qbuf,"SELECT * FROM tariffs WHERE name='%s' LIMIT 1", tariffName.c_str());
1454     
1455 if(MysqlGetQuery(qbuf,sock))
1456 {
1457     errorStr = "Couldn't restore Tariff:\n";
1458     errorStr += mysql_error(sock);
1459     mysql_close(sock);
1460     return -1;
1461 }
1462
1463 if (!(res=mysql_store_result(sock)))
1464 {
1465     errorStr = "Couldn't restore Tariff:\n";
1466     errorStr += mysql_error(sock);
1467     mysql_close(sock);
1468     return -1;
1469 }
1470
1471 string str;
1472 td->tariffConf.name = tariffName;
1473
1474 row = mysql_fetch_row(res);
1475
1476 string param;
1477 for (int i = 0; i<DIR_NUM; i++)
1478     {
1479     strprintf(&param, "Time%d", i);
1480     str = row[6+i*8];
1481     if (str.length() == 0)
1482         {
1483         mysql_free_result(res);
1484         errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
1485         mysql_close(sock);
1486         return -1;
1487         }
1488
1489     ParseTariffTimeStr(str.c_str(), 
1490                        td->dirPrice[i].hDay, 
1491                        td->dirPrice[i].mDay, 
1492                        td->dirPrice[i].hNight, 
1493                        td->dirPrice[i].mNight);
1494
1495     strprintf(&param, "PriceDayA%d", i);
1496     if (GetDouble(row[1+i*8], &td->dirPrice[i].priceDayA, 0.0) < 0)
1497         {
1498         mysql_free_result(res);
1499         errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
1500         mysql_close(sock);
1501         return -1;
1502         }
1503     td->dirPrice[i].priceDayA /= (1024*1024);
1504
1505     strprintf(&param, "PriceDayB%d", i);
1506     if (GetDouble(row[2+i*8], &td->dirPrice[i].priceDayB, 0.0) < 0)
1507         {
1508         mysql_free_result(res);
1509         errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
1510         mysql_close(sock);
1511         return -1;
1512         }
1513     td->dirPrice[i].priceDayB /= (1024*1024);
1514
1515     strprintf(&param, "PriceNightA%d", i);
1516     if (GetDouble(row[3+i*8], &td->dirPrice[i].priceNightA, 0.0) < 0)
1517         {
1518         mysql_free_result(res);
1519         errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
1520         mysql_close(sock);
1521         return -1;
1522         }
1523     td->dirPrice[i].priceNightA /= (1024*1024);
1524
1525     strprintf(&param, "PriceNightB%d", i);
1526     if (GetDouble(row[4+i*8], &td->dirPrice[i].priceNightB, 0.0) < 0)
1527         {
1528         mysql_free_result(res);
1529         errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
1530         mysql_close(sock);
1531         return -1;
1532         }
1533     td->dirPrice[i].priceNightB /= (1024*1024);
1534
1535     strprintf(&param, "Threshold%d", i);
1536     if (GetInt(row[5+i*8], &td->dirPrice[i].threshold, 0) < 0)
1537         {
1538         mysql_free_result(res);
1539         errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
1540         mysql_close(sock);
1541         return -1;
1542         }
1543
1544     strprintf(&param, "SinglePrice%d", i);
1545     if (GetInt(row[8+i*8], &td->dirPrice[i].singlePrice, 0) < 0)
1546         {
1547         mysql_free_result(res);
1548         errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
1549         mysql_close(sock);
1550         return -1;
1551         }
1552
1553     strprintf(&param, "NoDiscount%d", i);
1554     if (GetInt(row[7+i*8], &td->dirPrice[i].noDiscount, 0) < 0)
1555         {
1556         mysql_free_result(res);
1557         errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
1558         mysql_close(sock);
1559         return -1;
1560         }
1561     }//main for
1562
1563 if (GetDouble(row[2+8*DIR_NUM], &td->tariffConf.fee, 0.0) < 0)
1564     {
1565     mysql_free_result(res);
1566     errorStr = "Cannot read tariff " + tariffName + ". Parameter Fee";
1567     mysql_close(sock);
1568     return -1;
1569     }
1570
1571 if (GetDouble(row[3+8*DIR_NUM], &td->tariffConf.free, 0.0) < 0)
1572     {
1573     mysql_free_result(res);
1574     errorStr = "Cannot read tariff " + tariffName + ". Parameter Free";
1575     mysql_close(sock);
1576     return -1;
1577     }
1578
1579 if (GetDouble(row[1+8*DIR_NUM], &td->tariffConf.passiveCost, 0.0) < 0)
1580     {
1581     mysql_free_result(res);
1582     errorStr = "Cannot read tariff " + tariffName + ". Parameter PassiveCost";
1583     mysql_close(sock);
1584     return -1;
1585     }
1586
1587     str = row[4+8*DIR_NUM];
1588     param = "TraffType";
1589     
1590     if (str.length() == 0)
1591         {
1592         mysql_free_result(res);
1593         errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
1594         mysql_close(sock);
1595         return -1;
1596         }
1597
1598 if (!strcasecmp(str.c_str(), "up"))
1599     td->tariffConf.traffType = TRAFF_UP;
1600 else
1601     if (!strcasecmp(str.c_str(), "down"))
1602         td->tariffConf.traffType = TRAFF_DOWN;
1603     else
1604         if (!strcasecmp(str.c_str(), "up+down"))
1605             td->tariffConf.traffType = TRAFF_UP_DOWN;
1606         else
1607             if (!strcasecmp(str.c_str(), "max"))
1608                 td->tariffConf.traffType = TRAFF_MAX;
1609             else
1610                 {
1611                 mysql_free_result(res);
1612                 errorStr = "Cannot read tariff " + tariffName + ". Parameter TraffType incorrect";
1613                 mysql_close(sock);
1614                 return -1;
1615                 }
1616
1617 mysql_free_result(res);
1618 mysql_close(sock);
1619 return 0;
1620 }
1621 //-----------------------------------------------------------------------------
1622 int MYSQL_STORE::SaveTariff(const TARIFF_DATA & td, const string & tariffName) const
1623 {
1624 string param;
1625
1626 string res="UPDATE tariffs SET";
1627
1628 for (int i = 0; i < DIR_NUM; i++)
1629     {
1630     strprintf(&param, " PriceDayA%d=%f,", i, 
1631         td.dirPrice[i].priceDayA * pt_mega);
1632     res += param;
1633
1634     strprintf(&param, " PriceDayB%d=%f,", i, 
1635         td.dirPrice[i].priceDayB * pt_mega);        
1636     res += param;
1637         
1638     strprintf(&param, " PriceNightA%d=%f,", i,
1639         td.dirPrice[i].priceNightA * pt_mega);
1640     res += param;
1641
1642     strprintf(&param, " PriceNightB%d=%f,", i, 
1643         td.dirPrice[i].priceNightB * pt_mega);
1644     res += param;
1645         
1646     strprintf(&param, " Threshold%d=%d,", i, 
1647         td.dirPrice[i].threshold);
1648     res += param;
1649
1650     string s;
1651     strprintf(&param, " Time%d", i);
1652
1653     strprintf(&s, "%0d:%0d-%0d:%0d", 
1654             td.dirPrice[i].hDay,
1655             td.dirPrice[i].mDay,
1656             td.dirPrice[i].hNight,
1657             td.dirPrice[i].mNight);
1658
1659     res += (param + "='" + s + "',");
1660
1661     strprintf(&param, " NoDiscount%d=%d,", i, 
1662         td.dirPrice[i].noDiscount);
1663     res += param;
1664
1665     strprintf(&param, " SinglePrice%d=%d,", i, 
1666         td.dirPrice[i].singlePrice);
1667     res += param;
1668     }
1669
1670 strprintf(&param, " PassiveCost=%f,", td.tariffConf.passiveCost);
1671 res += param;
1672
1673 strprintf(&param, " Fee=%f,", td.tariffConf.fee);
1674 res += param;
1675
1676 strprintf(&param, " Free=%f,", td.tariffConf.free);
1677 res += param;
1678
1679 switch (td.tariffConf.traffType)
1680     {
1681     case TRAFF_UP:
1682         res += " TraffType='up'";
1683         break;
1684     case TRAFF_DOWN:
1685         res += " TraffType='down'";
1686         break;
1687     case TRAFF_UP_DOWN:
1688         res += " TraffType='up+down'";
1689         break;
1690     case TRAFF_MAX:
1691         res += " TraffType='max'";
1692         break;
1693     }
1694 strprintf(&param, " WHERE name='%s' LIMIT 1", tariffName.c_str());
1695 res += param;
1696
1697 if(MysqlSetQuery(res.c_str()))
1698 {
1699     errorStr = "Couldn't save admin:\n";
1700     //errorStr += mysql_error(sock);
1701     return -1;
1702 }
1703
1704 return 0;
1705 }
1706 //-----------------------------------------------------------------------------
1707 int MYSQL_STORE::WriteDetailedStat(const map<IP_DIR_PAIR, STAT_NODE> & statTree, 
1708                                    time_t lastStat, 
1709                                    const string & login) const
1710 {
1711 string res, stTime, endTime, tempStr;
1712 time_t t;
1713 tm * lt;
1714
1715 t = time(NULL);
1716 lt = localtime(&t);
1717
1718 if (lt->tm_hour == 0 && lt->tm_min <= 5)
1719     {
1720         t -= 3600 * 24;
1721         lt = localtime(&t);
1722     }
1723
1724 MYSQL_RES* result;
1725 MYSQL * sock;
1726 strprintf(&tempStr, "detailstat_%02d_%4d", lt->tm_mon+1, lt->tm_year+1900);
1727
1728 if (!(sock=MysqlConnect())){
1729     mysql_close(sock);
1730     return -1;
1731 }
1732
1733 if (!(result=mysql_list_tables(sock,tempStr.c_str() )))
1734 {
1735     errorStr = "Couldn't get table " + tempStr + ":\n";
1736     errorStr += mysql_error(sock);
1737     mysql_close(sock);
1738     return -1;
1739 }
1740
1741 unsigned int num_rows =  mysql_num_rows(result);
1742
1743 mysql_free_result(result);
1744
1745 if (num_rows < 1)
1746 {
1747     sprintf(qbuf,"CREATE TABLE detailstat_%02d_%4d (login VARCHAR(40) DEFAULT '',"\
1748         "day TINYINT DEFAULT 0,startTime TIME,endTime TIME,"\
1749         "IP VARCHAR(17) DEFAULT '',dir INT DEFAULT 0,"\
1750         "down BIGINT DEFAULT 0,up BIGINT DEFAULT 0, cash DOUBLE DEFAULT 0.0, INDEX (login), INDEX(dir), INDEX(day), INDEX(IP))",
1751     lt->tm_mon+1, lt->tm_year+1900);
1752     
1753     if(MysqlQuery(qbuf,sock))
1754     {
1755         errorStr = "Couldn't create WriteDetailedStat table:\n";
1756         errorStr += mysql_error(sock);
1757         mysql_close(sock);
1758         return -1;
1759     }
1760 }
1761
1762 struct tm * lt1;
1763 struct tm * lt2;
1764
1765 lt1 = localtime(&lastStat);
1766
1767 int h1, m1, s1;
1768 int h2, m2, s2;
1769
1770 h1 = lt1->tm_hour;
1771 m1 = lt1->tm_min;
1772 s1 = lt1->tm_sec;
1773
1774 lt2 = localtime(&t);
1775
1776 h2 = lt2->tm_hour;
1777 m2 = lt2->tm_min;
1778 s2 = lt2->tm_sec;
1779     
1780 strprintf(&stTime, "%02d:%02d:%02d", h1, m1, s1);
1781 strprintf(&endTime, "%02d:%02d:%02d", h2, m2, s2);
1782
1783 strprintf(&res,"INSERT INTO detailstat_%02d_%4d SET login='%s',"\
1784     "day=%d,startTime='%s',endTime='%s',", 
1785     lt->tm_mon+1, lt->tm_year+1900,
1786     login.c_str(),
1787     lt->tm_mday,
1788     stTime.c_str(),
1789     endTime.c_str()
1790     );
1791
1792 map<IP_DIR_PAIR, STAT_NODE>::const_iterator stIter;
1793 stIter = statTree.begin();
1794
1795 while (stIter != statTree.end())
1796     {
1797         strprintf(&tempStr,"IP='%s', dir=%d, down=%lld, up=%lld, cash=%f", 
1798                 inet_ntostring(stIter->first.ip).c_str(),
1799                 stIter->first.dir, 
1800                 stIter->second.down, 
1801                 stIter->second.up, 
1802                 stIter->second.cash
1803             );
1804     
1805         if( MysqlQuery((res+tempStr).c_str(),sock) )
1806         {
1807             errorStr = "Couldn't insert data in WriteDetailedStat:\n";
1808             errorStr += mysql_error(sock);
1809             mysql_close(sock);
1810             return -1;
1811         }
1812
1813         result=mysql_store_result(sock);
1814         if(result)
1815             mysql_free_result(result);
1816
1817         ++stIter;
1818     }
1819 mysql_close(sock);
1820 return 0;
1821 }
1822 //-----------------------------------------------------------------------------
1823 int MYSQL_STORE::AddMessage(STG_MSG * msg, const string & login) const
1824 {
1825 struct timeval tv;
1826
1827 gettimeofday(&tv, NULL);
1828
1829 msg->header.id = ((long long)tv.tv_sec) * 1000000 + ((long long)tv.tv_usec);
1830
1831 sprintf(qbuf,"INSERT INTO messages SET login='%s', id=%lld", 
1832     login.c_str(),
1833     (long long)msg->header.id
1834     );
1835     
1836 if(MysqlSetQuery(qbuf))
1837 {
1838     errorStr = "Couldn't add message:\n";
1839     //errorStr += mysql_error(sock);
1840     return -1;
1841 }
1842
1843 return EditMessage(*msg, login);
1844 }
1845 //-----------------------------------------------------------------------------
1846 int MYSQL_STORE::EditMessage(const STG_MSG & msg, const string & login) const
1847 {
1848 string res;
1849
1850 strprintf(&res,"UPDATE messages SET type=%d, lastSendTime=%u, creationTime=%u, "\
1851     "showTime=%u, stgRepeat=%d, repeatPeriod=%u, text='%s' "\
1852     "WHERE login='%s' AND id=%lld LIMIT 1", 
1853     msg.header.type,
1854     msg.header.lastSendTime,
1855     msg.header.creationTime,
1856     msg.header.showTime,
1857     msg.header.repeat,
1858     msg.header.repeatPeriod,
1859     (ReplaceStr(msg.text,badSyms,repSym)).c_str(),
1860     login.c_str(),
1861     (long long)msg.header.id
1862     );
1863
1864 if(MysqlSetQuery(res.c_str()))
1865 {
1866     errorStr = "Couldn't edit message:\n";
1867     //errorStr += mysql_error(sock);
1868     return -1;
1869 }
1870
1871 return 0;
1872 }
1873 //-----------------------------------------------------------------------------
1874 int MYSQL_STORE::GetMessage(uint64_t id, STG_MSG * msg, const string & login) const
1875 {
1876 MYSQL_RES *res;
1877 MYSQL_ROW row;
1878 MYSQL * sock;
1879
1880 sprintf(qbuf,"SELECT * FROM messages WHERE login='%s' AND id=%lld LIMIT 1",
1881     login.c_str(), id);
1882     
1883 if(MysqlGetQuery(qbuf,sock))
1884 {
1885     errorStr = "Couldn't GetMessage:\n";
1886     errorStr += mysql_error(sock);
1887     mysql_close(sock);
1888     return -1;
1889 }
1890
1891 if (!(res=mysql_store_result(sock)))
1892 {
1893     errorStr = "Couldn't GetMessage:\n";
1894     errorStr += mysql_error(sock);
1895     mysql_close(sock);
1896     return -1;
1897 }
1898
1899 row = mysql_fetch_row(res);
1900
1901 if(row[2]&&str2x(row[2], msg->header.type))
1902 {
1903     mysql_free_result(res);
1904     errorStr = "Invalid value in message header for user: " + login;
1905     mysql_close(sock);
1906     return -1;
1907 }
1908
1909 if(row[3] && str2x(row[3], msg->header.lastSendTime))
1910 {
1911     mysql_free_result(res);
1912     errorStr = "Invalid value in message header for user: " + login;
1913     mysql_close(sock);
1914     return -1;
1915 }
1916
1917 if(row[4] && str2x(row[4], msg->header.creationTime))
1918 {
1919     mysql_free_result(res);
1920     errorStr = "Invalid value in message header for user: " + login;
1921     mysql_close(sock);
1922     return -1;
1923 }
1924
1925 if(row[5] && str2x(row[5], msg->header.showTime))
1926 {
1927     mysql_free_result(res);
1928     errorStr = "Invalid value in message header for user: " + login;
1929     mysql_close(sock);
1930     return -1;
1931 }
1932
1933 if(row[6] && str2x(row[6], msg->header.repeat))
1934 {
1935     mysql_free_result(res);
1936     errorStr = "Invalid value in message header for user: " + login;
1937     mysql_close(sock);
1938     return -1;
1939 }
1940
1941 if(row[7] && str2x(row[7], msg->header.repeatPeriod))
1942 {
1943     mysql_free_result(res);
1944     errorStr = "Invalid value in message header for user: " + login;
1945     mysql_close(sock);
1946     return -1;
1947 }
1948
1949 msg->header.id = id;
1950 msg->text = row[8];
1951
1952 mysql_free_result(res);
1953 mysql_close(sock);
1954 return 0;
1955 }
1956 //-----------------------------------------------------------------------------
1957 int MYSQL_STORE::DelMessage(uint64_t id, const string & login) const
1958 {
1959 sprintf(qbuf,"DELETE FROM messages WHERE login='%s' AND id=%lld LIMIT 1", 
1960     login.c_str(),(long long)id);
1961     
1962 if(MysqlSetQuery(qbuf))
1963 {
1964     errorStr = "Couldn't delete Message:\n";
1965     //errorStr += mysql_error(sock);
1966     return -1;
1967 }
1968
1969 return 0;
1970 }
1971 //-----------------------------------------------------------------------------
1972 int MYSQL_STORE::GetMessageHdrs(vector<STG_MSG_HDR> * hdrsList, const string & login) const
1973 {
1974 MYSQL_RES *res;
1975 MYSQL_ROW row;
1976 MYSQL * sock;
1977 sprintf(qbuf,"SELECT * FROM messages WHERE login='%s'", login.c_str());
1978     
1979 if(MysqlGetQuery(qbuf,sock))
1980 {
1981     errorStr = "Couldn't GetMessageHdrs:\n";
1982     errorStr += mysql_error(sock);
1983     mysql_close(sock);
1984     return -1;
1985 }
1986
1987 if (!(res=mysql_store_result(sock)))
1988 {
1989     errorStr = "Couldn't GetMessageHdrs:\n";
1990     errorStr += mysql_error(sock);
1991     mysql_close(sock);
1992     return -1;
1993 }
1994
1995 unsigned int i, num_rows =  mysql_num_rows(res);
1996 long long int unsigned id = 0;
1997
1998 for (i=0; i<num_rows; i++)
1999 {
2000     row = mysql_fetch_row(res);
2001     if (str2x(row[1], id))
2002         continue;
2003     
2004     STG_MSG_HDR hdr;
2005     if (row[2]) 
2006         if(str2x(row[2], hdr.type))
2007             continue;
2008
2009     if (row[3])
2010         if(str2x(row[3], hdr.lastSendTime))
2011             continue;
2012
2013     if (row[4])
2014         if(str2x(row[4], hdr.creationTime))
2015             continue;
2016
2017     if (row[5])
2018         if(str2x(row[5], hdr.showTime))
2019             continue;
2020
2021     if (row[6])
2022         if(str2x(row[6], hdr.repeat))
2023             continue;
2024
2025     if (row[7])
2026         if(str2x(row[7], hdr.repeatPeriod))
2027             continue;
2028
2029     hdr.id = id;
2030     hdrsList->push_back(hdr);
2031 }
2032
2033 mysql_free_result(res);
2034 mysql_close(sock);
2035 return 0;
2036 }
2037 //-----------------------------------------------------------------------------
2038
2039 int MYSQL_STORE::MysqlSetQuery(const char * Query) const {
2040
2041     MYSQL * sock;
2042     int ret=MysqlGetQuery(Query,sock);
2043     mysql_close(sock);
2044     return ret;
2045 }
2046 //-----------------------------------------------------------------------------
2047 int  MYSQL_STORE::MysqlGetQuery(const char * Query,MYSQL * & sock) const {
2048     if (!(sock=MysqlConnect())) {
2049         return -1;
2050     }
2051     return   MysqlQuery(Query,sock);
2052 }
2053 //-----------------------------------------------------------------------------
2054 MYSQL *  MYSQL_STORE::MysqlConnect() const {
2055     MYSQL * sock;
2056     if ( !(sock=mysql_init(NULL)) ){
2057         errorStr= "mysql init susck\n";
2058         return NULL;
2059     }
2060     if (!(sock = mysql_real_connect(sock,storeSettings.GetDBHost().c_str(),
2061             storeSettings.GetDBUser().c_str(),storeSettings.GetDBPassword().c_str(),
2062             0,0,NULL,0)))
2063         {
2064             errorStr = "Couldn't connect to mysql engine! With error:\n";
2065             errorStr += mysql_error(sock);
2066             return NULL;
2067         }
2068     else{
2069          if(mysql_select_db(sock, storeSettings.GetDBName().c_str())){
2070              errorStr = "Database lost !\n";
2071              return NULL;
2072          }
2073     }
2074     return sock;
2075 }
2076 //-----------------------------------------------------------------------------