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