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