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