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