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