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