]> git.stg.codes - stg.git/blobdiff - projects/stargazer/plugins/store/mysql/mysql_store.cpp
Add tariff change policy description.
[stg.git] / projects / stargazer / plugins / store / mysql / mysql_store.cpp
index e52c055d8925d7676f2e9e700fb01e2e8ffdb0b4..cef72671b1c5e6b68b4b0d88c5e22b65d16d5ebd 100644 (file)
@@ -2,36 +2,39 @@
 #include <cerrno>
 #include <cstdio>
 #include <cstdlib>
 #include <cerrno>
 #include <cstdio>
 #include <cstdlib>
-#include <string>
 #include <algorithm>
 
 #include <mysql.h>
 #include <errmsg.h>
 
 #include <algorithm>
 
 #include <mysql.h>
 #include <errmsg.h>
 
+#include "stg/common.h"
 #include "stg/user_ips.h"
 #include "stg/user_conf.h"
 #include "stg/user_stat.h"
 #include "stg/blowfish.h"
 #include "stg/plugin_creator.h"
 #include "stg/user_ips.h"
 #include "stg/user_conf.h"
 #include "stg/user_stat.h"
 #include "stg/blowfish.h"
 #include "stg/plugin_creator.h"
+#include "stg/logger.h"
 #include "mysql_store.h"
 
 #define adm_enc_passwd "cjeifY8m3"
 #include "mysql_store.h"
 
 #define adm_enc_passwd "cjeifY8m3"
-char qbuf[4096];
 
 
-using namespace std;
+namespace
+{
+char qbuf[4096];
 
 const int pt_mega = 1024 * 1024;
 
 const int pt_mega = 1024 * 1024;
-const string badSyms = "'`";
+const std::string badSyms = "'`";
 const char repSym = '\"';
 const int RepitTimes = 3;
 
 const char repSym = '\"';
 const int RepitTimes = 3;
 
-int GetInt(const string & str, int * val, int defaultVal)
+template <typename T>
+int GetInt(const std::string & str, T * val, T defaultVal = T())
 {
     char *res;
 {
     char *res;
-    
-    *val = strtol(str.c_str(), &res, 10);
-    
-    if (*res != 0) 
+
+    *val = static_cast<T>(strtoll(str.c_str(), &res, 10));
+
+    if (*res != 0)
     {
         *val = defaultVal; //Error!
         return EINVAL;
     {
         *val = defaultVal; //Error!
         return EINVAL;
@@ -40,13 +43,13 @@ int GetInt(const string & str, int * val, int defaultVal)
     return 0;
 }
 
     return 0;
 }
 
-int GetDouble(const string & str, double * val, double defaultVal)
+int GetDouble(const std::string & str, double * val, double defaultVal)
 {
     char *res;
 {
     char *res;
-    
+
     *val = strtod(str.c_str(), &res);
     *val = strtod(str.c_str(), &res);
-    
-    if (*res != 0) 
+
+    if (*res != 0)
     {
         *val = defaultVal; //Error!
         return EINVAL;
     {
         *val = defaultVal; //Error!
         return EINVAL;
@@ -55,13 +58,13 @@ int GetDouble(const string & str, double * val, double defaultVal)
     return 0;
 }
 
     return 0;
 }
 
-int GetTime(const string & str, time_t * val, time_t defaultVal)
+int GetTime(const std::string & str, time_t * val, time_t defaultVal)
 {
     char *res;
 {
     char *res;
-    
+
     *val = strtol(str.c_str(), &res, 10);
     *val = strtol(str.c_str(), &res, 10);
-    
-    if (*res != 0) 
+
+    if (*res != 0)
     {
         *val = defaultVal; //Error!
         return EINVAL;
     {
         *val = defaultVal; //Error!
         return EINVAL;
@@ -71,32 +74,35 @@ int GetTime(const string & str, time_t * val, time_t defaultVal)
 }
 
 //-----------------------------------------------------------------------------
 }
 
 //-----------------------------------------------------------------------------
-string ReplaceStr(string source, const string symlist, const char chgsym)
+std::string ReplaceStr(std::string source, const std::string & symlist, const char chgsym)
 {
 {
-    string::size_type pos=0;
+    std::string::size_type pos=0;
 
 
-    while( (pos = source.find_first_of(symlist,pos)) != string::npos)
+    while( (pos = source.find_first_of(symlist,pos)) != std::string::npos)
         source.replace(pos, 1,1, chgsym);
 
     return source;
 }
 
         source.replace(pos, 1,1, chgsym);
 
     return source;
 }
 
-int GetULongLongInt(const string & str, uint64_t * val, uint64_t defaultVal)
+int GetULongLongInt(const std::string & str, uint64_t * val, uint64_t defaultVal)
 {
     char *res;
 {
     char *res;
-    
+
     *val = strtoull(str.c_str(), &res, 10);
     *val = strtoull(str.c_str(), &res, 10);
-    
-    if (*res != 0) 
+
+    if (*res != 0)
     {
         *val = defaultVal; //Error!
         return EINVAL;
     }
 
     return 0;
     {
         *val = defaultVal; //Error!
         return EINVAL;
     }
 
     return 0;
-} 
+}
 
 PLUGIN_CREATOR<MYSQL_STORE> msc;
 
 PLUGIN_CREATOR<MYSQL_STORE> msc;
+}
+
+extern "C" STORE * GetStore();
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -106,28 +112,23 @@ return msc.GetPlugin();
 }
 //-----------------------------------------------------------------------------
 MYSQL_STORE_SETTINGS::MYSQL_STORE_SETTINGS()
 }
 //-----------------------------------------------------------------------------
 MYSQL_STORE_SETTINGS::MYSQL_STORE_SETTINGS()
-    : settings(NULL),
-      errorStr(),
-      dbUser(),
-      dbPass(),
-      dbName(),
-      dbHost()
+    : settings(NULL)
 {
 }
 //-----------------------------------------------------------------------------
 {
 }
 //-----------------------------------------------------------------------------
-int MYSQL_STORE_SETTINGS::ParseParam(const vector<PARAM_VALUE> & moduleParams, 
-                        const string & name, string & result)
+int MYSQL_STORE_SETTINGS::ParseParam(const std::vector<PARAM_VALUE> & moduleParams,
+                                     const std::string & name, std::string & result)
 {
 PARAM_VALUE pv;
 pv.param = name;
 {
 PARAM_VALUE pv;
 pv.param = name;
-vector<PARAM_VALUE>::const_iterator pvi;
+std::vector<PARAM_VALUE>::const_iterator pvi;
 pvi = find(moduleParams.begin(), moduleParams.end(), pv);
 pvi = find(moduleParams.begin(), moduleParams.end(), pv);
-if (pvi == moduleParams.end())
+if (pvi == moduleParams.end() || pvi->value.empty())
     {
     errorStr = "Parameter \'" + name + "\' not found.";
     return -1;
     }
     {
     errorStr = "Parameter \'" + name + "\' not found.";
     return -1;
     }
-    
+
 result = pvi->value[0];
 
 return 0;
 result = pvi->value[0];
 
 return 0;
@@ -154,20 +155,19 @@ return 0;
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 MYSQL_STORE::MYSQL_STORE()
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 MYSQL_STORE::MYSQL_STORE()
-    : errorStr(),
-      version("mysql_store v.0.67"),
-      storeSettings(),
-      settings()
+    : version("mysql_store v.0.67"),
+      schemaVersion(0),
+      logger(GetPluginLogger(GetStgLogger(), "store_mysql"))
 {
 {
-};
+}
 //-----------------------------------------------------------------------------
 int    MYSQL_STORE::MysqlQuery(const char* sQuery,MYSQL * sock) const
 {
 //-----------------------------------------------------------------------------
 int    MYSQL_STORE::MysqlQuery(const char* sQuery,MYSQL * sock) const
 {
-    int ret,i;
+    int ret;
 
     if( (ret = mysql_query(sock,sQuery)) )
     {
 
     if( (ret = mysql_query(sock,sQuery)) )
     {
-        for(i=0; i<RepitTimes; i++)
+        for(int i=0; i<RepitTimes; i++)
         {
             if( (ret = mysql_query(sock,sQuery)) )
                 ;//need to send error result
         {
             if( (ret = mysql_query(sock,sQuery)) )
                 ;//need to send error result
@@ -175,7 +175,7 @@ int    MYSQL_STORE::MysqlQuery(const char* sQuery,MYSQL * sock) const
                 return 0;
         }
     }
                 return 0;
         }
     }
-    
+
     return ret;
 }
 //-----------------------------------------------------------------------------
     return ret;
 }
 //-----------------------------------------------------------------------------
@@ -185,7 +185,6 @@ int MYSQL_STORE::ParseSettings()
 {
 int ret = storeSettings.ParseSettings(settings);
 MYSQL mysql;
 {
 int ret = storeSettings.ParseSettings(settings);
 MYSQL mysql;
-MYSQL * sock;
 mysql_init(&mysql);
 if (ret)
     errorStr = storeSettings.GetStrError();
 mysql_init(&mysql);
 if (ret)
     errorStr = storeSettings.GetStrError();
@@ -196,7 +195,7 @@ else
         errorStr = "Database password must be not empty. Please read Manual.";
         return -1;
     }
         errorStr = "Database password must be not empty. Please read Manual.";
         return -1;
     }
-    
+    MYSQL * sock;
     if (!(sock = mysql_real_connect(&mysql,storeSettings.GetDBHost().c_str(),
             storeSettings.GetDBUser().c_str(),storeSettings.GetDBPassword().c_str(),
             0,0,NULL,0)))
     if (!(sock = mysql_real_connect(&mysql,storeSettings.GetDBHost().c_str(),
             storeSettings.GetDBUser().c_str(),storeSettings.GetDBPassword().c_str(),
             0,0,NULL,0)))
@@ -210,8 +209,8 @@ else
     {
          if(mysql_select_db(sock, storeSettings.GetDBName().c_str()))
          {
     {
          if(mysql_select_db(sock, storeSettings.GetDBName().c_str()))
          {
-             string res = "CREATE DATABASE " + storeSettings.GetDBName();
-            
+             std::string res = "CREATE DATABASE " + storeSettings.GetDBName();
+
             if(MysqlQuery(res.c_str(),sock))
             {
                 errorStr = "Couldn't create database! With error:\n";
             if(MysqlQuery(res.c_str(),sock))
             {
                 errorStr = "Couldn't create database! With error:\n";
@@ -223,24 +222,31 @@ else
             {
                  if(mysql_select_db(sock, storeSettings.GetDBName().c_str()))
                  {
             {
                  if(mysql_select_db(sock, storeSettings.GetDBName().c_str()))
                  {
-                    errorStr = "Couldn't select database! With error:\n";
-                    errorStr += mysql_error(sock);
-                    mysql_close(sock);
-                    ret = -1;
+                     errorStr = "Couldn't select database! With error:\n";
+                     errorStr += mysql_error(sock);
+                     mysql_close(sock);
+                     ret = -1;
                  }
                  }
-                 ret = CheckAllTables(sock);
+                 else
+                     ret = CheckAllTables(sock);
             }
             }
-         }
-         else
-             ret = CheckAllTables(sock);
-         mysql_close(sock);
+        }
+        else
+        {
+            ret = CheckAllTables(sock);
+        }
+        if (!ret)
+        {
+            logger("MYSQL_STORE: Current DB schema version: %d", schemaVersion);
+            MakeUpdates(sock);
+        }
+        mysql_close(sock);
     }
     }
-    
 }
 return ret;
 }
 //-----------------------------------------------------------------------------
 }
 return ret;
 }
 //-----------------------------------------------------------------------------
-bool MYSQL_STORE::IsTablePresent(const string & str,MYSQL * sock)
+bool MYSQL_STORE::IsTablePresent(const std::string & str,MYSQL * sock)
 {
 MYSQL_RES* result;
 
 {
 MYSQL_RES* result;
 
@@ -252,16 +258,53 @@ if (!(result=mysql_list_tables(sock,str.c_str() )))
     return -1;
 }
 
     return -1;
 }
 
-unsigned int num_rows =  mysql_num_rows(result);
+my_ulonglong num_rows =  mysql_num_rows(result);
 
 if(result)
     mysql_free_result(result);
 
 
 if(result)
     mysql_free_result(result);
 
-return (num_rows == 1);
+return num_rows == 1;
 }
 //-----------------------------------------------------------------------------
 int MYSQL_STORE::CheckAllTables(MYSQL * sock)
 {
 }
 //-----------------------------------------------------------------------------
 int MYSQL_STORE::CheckAllTables(MYSQL * sock)
 {
+//info-------------------------------------------------------------------------
+if(!IsTablePresent("info",sock))
+{
+    sprintf(qbuf,"CREATE TABLE info (version INTEGER NOT NULL)");
+
+    if(MysqlQuery(qbuf,sock))
+        {
+        errorStr = "Couldn't create info table With error:\n";
+        errorStr += mysql_error(sock);
+        mysql_close(sock);
+        return -1;
+        }
+
+    sprintf(qbuf,"INSERT INTO info SET version=0");
+
+    if(MysqlQuery(qbuf,sock))
+        {
+        errorStr = "Couldn't write default version. With error:\n";
+        errorStr += mysql_error(sock);
+        mysql_close(sock);
+        return -1;
+        }
+    schemaVersion = 0;
+}
+else
+{
+    std::vector<std::string> info;
+    if (GetAllParams(&info, "info", "version"))
+        schemaVersion = 0;
+    else
+    {
+        if (info.empty())
+            schemaVersion = 0;
+        else
+            GetInt(info.front(), &schemaVersion, 0);
+    }
+}
 //admins-----------------------------------------------------------------------
 if(!IsTablePresent("admins",sock))
 {
 //admins-----------------------------------------------------------------------
 if(!IsTablePresent("admins",sock))
 {
@@ -270,7 +313,7 @@ if(!IsTablePresent("admins",sock))
         "ChgPassword TINYINT DEFAULT 0,ChgStat TINYINT DEFAULT 0,"\
         "ChgCash TINYINT DEFAULT 0,UsrAddDel TINYINT DEFAULT 0,"\
         "ChgTariff TINYINT DEFAULT 0,ChgAdmin TINYINT DEFAULT 0)");
         "ChgPassword TINYINT DEFAULT 0,ChgStat TINYINT DEFAULT 0,"\
         "ChgCash TINYINT DEFAULT 0,UsrAddDel TINYINT DEFAULT 0,"\
         "ChgTariff TINYINT DEFAULT 0,ChgAdmin TINYINT DEFAULT 0)");
-    
+
     if(MysqlQuery(qbuf,sock))
     {
         errorStr = "Couldn't create admin table list With error:\n";
     if(MysqlQuery(qbuf,sock))
     {
         errorStr = "Couldn't create admin table list With error:\n";
@@ -282,7 +325,7 @@ if(!IsTablePresent("admins",sock))
     sprintf(qbuf,"INSERT INTO admins SET login='admin',"\
         "password='geahonjehjfofnhammefahbbbfbmpkmkmmefahbbbfbmpkmkmmefahbbbfbmpkmkaa',"\
         "ChgConf=1,ChgPassword=1,ChgStat=1,ChgCash=1,UsrAddDel=1,ChgTariff=1,ChgAdmin=1");
     sprintf(qbuf,"INSERT INTO admins SET login='admin',"\
         "password='geahonjehjfofnhammefahbbbfbmpkmkmmefahbbbfbmpkmkmmefahbbbfbmpkmkaa',"\
         "ChgConf=1,ChgPassword=1,ChgStat=1,ChgCash=1,UsrAddDel=1,ChgTariff=1,ChgAdmin=1");
-    
+
     if(MysqlQuery(qbuf,sock))
     {
         errorStr = "Couldn't create default admin. With error:\n";
     if(MysqlQuery(qbuf,sock))
     {
         errorStr = "Couldn't create default admin. With error:\n";
@@ -293,41 +336,44 @@ if(!IsTablePresent("admins",sock))
 }
 
 //tariffs-----------------------------------------------------------------------
 }
 
 //tariffs-----------------------------------------------------------------------
-string param, res;
+std::string param, res;
 if(!IsTablePresent("tariffs",sock))
 {
     res = "CREATE TABLE tariffs (name VARCHAR(40) DEFAULT '' PRIMARY KEY,";
 if(!IsTablePresent("tariffs",sock))
 {
     res = "CREATE TABLE tariffs (name VARCHAR(40) DEFAULT '' PRIMARY KEY,";
-        
+
     for (int i = 0; i < DIR_NUM; i++)
         {
     for (int i = 0; i < DIR_NUM; i++)
         {
-        strprintf(&param, " PriceDayA%d DOUBLE DEFAULT 0.0,", i); 
+        strprintf(&param, " PriceDayA%d DOUBLE DEFAULT 0.0,", i);
         res += param;
         res += param;
-    
+
         strprintf(&param, " PriceDayB%d DOUBLE DEFAULT 0.0,", i);
         res += param;
         strprintf(&param, " PriceDayB%d DOUBLE DEFAULT 0.0,", i);
         res += param;
-            
+
         strprintf(&param, " PriceNightA%d DOUBLE DEFAULT 0.0,", i);
         res += param;
         strprintf(&param, " PriceNightA%d DOUBLE DEFAULT 0.0,", i);
         res += param;
-    
+
         strprintf(&param, " PriceNightB%d DOUBLE DEFAULT 0.0,", i);
         res += param;
         strprintf(&param, " PriceNightB%d DOUBLE DEFAULT 0.0,", i);
         res += param;
-            
+
         strprintf(&param, " Threshold%d INT DEFAULT 0,", i);
         res += param;
         strprintf(&param, " Threshold%d INT DEFAULT 0,", i);
         res += param;
-    
+
         strprintf(&param, " Time%d VARCHAR(15) DEFAULT '0:0-0:0',", i);
         res += param;
         strprintf(&param, " Time%d VARCHAR(15) DEFAULT '0:0-0:0',", i);
         res += param;
-    
+
         strprintf(&param, " NoDiscount%d INT DEFAULT 0,", i);
         res += param;
         strprintf(&param, " NoDiscount%d INT DEFAULT 0,", i);
         res += param;
-    
+
         strprintf(&param, " SinglePrice%d INT DEFAULT 0,", i);
         res += param;
         }
         strprintf(&param, " SinglePrice%d INT DEFAULT 0,", i);
         res += param;
         }
-    
-    res += "PassiveCost DOUBLE DEFAULT 0.0, Fee DOUBLE DEFAULT 0.0,"\
-        "Free DOUBLE DEFAULT 0.0, TraffType VARCHAR(10) DEFAULT '')";
-    
+
+    res += "PassiveCost DOUBLE DEFAULT 0.0, Fee DOUBLE DEFAULT 0.0,"
+        "Free DOUBLE DEFAULT 0.0, TraffType VARCHAR(10) DEFAULT '',"
+        "period VARCHAR(32) NOT NULL DEFAULT 'month',"
+        "change_policy VARCHAR(32) NOT NULL DEFAULT 'allow',"
+        "change_policy_timeout TIMESTAMP NOT NULL DEFAULT 0)";
+
     if(MysqlQuery(res.c_str(),sock))
     {
         errorStr = "Couldn't create tariffs table list With error:\n";
     if(MysqlQuery(res.c_str(),sock))
     {
         errorStr = "Couldn't create tariffs table list With error:\n";
@@ -337,51 +383,52 @@ if(!IsTablePresent("tariffs",sock))
     }
 
     res = "INSERT INTO tariffs SET name='tariff',";
     }
 
     res = "INSERT INTO tariffs SET name='tariff',";
-        
+
     for (int i = 0; i < DIR_NUM; i++)
         {
         strprintf(&param, " NoDiscount%d=1,", i);
         res += param;
     for (int i = 0; i < DIR_NUM; i++)
         {
         strprintf(&param, " NoDiscount%d=1,", i);
         res += param;
-    
+
         strprintf(&param, " Threshold%d=0,", i);
         res += param;
         strprintf(&param, " Threshold%d=0,", i);
         res += param;
-    
+
         strprintf(&param, " Time%d='0:0-0:0',", i);
         res += param;
         strprintf(&param, " Time%d='0:0-0:0',", i);
         res += param;
-    
+
         if(i != 0 && i != 1)
         {
             strprintf(&param, " SinglePrice%d=0,", i);
         if(i != 0 && i != 1)
         {
             strprintf(&param, " SinglePrice%d=0,", i);
-            res += param;        
+            res += param;
         }
         }
-    
+
         if(i != 1)
         {
         if(i != 1)
         {
-            strprintf(&param, " PriceDayA%d=0.0,", i); 
-            res += param;        
+            strprintf(&param, " PriceDayA%d=0.0,", i);
+            res += param;
         }
         if(i != 1)
         {
         }
         if(i != 1)
         {
-            strprintf(&param, " PriceDayB%d=0.0,", i);        
-            res += param;    
+            strprintf(&param, " PriceDayB%d=0.0,", i);
+            res += param;
         }
         }
-    
+
         if(i != 0)
         {
         if(i != 0)
         {
-            strprintf(&param, " PriceNightA%d=0.0,", i); 
-            res += param;        
+            strprintf(&param, " PriceNightA%d=0.0,", i);
+            res += param;
         }
         if(i != 0)
         {
         }
         if(i != 0)
         {
-            strprintf(&param, " PriceNightB%d=0.0,", i);        
-            res += param;    
+            strprintf(&param, " PriceNightB%d=0.0,", i);
+            res += param;
         }
         }
         }
         }
-    
+
     res += "PassiveCost=0.0, Fee=10.0, Free=0,"\
         "SinglePrice0=1, SinglePrice1=1,PriceDayA1=0.75,PriceDayB1=0.75,"\
     res += "PassiveCost=0.0, Fee=10.0, Free=0,"\
         "SinglePrice0=1, SinglePrice1=1,PriceDayA1=0.75,PriceDayB1=0.75,"\
-        "PriceNightA0=1.0,PriceNightB0=1.0,TraffType='up+down'";
-    
+        "PriceNightA0=1.0,PriceNightB0=1.0,TraffType='up+down',period='month',"\
+        "change_policy='allow', change_policy_timeout=0";
+
     if(MysqlQuery(res.c_str(),sock))
     {
         errorStr = "Couldn't create default tariff. With error:\n";
     if(MysqlQuery(res.c_str(),sock))
     {
         errorStr = "Couldn't create default tariff. With error:\n";
@@ -389,6 +436,17 @@ if(!IsTablePresent("tariffs",sock))
         mysql_close(sock);
         return -1;
     }
         mysql_close(sock);
         return -1;
     }
+
+    sprintf(qbuf,"UPDATE info SET version=1");
+
+    if(MysqlQuery(qbuf,sock))
+    {
+        errorStr = "Couldn't write default version. With error:\n";
+        errorStr += mysql_error(sock);
+        mysql_close(sock);
+        return -1;
+    }
+    schemaVersion = 2;
 }
 
 //users-----------------------------------------------------------------------
 }
 
 //users-----------------------------------------------------------------------
@@ -399,34 +457,34 @@ if(!IsTablePresent("users",sock))
         "Address VARCHAR(254) NOT NULL DEFAULT '',Phone VARCHAR(128) NOT NULL DEFAULT '',Email VARCHAR(50) NOT NULL DEFAULT '',"\
         "Note TEXT NOT NULL,RealName VARCHAR(254) NOT NULL DEFAULT '',StgGroup VARCHAR(40) NOT NULL DEFAULT '',"\
         "Credit DOUBLE DEFAULT 0, TariffChange VARCHAR(40) NOT NULL DEFAULT '',";
         "Address VARCHAR(254) NOT NULL DEFAULT '',Phone VARCHAR(128) NOT NULL DEFAULT '',Email VARCHAR(50) NOT NULL DEFAULT '',"\
         "Note TEXT NOT NULL,RealName VARCHAR(254) NOT NULL DEFAULT '',StgGroup VARCHAR(40) NOT NULL DEFAULT '',"\
         "Credit DOUBLE DEFAULT 0, TariffChange VARCHAR(40) NOT NULL DEFAULT '',";
-    
+
     for (int i = 0; i < USERDATA_NUM; i++)
         {
         strprintf(&param, " Userdata%d VARCHAR(254) NOT NULL,", i);
         res += param;
         }
     for (int i = 0; i < USERDATA_NUM; i++)
         {
         strprintf(&param, " Userdata%d VARCHAR(254) NOT NULL,", i);
         res += param;
         }
-    
+
     param = " CreditExpire INT(11) DEFAULT 0,";
     res += param;
     param = " CreditExpire INT(11) DEFAULT 0,";
     res += param;
-    
+
     strprintf(&param, " IP VARCHAR(254) DEFAULT '*',");
     res += param;
     strprintf(&param, " IP VARCHAR(254) DEFAULT '*',");
     res += param;
-    
+
     for (int i = 0; i < DIR_NUM; i++)
         {
         strprintf(&param, " D%d BIGINT(30) DEFAULT 0,", i);
         res += param;
     for (int i = 0; i < DIR_NUM; i++)
         {
         strprintf(&param, " D%d BIGINT(30) DEFAULT 0,", i);
         res += param;
-    
+
         strprintf(&param, " U%d BIGINT(30) DEFAULT 0,", i);
         res += param;
         }
         strprintf(&param, " U%d BIGINT(30) DEFAULT 0,", i);
         res += param;
         }
-    
+
     strprintf(&param, "Cash DOUBLE DEFAULT 0,FreeMb DOUBLE DEFAULT 0,LastCashAdd DOUBLE DEFAULT 0,"\
         "LastCashAddTime INT(11) DEFAULT 0,PassiveTime INT(11) DEFAULT 0,LastActivityTime INT(11) DEFAULT 0,"\
         "NAS VARCHAR(17) NOT NULL, INDEX (AlwaysOnline), INDEX (IP), INDEX (Address),"\
         " INDEX (Tariff),INDEX (Phone),INDEX (Email),INDEX (RealName))");
     res += param;
     strprintf(&param, "Cash DOUBLE DEFAULT 0,FreeMb DOUBLE DEFAULT 0,LastCashAdd DOUBLE DEFAULT 0,"\
         "LastCashAddTime INT(11) DEFAULT 0,PassiveTime INT(11) DEFAULT 0,LastActivityTime INT(11) DEFAULT 0,"\
         "NAS VARCHAR(17) NOT NULL, INDEX (AlwaysOnline), INDEX (IP), INDEX (Address),"\
         " INDEX (Tariff),INDEX (Phone),INDEX (Email),INDEX (RealName))");
     res += param;
-        
+
     if(MysqlQuery(res.c_str(),sock))
     {
         errorStr = "Couldn't create users table list With error:\n";
     if(MysqlQuery(res.c_str(),sock))
     {
         errorStr = "Couldn't create users table list With error:\n";
@@ -439,21 +497,26 @@ if(!IsTablePresent("users",sock))
     res = "INSERT INTO users SET login='test',Address='',AlwaysOnline=0,"\
         "Credit=0.0,CreditExpire=0,Down=0,Email='',DisabledDetailStat=0,"\
         "StgGroup='',IP='192.168.1.1',Note='',Passive=0,Password='123456',"\
     res = "INSERT INTO users SET login='test',Address='',AlwaysOnline=0,"\
         "Credit=0.0,CreditExpire=0,Down=0,Email='',DisabledDetailStat=0,"\
         "StgGroup='',IP='192.168.1.1',Note='',Passive=0,Password='123456',"\
-        "Phone='', RealName='',Tariff='tariff',TariffChange='',Userdata0='',"\
-        "Userdata1='',";
-    
+        "Phone='', RealName='',Tariff='tariff',TariffChange='',NAS='',";
+
+    for (int i = 0; i < USERDATA_NUM; i++)
+        {
+        strprintf(&param, " Userdata%d='',", i);
+        res += param;
+        }
+
     for (int i = 0; i < DIR_NUM; i++)
         {
         strprintf(&param, " D%d=0,", i);
         res += param;
     for (int i = 0; i < DIR_NUM; i++)
         {
         strprintf(&param, " D%d=0,", i);
         res += param;
-    
+
         strprintf(&param, " U%d=0,", i);
         res += param;
         }
         strprintf(&param, " U%d=0,", i);
         res += param;
         }
-    
+
     res += "Cash=10.0,FreeMb=0.0,LastActivityTime=0,LastCashAdd=0,"\
         "LastCashAddTime=0, PassiveTime=0";
     res += "Cash=10.0,FreeMb=0.0,LastActivityTime=0,LastCashAdd=0,"\
         "LastCashAddTime=0, PassiveTime=0";
-        
+
     if(MysqlQuery(res.c_str(),sock))
     {
         errorStr = "Couldn't create default user. With error:\n";
     if(MysqlQuery(res.c_str(),sock))
     {
         errorStr = "Couldn't create default user. With error:\n";
@@ -467,7 +530,7 @@ if(!IsTablePresent("users",sock))
 if(!IsTablePresent("logs"))
 {
     sprintf(qbuf,"CREATE TABLE logs (unid INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, login VARCHAR(40),text TEXT)");
 if(!IsTablePresent("logs"))
 {
     sprintf(qbuf,"CREATE TABLE logs (unid INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, login VARCHAR(40),text TEXT)");
-    
+
     if(MysqlQuery(qbuf))
     {
         errorStr = "Couldn't create admin table list With error:\n";
     if(MysqlQuery(qbuf))
     {
         errorStr = "Couldn't create admin table list With error:\n";
@@ -482,7 +545,7 @@ if(!IsTablePresent("messages",sock))
     sprintf(qbuf,"CREATE TABLE messages (login VARCHAR(40) DEFAULT '', id BIGINT, "\
             "type INT, lastSendTime INT, creationTime INT, showTime INT,"\
             "stgRepeat INT, repeatPeriod INT, text TEXT)");
     sprintf(qbuf,"CREATE TABLE messages (login VARCHAR(40) DEFAULT '', id BIGINT, "\
             "type INT, lastSendTime INT, creationTime INT, showTime INT,"\
             "stgRepeat INT, repeatPeriod INT, text TEXT)");
-    
+
     if(MysqlQuery(qbuf,sock))
     {
         errorStr = "Couldn't create messages table. With error:\n";
     if(MysqlQuery(qbuf,sock))
     {
         errorStr = "Couldn't create messages table. With error:\n";
@@ -496,18 +559,18 @@ if(!IsTablePresent("messages",sock))
 if(!IsTablePresent("stat",sock))
 {
     res = "CREATE TABLE stat (login VARCHAR(50), month TINYINT, year SMALLINT,";
 if(!IsTablePresent("stat",sock))
 {
     res = "CREATE TABLE stat (login VARCHAR(50), month TINYINT, year SMALLINT,";
-    
+
     for (int i = 0; i < DIR_NUM; i++)
         {
     for (int i = 0; i < DIR_NUM; i++)
         {
-        strprintf(&param, " U%d BIGINT,", i); 
+        strprintf(&param, " U%d BIGINT,", i);
         res += param;
         res += param;
-            
-        strprintf(&param, " D%d BIGINT,", i); 
+
+        strprintf(&param, " D%d BIGINT,", i);
         res += param;
         }
         res += param;
         }
-        
+
     res += " cash DOUBLE, INDEX (login))";
     res += " cash DOUBLE, INDEX (login))";
-    
+
     if(MysqlQuery(res.c_str(),sock))
     {
         errorStr = "Couldn't create stat table. With error:\n";
     if(MysqlQuery(res.c_str(),sock))
     {
         errorStr = "Couldn't create stat table. With error:\n";
@@ -520,20 +583,64 @@ if(!IsTablePresent("stat",sock))
 return 0;
 }
 //-----------------------------------------------------------------------------
 return 0;
 }
 //-----------------------------------------------------------------------------
+int MYSQL_STORE::MakeUpdates(MYSQL * sock)
+{
+if (schemaVersion  < 1)
+    {
+    if (MysqlQuery("ALTER TABLE tariffs ADD period VARCHAR(32) NOT NULL DEFAULT 'month'", sock))
+        {
+        errorStr = "Couldn't update tariffs table to version 1. With error:\n";
+        errorStr += mysql_error(sock);
+        mysql_close(sock);
+        return -1;
+        }
+    if (MysqlQuery("UPDATE info SET version = 1", sock))
+        {
+        errorStr = "Couldn't update DB schema version to 1. With error:\n";
+        errorStr += mysql_error(sock);
+        mysql_close(sock);
+        return -1;
+        }
+    schemaVersion = 1;
+    logger("MYSQL_STORE: Updated DB schema to version %d", schemaVersion);
+    }
+
+if (schemaVersion  < 2)
+    {
+    if (MysqlQuery("ALTER TABLE tariffs ADD change_policy VARCHAR(32) NOT NULL DEFAULT 'allow'", sock) ||
+        MysqlQuery("ALTER TABLE tariffs ADD change_policy_timeout TIMESTAMP NOT NULL DEFAULT 0", sock))
+        {
+        errorStr = "Couldn't update tariffs table to version 2. With error:\n";
+        errorStr += mysql_error(sock);
+        mysql_close(sock);
+        return -1;
+        }
+    if (MysqlQuery("UPDATE info SET version = 2", sock))
+        {
+        errorStr = "Couldn't update DB schema version to 2. With error:\n";
+        errorStr += mysql_error(sock);
+        mysql_close(sock);
+        return -1;
+        }
+    schemaVersion = 2;
+    logger("MYSQL_STORE: Updated DB schema to version %d", schemaVersion);
+    }
+return 0;
+}
 //-----------------------------------------------------------------------------
 
 //-----------------------------------------------------------------------------
 
-int MYSQL_STORE::GetAllParams(vector<string> * ParamList, 
-                            const string & table, const string & name) const
+int MYSQL_STORE::GetAllParams(std::vector<std::string> * ParamList,
+                            const std::string & table, const std::string & name) const
 {
 MYSQL_RES *res;
 MYSQL_ROW row;
 MYSQL * sock=NULL;
 {
 MYSQL_RES *res;
 MYSQL_ROW row;
 MYSQL * sock=NULL;
-unsigned int num,i;
-    
+my_ulonglong num, i;
+
 ParamList->clear();
 ParamList->clear();
-    
+
 sprintf(qbuf,"SELECT %s FROM %s", name.c_str(), table.c_str());
 sprintf(qbuf,"SELECT %s FROM %s", name.c_str(), table.c_str());
-    
+
 if(MysqlGetQuery(qbuf,sock))
 {
     errorStr = "Couldn't GetAllParams Query for: ";
 if(MysqlGetQuery(qbuf,sock))
 {
     errorStr = "Couldn't GetAllParams Query for: ";
@@ -553,9 +660,9 @@ if (!(res=mysql_store_result(sock)))
 
 num = mysql_num_rows(res);
 
 
 num = mysql_num_rows(res);
 
-for(i=0;i<num;i++)
+for(i = 0; i < num; i++)
 {
 {
-    row = mysql_fetch_row(res);    
+    row = mysql_fetch_row(res);
     ParamList->push_back(row[0]);
 }
 
     ParamList->push_back(row[0]);
 }
 
@@ -566,7 +673,7 @@ return 0;
 }
 
 //-----------------------------------------------------------------------------
 }
 
 //-----------------------------------------------------------------------------
-int MYSQL_STORE::GetUsersList(vector<string> * usersList) const
+int MYSQL_STORE::GetUsersList(std::vector<std::string> * usersList) const
 {
 if(GetAllParams(usersList, "users", "login"))
     return -1;
 {
 if(GetAllParams(usersList, "users", "login"))
     return -1;
@@ -574,7 +681,7 @@ if(GetAllParams(usersList, "users", "login"))
 return 0;
 }
 //-----------------------------------------------------------------------------
 return 0;
 }
 //-----------------------------------------------------------------------------
-int MYSQL_STORE::GetAdminsList(vector<string> * adminsList) const
+int MYSQL_STORE::GetAdminsList(std::vector<std::string> * adminsList) const
 {
 if(GetAllParams(adminsList, "admins", "login"))
     return -1;
 {
 if(GetAllParams(adminsList, "admins", "login"))
     return -1;
@@ -582,7 +689,7 @@ if(GetAllParams(adminsList, "admins", "login"))
 return 0;
 }
 //-----------------------------------------------------------------------------
 return 0;
 }
 //-----------------------------------------------------------------------------
-int MYSQL_STORE::GetTariffsList(vector<string> * tariffsList) const
+int MYSQL_STORE::GetTariffsList(std::vector<std::string> * tariffsList) const
 {
 if(GetAllParams(tariffsList, "tariffs", "name"))
     return -1;
 {
 if(GetAllParams(tariffsList, "tariffs", "name"))
     return -1;
@@ -590,11 +697,14 @@ if(GetAllParams(tariffsList, "tariffs", "name"))
 return 0;
 }
 //-----------------------------------------------------------------------------
 return 0;
 }
 //-----------------------------------------------------------------------------
-int MYSQL_STORE::AddUser(const string & login) const
+int MYSQL_STORE::AddUser(const std::string & login) const
 {
 {
-sprintf(qbuf,"INSERT INTO users SET login='%s'", login.c_str());
-    
-if(MysqlSetQuery(qbuf))
+std::string query = "INSERT INTO users SET login='" + login + "',Note='',NAS=''";
+
+for (int i = 0; i < USERDATA_NUM; i++)
+    query += ",Userdata" + x2str(i) + "=''";
+
+if(MysqlSetQuery(query.c_str()))
 {
     errorStr = "Couldn't add user:\n";
     //errorStr += mysql_error(sock);
 {
     errorStr = "Couldn't add user:\n";
     //errorStr += mysql_error(sock);
@@ -604,10 +714,10 @@ if(MysqlSetQuery(qbuf))
 return 0;
 }
 //-----------------------------------------------------------------------------
 return 0;
 }
 //-----------------------------------------------------------------------------
-int MYSQL_STORE::DelUser(const string & login) const
+int MYSQL_STORE::DelUser(const std::string & login) const
 {
 sprintf(qbuf,"DELETE FROM users WHERE login='%s' LIMIT 1", login.c_str());
 {
 sprintf(qbuf,"DELETE FROM users WHERE login='%s' LIMIT 1", login.c_str());
-    
+
 if(MysqlSetQuery(qbuf))
 {
     errorStr = "Couldn't delete user:\n";
 if(MysqlSetQuery(qbuf))
 {
     errorStr = "Couldn't delete user:\n";
@@ -618,12 +728,12 @@ if(MysqlSetQuery(qbuf))
 return 0;
 }
 //-----------------------------------------------------------------------------
 return 0;
 }
 //-----------------------------------------------------------------------------
-int MYSQL_STORE::RestoreUserConf(USER_CONF * conf, const string & login) const
+int MYSQL_STORE::RestoreUserConf(USER_CONF * conf, const std::string & login) const
 {
 MYSQL_RES *res;
 MYSQL_ROW row;
 MYSQL * sock;
 {
 MYSQL_RES *res;
 MYSQL_ROW row;
 MYSQL * sock;
-string query;
+std::string query;
 
 query = "SELECT login, Password, Passive, Down, DisabledDetailStat, \
          AlwaysOnline, Tariff, Address, Phone, Email, Note, \
 
 query = "SELECT login, Password, Passive, Down, DisabledDetailStat, \
          AlwaysOnline, Tariff, Address, Phone, Email, Note, \
@@ -639,7 +749,7 @@ query += "CreditExpire, IP FROM users WHERE login='";
 query += login + "' LIMIT 1";
 
 //sprintf(qbuf,"SELECT * FROM users WHERE login='%s' LIMIT 1", login.c_str());
 query += login + "' LIMIT 1";
 
 //sprintf(qbuf,"SELECT * FROM users WHERE login='%s' LIMIT 1", login.c_str());
-    
+
 if(MysqlGetQuery(query.c_str(),sock))
 {
     errorStr = "Couldn't restore Tariff(on query):\n";
 if(MysqlGetQuery(query.c_str(),sock))
 {
     errorStr = "Couldn't restore Tariff(on query):\n";
@@ -665,8 +775,6 @@ if (mysql_num_rows(res) != 1)
 
 row = mysql_fetch_row(res);
 
 
 row = mysql_fetch_row(res);
 
-string param;
-
 conf->password = row[1];
 
 if (conf->password.empty())
 conf->password = row[1];
 
 if (conf->password.empty())
@@ -677,7 +785,7 @@ if (conf->password.empty())
     return -1;
     }
 
     return -1;
     }
 
-if (GetInt(row[2],&conf->passive, 0) != 0)
+if (GetInt(row[2],&conf->passive) != 0)
     {
     mysql_free_result(res);
     errorStr = "User \'" + login + "\' data not read. Parameter Passive.";
     {
     mysql_free_result(res);
     errorStr = "User \'" + login + "\' data not read. Parameter Passive.";
@@ -685,7 +793,7 @@ if (GetInt(row[2],&conf->passive, 0) != 0)
     return -1;
     }
 
     return -1;
     }
 
-if (GetInt(row[3], &conf->disabled, 0) != 0)
+if (GetInt(row[3], &conf->disabled) != 0)
     {
     mysql_free_result(res);
     errorStr = "User \'" + login + "\' data not read. Parameter Down.";
     {
     mysql_free_result(res);
     errorStr = "User \'" + login + "\' data not read. Parameter Down.";
@@ -693,7 +801,7 @@ if (GetInt(row[3], &conf->disabled, 0) != 0)
     return -1;
     }
 
     return -1;
     }
 
-if (GetInt(row[4], &conf->disabledDetailStat, 0) != 0)
+if (GetInt(row[4], &conf->disabledDetailStat) != 0)
     {
     mysql_free_result(res);
     errorStr = "User \'" + login + "\' data not read. Parameter DisabledDetailStat.";
     {
     mysql_free_result(res);
     errorStr = "User \'" + login + "\' data not read. Parameter DisabledDetailStat.";
@@ -701,7 +809,7 @@ if (GetInt(row[4], &conf->disabledDetailStat, 0) != 0)
     return -1;
     }
 
     return -1;
     }
 
-if (GetInt(row[5], &conf->alwaysOnline, 0) != 0)
+if (GetInt(row[5], &conf->alwaysOnline) != 0)
     {
     mysql_free_result(res);
     errorStr = "User \'" + login + "\' data not read. Parameter AlwaysOnline.";
     {
     mysql_free_result(res);
     errorStr = "User \'" + login + "\' data not read. Parameter AlwaysOnline.";
@@ -711,7 +819,7 @@ if (GetInt(row[5], &conf->alwaysOnline, 0) != 0)
 
 conf->tariffName = row[6];
 
 
 conf->tariffName = row[6];
 
-if (conf->tariffName.empty()) 
+if (conf->tariffName.empty())
     {
     mysql_free_result(res);
     errorStr = "User \'" + login + "\' tariff is blank.";
     {
     mysql_free_result(res);
     errorStr = "User \'" + login + "\' tariff is blank.";
@@ -742,14 +850,14 @@ for (int i = 0; i < USERDATA_NUM; i++)
     }
 
 GetTime(row[15+USERDATA_NUM], &conf->creditExpire, 0);
     }
 
 GetTime(row[15+USERDATA_NUM], &conf->creditExpire, 0);
-    
-string ipStr = row[16+USERDATA_NUM];
+
+std::string ipStr = row[16+USERDATA_NUM];
 USER_IPS i;
 try
     {
     i = StrToIPS(ipStr);
     }
 USER_IPS i;
 try
     {
     i = StrToIPS(ipStr);
     }
-catch (const string & s)
+catch (const std::string & s)
     {
     mysql_free_result(res);
     errorStr = "User \'" + login + "\' data not read. Parameter IP address. " + s;
     {
     mysql_free_result(res);
     errorStr = "User \'" + login + "\' data not read. Parameter IP address. " + s;
@@ -764,13 +872,13 @@ mysql_close(sock);
 return 0;
 }
 //-----------------------------------------------------------------------------
 return 0;
 }
 //-----------------------------------------------------------------------------
-int MYSQL_STORE::RestoreUserStat(USER_STAT * stat, const string & login) const
+int MYSQL_STORE::RestoreUserStat(USER_STAT * stat, const std::string & login) const
 {
 MYSQL_RES *res;
 MYSQL_ROW row;
 MYSQL * sock;
 
 {
 MYSQL_RES *res;
 MYSQL_ROW row;
 MYSQL * sock;
 
-string query;
+std::string query;
 
 query = "SELECT ";
 
 
 query = "SELECT ";
 
@@ -785,7 +893,7 @@ query += "Cash, FreeMb, LastCashAdd, LastCashAddTime, PassiveTime, LastActivityT
 query += login + "'";
 
 //sprintf(qbuf,"SELECT * FROM users WHERE login='%s' LIMIT 1", login.c_str());
 query += login + "'";
 
 //sprintf(qbuf,"SELECT * FROM users WHERE login='%s' LIMIT 1", login.c_str());
-    
+
 if(MysqlGetQuery(query.c_str() ,sock))
 {
     errorStr = "Couldn't restore UserStat(on query):\n";
 if(MysqlGetQuery(query.c_str() ,sock))
 {
     errorStr = "Couldn't restore UserStat(on query):\n";
@@ -815,21 +923,21 @@ for (int i = 0; i < DIR_NUM; i++)
     if (GetULongLongInt(row[startPos+i*2], &traff, 0) != 0)
         {
         mysql_free_result(res);
     if (GetULongLongInt(row[startPos+i*2], &traff, 0) != 0)
         {
         mysql_free_result(res);
-        errorStr = "User \'" + login + "\' stat not read. Parameter " + string(s);
+        errorStr = "User \'" + login + "\' stat not read. Parameter " + std::string(s);
         mysql_close(sock);
         return -1;
         }
         mysql_close(sock);
         return -1;
         }
-    stat->down[i] = traff;
+    stat->monthDown[i] = traff;
 
     sprintf(s, "U%d", i);
     if (GetULongLongInt(row[startPos+i*2+1], &traff, 0) != 0)
         {
         mysql_free_result(res);
 
     sprintf(s, "U%d", i);
     if (GetULongLongInt(row[startPos+i*2+1], &traff, 0) != 0)
         {
         mysql_free_result(res);
-        errorStr =   "User \'" + login + "\' stat not read. Parameter " + string(s);
+        errorStr =   "User \'" + login + "\' stat not read. Parameter " + std::string(s);
         mysql_close(sock);
         return -1;
         }
         mysql_close(sock);
         return -1;
         }
-    stat->up[i] = traff;
+    stat->monthUp[i] = traff;
     }//for
 
 startPos += (2*DIR_NUM);
     }//for
 
 startPos += (2*DIR_NUM);
@@ -887,14 +995,14 @@ mysql_close(sock);
 return 0;
 }
 //-----------------------------------------------------------------------------
 return 0;
 }
 //-----------------------------------------------------------------------------
-int MYSQL_STORE::SaveUserConf(const USER_CONF & conf, const string & login) const
+int MYSQL_STORE::SaveUserConf(const USER_CONF & conf, const std::string & login) const
 {
 {
-string param;
-string res;
+std::string param;
+std::string res;
 
 strprintf(&res,"UPDATE users SET Password='%s', Passive=%d, Down=%d, DisabledDetailStat = %d, "\
     "AlwaysOnline=%d, Tariff='%s', Address='%s', Phone='%s', Email='%s', "\
 
 strprintf(&res,"UPDATE users SET Password='%s', Passive=%d, Down=%d, DisabledDetailStat = %d, "\
     "AlwaysOnline=%d, Tariff='%s', Address='%s', Phone='%s', Email='%s', "\
-    "Note='%s', RealName='%s', StgGroup='%s', Credit=%f, TariffChange='%s', ", 
+    "Note='%s', RealName='%s', StgGroup='%s', Credit=%f, TariffChange='%s', ",
     conf.password.c_str(),
     conf.passive,
     conf.disabled,
     conf.password.c_str(),
     conf.passive,
     conf.disabled,
@@ -913,15 +1021,15 @@ strprintf(&res,"UPDATE users SET Password='%s', Passive=%d, Down=%d, DisabledDet
 
 for (int i = 0; i < USERDATA_NUM; i++)
     {
 
 for (int i = 0; i < USERDATA_NUM; i++)
     {
-    strprintf(&param, " Userdata%d='%s',", i, 
+    strprintf(&param, " Userdata%d='%s',", i,
         (ReplaceStr(conf.userdata[i],badSyms,repSym)).c_str());
     res += param;
     }
         (ReplaceStr(conf.userdata[i],badSyms,repSym)).c_str());
     res += param;
     }
-    
+
 strprintf(&param, " CreditExpire=%d,", conf.creditExpire);
 res += param;
 
 strprintf(&param, " CreditExpire=%d,", conf.creditExpire);
 res += param;
 
-stringstream ipStr;
+std::ostringstream ipStr;
 ipStr << conf.ips;
 
 strprintf(&param, " IP='%s'", ipStr.str().c_str());
 ipStr << conf.ips;
 
 strprintf(&param, " IP='%s'", ipStr.str().c_str());
@@ -940,24 +1048,24 @@ if(MysqlSetQuery(res.c_str()))
 return 0;
 }
 //-----------------------------------------------------------------------------
 return 0;
 }
 //-----------------------------------------------------------------------------
-int MYSQL_STORE::SaveUserStat(const USER_STAT & stat, const string & login) const
+int MYSQL_STORE::SaveUserStat(const USER_STAT & stat, const std::string & login) const
 {
 {
-string param;
-string res;
+std::string param;
+std::string res;
 
 res = "UPDATE users SET";
 
 for (int i = 0; i < DIR_NUM; i++)
     {
 
 res = "UPDATE users SET";
 
 for (int i = 0; i < DIR_NUM; i++)
     {
-    strprintf(&param, " D%d=%lld,", i, stat.down[i]);
+    strprintf(&param, " D%d=%lld,", i, stat.monthDown[i]);
     res += param;
 
     res += param;
 
-    strprintf(&param, " U%d=%lld,", i, stat.up[i]);
+    strprintf(&param, " U%d=%lld,", i, stat.monthUp[i]);
     res += param;
     }
 
 strprintf(&param, " Cash=%f, FreeMb=%f, LastCashAdd=%f, LastCashAddTime=%d,"\
     res += param;
     }
 
 strprintf(&param, " Cash=%f, FreeMb=%f, LastCashAdd=%f, LastCashAddTime=%d,"\
-    " PassiveTime=%d, LastActivityTime=%d", 
+    " PassiveTime=%d, LastActivityTime=%d",
     stat.cash,
     stat.freeMb,
     stat.lastCashAdd,
     stat.cash,
     stat.freeMb,
     stat.lastCashAdd,
@@ -980,9 +1088,9 @@ if(MysqlSetQuery(res.c_str()))
 return 0;
 }
 //-----------------------------------------------------------------------------
 return 0;
 }
 //-----------------------------------------------------------------------------
-int MYSQL_STORE::WriteLogString(const string & str, const string & login) const
+int MYSQL_STORE::WriteLogString(const std::string & str, const std::string & login) const
 {
 {
-string res, tempStr;
+std::string res, tempStr;
 time_t t;
 tm * lt;
 
 time_t t;
 tm * lt;
 
@@ -1004,7 +1112,7 @@ if (!(result=mysql_list_tables(sock,tempStr.c_str() )))
     return -1;
 }
 
     return -1;
 }
 
-unsigned int num_rows =  mysql_num_rows(result);
+my_ulonglong num_rows =  mysql_num_rows(result);
 
 mysql_free_result(result);
 
 
 mysql_free_result(result);
 
@@ -1012,7 +1120,7 @@ if (num_rows < 1)
 {
     sprintf(qbuf,"CREATE TABLE logs_%02d_%4d (unid INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, login VARCHAR(40),text TEXT)",
     lt->tm_mon+1, lt->tm_year+1900);
 {
     sprintf(qbuf,"CREATE TABLE logs_%02d_%4d (unid INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, login VARCHAR(40),text TEXT)",
     lt->tm_mon+1, lt->tm_year+1900);
-    
+
     if(MysqlQuery(qbuf,sock))
     {
         errorStr = "Couldn't create WriteDetailedStat table:\n";
     if(MysqlQuery(qbuf,sock))
     {
         errorStr = "Couldn't create WriteDetailedStat table:\n";
@@ -1024,7 +1132,7 @@ if (num_rows < 1)
 
 strprintf(&res, "%s -- %s",LogDate(t), str.c_str());
 
 
 strprintf(&res, "%s -- %s",LogDate(t), str.c_str());
 
-string send;
+std::string send;
 
 strprintf(&send,"INSERT INTO logs_%02d_%4d SET login='%s', text='%s'",
         lt->tm_mon+1, lt->tm_year+1900,
 
 strprintf(&send,"INSERT INTO logs_%02d_%4d SET login='%s', text='%s'",
         lt->tm_mon+1, lt->tm_year+1900,
@@ -1042,42 +1150,42 @@ return 0;
 
 }
 //-----------------------------------------------------------------------------
 
 }
 //-----------------------------------------------------------------------------
-int MYSQL_STORE::WriteUserChgLog(const string & login,
-                                 const string & admLogin,
+int MYSQL_STORE::WriteUserChgLog(const std::string & login,
+                                 const std::string & admLogin,
                                  uint32_t       admIP,
                                  uint32_t       admIP,
-                                 const string & paramName,
-                                 const string & oldValue,
-                                 const string & newValue,
-                                 const string & message) const
+                                 const std::string & paramName,
+                                 const std::string & oldValue,
+                                 const std::string & newValue,
+                                 const std::string & message) const
 {
 {
-string userLogMsg = "Admin \'" + admLogin + "\', " + inet_ntostring(admIP) + ": \'"
+std::string userLogMsg = "Admin \'" + admLogin + "\', " + inet_ntostring(admIP) + ": \'"
     + paramName + "\' parameter changed from \'" + oldValue +
     "\' to \'" + newValue + "\'. " + message;
 
 return WriteLogString(userLogMsg, login);
 }
 //-----------------------------------------------------------------------------
     + paramName + "\' parameter changed from \'" + oldValue +
     "\' to \'" + newValue + "\'. " + message;
 
 return WriteLogString(userLogMsg, login);
 }
 //-----------------------------------------------------------------------------
-int MYSQL_STORE::WriteUserConnect(const string & login, uint32_t ip) const
+int MYSQL_STORE::WriteUserConnect(const std::string & login, uint32_t ip) const
 {
 {
-string logStr = "Connect, " + inet_ntostring(ip);
+std::string logStr = "Connect, " + inet_ntostring(ip);
 return WriteLogString(logStr, login);
 }
 //-----------------------------------------------------------------------------
 return WriteLogString(logStr, login);
 }
 //-----------------------------------------------------------------------------
-int MYSQL_STORE::WriteUserDisconnect(const string & login,
+int MYSQL_STORE::WriteUserDisconnect(const std::string & login,
                                      const DIR_TRAFF & up,
                                      const DIR_TRAFF & down,
                                      const DIR_TRAFF & sessionUp,
                                      const DIR_TRAFF & sessionDown,
                                      double cash,
                                      const DIR_TRAFF & up,
                                      const DIR_TRAFF & down,
                                      const DIR_TRAFF & sessionUp,
                                      const DIR_TRAFF & sessionDown,
                                      double cash,
-                                     double freeMb,
-                                     const std::string & reason) const
+                                     double /*freeMb*/,
+                                     const std::string & /*reason*/) const
 {
 {
-string logStr = "Disconnect, ";
-stringstream sssu;
-stringstream sssd;
-stringstream ssmu;
-stringstream ssmd;
-stringstream sscash;
+std::string logStr = "Disconnect, ";
+std::ostringstream sssu;
+std::ostringstream sssd;
+std::ostringstream ssmu;
+std::ostringstream ssmd;
+std::ostringstream sscash;
 
 ssmu << up;
 ssmd << down;
 
 ssmu << up;
 ssmd << down;
@@ -1102,24 +1210,24 @@ logStr += "\'";
 return WriteLogString(logStr, login);
 }
 //-----------------------------------------------------------------------------
 return WriteLogString(logStr, login);
 }
 //-----------------------------------------------------------------------------
-int MYSQL_STORE::SaveMonthStat(const USER_STAT & stat, int month, int year, 
-                                const string & login) const
+int MYSQL_STORE::SaveMonthStat(const USER_STAT & stat, int month, int year,
+                                const std::string & login) const
 {
 {
-string param, res;
+std::string param, res;
 
 
-strprintf(&res, "INSERT INTO stat SET login='%s', month=%d, year=%d,", 
+strprintf(&res, "INSERT INTO stat SET login='%s', month=%d, year=%d,",
     login.c_str(), month+1, year+1900);
     login.c_str(), month+1, year+1900);
-    
+
 for (int i = 0; i < DIR_NUM; i++)
     {
 for (int i = 0; i < DIR_NUM; i++)
     {
-    strprintf(&param, " U%d=%lld,", i, stat.up[i]); 
+    strprintf(&param, " U%d=%lld,", i, stat.monthUp[i]);
     res += param;
 
     res += param;
 
-    strprintf(&param, " D%d=%lld,", i, stat.down[i]);        
+    strprintf(&param, " D%d=%lld,", i, stat.monthDown[i]);
     res += param;
     }
     res += param;
     }
-    
-strprintf(&param, " cash=%f", stat.cash);        
+
+strprintf(&param, " cash=%f", stat.cash);
 res += param;
 
 if(MysqlSetQuery(res.c_str()))
 res += param;
 
 if(MysqlSetQuery(res.c_str()))
@@ -1132,10 +1240,10 @@ if(MysqlSetQuery(res.c_str()))
 return 0;
 }
 //-----------------------------------------------------------------------------*/
 return 0;
 }
 //-----------------------------------------------------------------------------*/
-int MYSQL_STORE::AddAdmin(const string & login) const
+int MYSQL_STORE::AddAdmin(const std::string & login) const
 {
 sprintf(qbuf,"INSERT INTO admins SET login='%s'", login.c_str());
 {
 sprintf(qbuf,"INSERT INTO admins SET login='%s'", login.c_str());
-    
+
 if(MysqlSetQuery(qbuf))
 {
     errorStr = "Couldn't add admin:\n";
 if(MysqlSetQuery(qbuf))
 {
     errorStr = "Couldn't add admin:\n";
@@ -1146,10 +1254,10 @@ if(MysqlSetQuery(qbuf))
 return 0;
 }
 //-----------------------------------------------------------------------------*/
 return 0;
 }
 //-----------------------------------------------------------------------------*/
-int MYSQL_STORE::DelAdmin(const string & login) const
+int MYSQL_STORE::DelAdmin(const std::string & login) const
 {
 sprintf(qbuf,"DELETE FROM admins where login='%s' LIMIT 1", login.c_str());
 {
 sprintf(qbuf,"DELETE FROM admins where login='%s' LIMIT 1", login.c_str());
-    
+
 if(MysqlSetQuery(qbuf))
 {
     errorStr = "Couldn't delete admin:\n";
 if(MysqlSetQuery(qbuf))
 {
     errorStr = "Couldn't delete admin:\n";
@@ -1170,14 +1278,14 @@ memset(pass, 0, sizeof(pass));
 memset(adminPass, 0, sizeof(adminPass));
 
 BLOWFISH_CTX ctx;
 memset(adminPass, 0, sizeof(adminPass));
 
 BLOWFISH_CTX ctx;
-EnDecodeInit(adm_enc_passwd, strlen(adm_enc_passwd), &ctx);
+InitContext(adm_enc_passwd, strlen(adm_enc_passwd), &ctx);
 
 strncpy(adminPass, ac.password.c_str(), ADM_PASSWD_LEN);
 adminPass[ADM_PASSWD_LEN - 1] = 0;
 
 for (int i = 0; i < ADM_PASSWD_LEN/8; i++)
     {
 
 strncpy(adminPass, ac.password.c_str(), ADM_PASSWD_LEN);
 adminPass[ADM_PASSWD_LEN - 1] = 0;
 
 for (int i = 0; i < ADM_PASSWD_LEN/8; i++)
     {
-    EncodeString(pass + 8*i, adminPass + 8*i, &ctx);
+    EncryptBlock(pass + 8*i, adminPass + 8*i, &ctx);
     }
 
 pass[ADM_PASSWD_LEN - 1] = 0;
     }
 
 pass[ADM_PASSWD_LEN - 1] = 0;
@@ -1185,7 +1293,7 @@ Encode12(passwordE, pass, ADM_PASSWD_LEN);
 
 sprintf(qbuf,"UPDATE admins SET password='%s', ChgConf=%d, ChgPassword=%d, "\
     "ChgStat=%d, ChgCash=%d, UsrAddDel=%d, ChgTariff=%d, ChgAdmin=%d "\
 
 sprintf(qbuf,"UPDATE admins SET password='%s', ChgConf=%d, ChgPassword=%d, "\
     "ChgStat=%d, ChgCash=%d, UsrAddDel=%d, ChgTariff=%d, ChgAdmin=%d "\
-    "WHERE login='%s' LIMIT 1", 
+    "WHERE login='%s' LIMIT 1",
     passwordE,
     ac.priv.userConf,
     ac.priv.userPasswd,
     passwordE,
     ac.priv.userConf,
     ac.priv.userPasswd,
@@ -1207,23 +1315,21 @@ if(MysqlSetQuery(qbuf))
 return 0;
 }
 //-----------------------------------------------------------------------------
 return 0;
 }
 //-----------------------------------------------------------------------------
-int MYSQL_STORE::RestoreAdmin(ADMIN_CONF * ac, const string & login) const
+int MYSQL_STORE::RestoreAdmin(ADMIN_CONF * ac, const std::string & login) const
 {
 char pass[ADM_PASSWD_LEN + 1];
 char password[ADM_PASSWD_LEN + 1];
 char passwordE[2*ADM_PASSWD_LEN + 2];
 BLOWFISH_CTX ctx;
 
 {
 char pass[ADM_PASSWD_LEN + 1];
 char password[ADM_PASSWD_LEN + 1];
 char passwordE[2*ADM_PASSWD_LEN + 2];
 BLOWFISH_CTX ctx;
 
-memset(pass, 0, sizeof(pass));
 memset(password, 0, sizeof(password));
 memset(password, 0, sizeof(password));
-memset(passwordE, 0, sizeof(passwordE));
 
 
-string p;
+std::string p;
 MYSQL_RES *res;
 MYSQL_ROW row;
 MYSQL * sock;
 sprintf(qbuf,"SELECT * FROM admins WHERE login='%s' LIMIT 1", login.c_str());
 MYSQL_RES *res;
 MYSQL_ROW row;
 MYSQL * sock;
 sprintf(qbuf,"SELECT * FROM admins WHERE login='%s' LIMIT 1", login.c_str());
-    
+
 if(MysqlGetQuery(qbuf,sock))
 {
     errorStr = "Couldn't restore admin:\n";
 if(MysqlGetQuery(qbuf,sock))
 {
     errorStr = "Couldn't restore admin:\n";
@@ -1247,11 +1353,10 @@ if ( mysql_num_rows(res) == 0)
     mysql_close(sock);
     return -1;
 }
     mysql_close(sock);
     return -1;
 }
-  
+
 row = mysql_fetch_row(res);
 
 p = row[1];
 row = mysql_fetch_row(res);
 
 p = row[1];
-int a;
 
 if(p.length() == 0)
 {
 
 if(p.length() == 0)
 {
@@ -1269,11 +1374,11 @@ memset(pass, 0, sizeof(pass));
 if (passwordE[0] != 0)
     {
     Decode21(pass, passwordE);
 if (passwordE[0] != 0)
     {
     Decode21(pass, passwordE);
-    EnDecodeInit(adm_enc_passwd, strlen(adm_enc_passwd), &ctx);
+    InitContext(adm_enc_passwd, strlen(adm_enc_passwd), &ctx);
 
     for (int i = 0; i < ADM_PASSWD_LEN/8; i++)
         {
 
     for (int i = 0; i < ADM_PASSWD_LEN/8; i++)
         {
-        DecodeString(password + 8*i, pass + 8*i, &ctx);
+        DecryptBlock(password + 8*i, pass + 8*i, &ctx);
         }
     }
 else
         }
     }
 else
@@ -1283,7 +1388,9 @@ else
 
 ac->password = password;
 
 
 ac->password = password;
 
-if (GetInt(row[2], &a, 0) == 0) 
+uint16_t a;
+
+if (GetInt(row[2], &a) == 0)
     ac->priv.userConf = a;
 else
     {
     ac->priv.userConf = a;
 else
     {
@@ -1293,7 +1400,7 @@ else
     return -1;
     }
 
     return -1;
     }
 
-if (GetInt(row[3], &a, 0) == 0) 
+if (GetInt(row[3], &a) == 0)
     ac->priv.userPasswd = a;
 else
     {
     ac->priv.userPasswd = a;
 else
     {
@@ -1303,7 +1410,7 @@ else
     return -1;
     }
 
     return -1;
     }
 
-if (GetInt(row[4], &a, 0) == 0) 
+if (GetInt(row[4], &a) == 0)
     ac->priv.userStat = a;
 else
     {
     ac->priv.userStat = a;
 else
     {
@@ -1313,7 +1420,7 @@ else
     return -1;
     }
 
     return -1;
     }
 
-if (GetInt(row[5], &a, 0) == 0) 
+if (GetInt(row[5], &a) == 0)
     ac->priv.userCash = a;
 else
     {
     ac->priv.userCash = a;
 else
     {
@@ -1323,7 +1430,7 @@ else
     return -1;
     }
 
     return -1;
     }
 
-if (GetInt(row[6], &a, 0) == 0) 
+if (GetInt(row[6], &a) == 0)
     ac->priv.userAddDel = a;
 else
     {
     ac->priv.userAddDel = a;
 else
     {
@@ -1333,7 +1440,7 @@ else
     return -1;
     }
 
     return -1;
     }
 
-if (GetInt(row[7], &a, 0) == 0) 
+if (GetInt(row[7], &a) == 0)
     ac->priv.tariffChg = a;
 else
     {
     ac->priv.tariffChg = a;
 else
     {
@@ -1343,7 +1450,7 @@ else
     return -1;
     }
 
     return -1;
     }
 
-if (GetInt(row[8], &a, 0) == 0) 
+if (GetInt(row[8], &a) == 0)
     ac->priv.adminChg = a;
 else
     {
     ac->priv.adminChg = a;
 else
     {
@@ -1358,10 +1465,10 @@ mysql_close(sock);
 return 0;
 }
 //-----------------------------------------------------------------------------
 return 0;
 }
 //-----------------------------------------------------------------------------
-int MYSQL_STORE::AddTariff(const string & name) const
+int MYSQL_STORE::AddTariff(const std::string & name) const
 {
 sprintf(qbuf,"INSERT INTO tariffs SET name='%s'", name.c_str());
 {
 sprintf(qbuf,"INSERT INTO tariffs SET name='%s'", name.c_str());
-    
+
 if(MysqlSetQuery(qbuf))
 {
     errorStr = "Couldn't add tariff:\n";
 if(MysqlSetQuery(qbuf))
 {
     errorStr = "Couldn't add tariff:\n";
@@ -1372,10 +1479,10 @@ if(MysqlSetQuery(qbuf))
 return 0;
 }
 //-----------------------------------------------------------------------------
 return 0;
 }
 //-----------------------------------------------------------------------------
-int MYSQL_STORE::DelTariff(const string & name) const
+int MYSQL_STORE::DelTariff(const std::string & name) const
 {
 sprintf(qbuf,"DELETE FROM tariffs WHERE name='%s' LIMIT 1", name.c_str());
 {
 sprintf(qbuf,"DELETE FROM tariffs WHERE name='%s' LIMIT 1", name.c_str());
-    
+
 if(MysqlSetQuery(qbuf))
 {
     errorStr = "Couldn't delete tariff: ";
 if(MysqlSetQuery(qbuf))
 {
     errorStr = "Couldn't delete tariff: ";
@@ -1386,13 +1493,13 @@ if(MysqlSetQuery(qbuf))
 return 0;
 }
 //-----------------------------------------------------------------------------
 return 0;
 }
 //-----------------------------------------------------------------------------
-int MYSQL_STORE::RestoreTariff(TARIFF_DATA * td, const string & tariffName) const
+int MYSQL_STORE::RestoreTariff(TARIFF_DATA * td, const std::string & tariffName) const
 {
 MYSQL_RES *res;
 MYSQL_ROW row;
 MYSQL * sock;
 sprintf(qbuf,"SELECT * FROM tariffs WHERE name='%s' LIMIT 1", tariffName.c_str());
 {
 MYSQL_RES *res;
 MYSQL_ROW row;
 MYSQL * sock;
 sprintf(qbuf,"SELECT * FROM tariffs WHERE name='%s' LIMIT 1", tariffName.c_str());
-    
+
 if(MysqlGetQuery(qbuf,sock))
 {
     errorStr = "Couldn't restore Tariff:\n";
 if(MysqlGetQuery(qbuf,sock))
 {
     errorStr = "Couldn't restore Tariff:\n";
@@ -1409,12 +1516,12 @@ if (!(res=mysql_store_result(sock)))
     return -1;
 }
 
     return -1;
 }
 
-string str;
+std::string str;
 td->tariffConf.name = tariffName;
 
 row = mysql_fetch_row(res);
 
 td->tariffConf.name = tariffName;
 
 row = mysql_fetch_row(res);
 
-string param;
+std::string param;
 for (int i = 0; i<DIR_NUM; i++)
     {
     strprintf(&param, "Time%d", i);
 for (int i = 0; i<DIR_NUM; i++)
     {
     strprintf(&param, "Time%d", i);
@@ -1427,10 +1534,10 @@ for (int i = 0; i<DIR_NUM; i++)
         return -1;
         }
 
         return -1;
         }
 
-    ParseTariffTimeStr(str.c_str(), 
-                       td->dirPrice[i].hDay, 
-                       td->dirPrice[i].mDay, 
-                       td->dirPrice[i].hNight, 
+    ParseTariffTimeStr(str.c_str(),
+                       td->dirPrice[i].hDay,
+                       td->dirPrice[i].mDay,
+                       td->dirPrice[i].hNight,
                        td->dirPrice[i].mNight);
 
     strprintf(&param, "PriceDayA%d", i);
                        td->dirPrice[i].mNight);
 
     strprintf(&param, "PriceDayA%d", i);
@@ -1474,7 +1581,7 @@ for (int i = 0; i<DIR_NUM; i++)
     td->dirPrice[i].priceNightB /= (1024*1024);
 
     strprintf(&param, "Threshold%d", i);
     td->dirPrice[i].priceNightB /= (1024*1024);
 
     strprintf(&param, "Threshold%d", i);
-    if (GetInt(row[5+i*8], &td->dirPrice[i].threshold, 0) < 0)
+    if (GetInt(row[5+i*8], &td->dirPrice[i].threshold) < 0)
         {
         mysql_free_result(res);
         errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
         {
         mysql_free_result(res);
         errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
@@ -1483,7 +1590,7 @@ for (int i = 0; i<DIR_NUM; i++)
         }
 
     strprintf(&param, "SinglePrice%d", i);
         }
 
     strprintf(&param, "SinglePrice%d", i);
-    if (GetInt(row[8+i*8], &td->dirPrice[i].singlePrice, 0) < 0)
+    if (GetInt(row[8+i*8], &td->dirPrice[i].singlePrice) < 0)
         {
         mysql_free_result(res);
         errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
         {
         mysql_free_result(res);
         errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
@@ -1492,7 +1599,7 @@ for (int i = 0; i<DIR_NUM; i++)
         }
 
     strprintf(&param, "NoDiscount%d", i);
         }
 
     strprintf(&param, "NoDiscount%d", i);
-    if (GetInt(row[7+i*8], &td->dirPrice[i].noDiscount, 0) < 0)
+    if (GetInt(row[7+i*8], &td->dirPrice[i].noDiscount) < 0)
         {
         mysql_free_result(res);
         errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
         {
         mysql_free_result(res);
         errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
@@ -1527,7 +1634,7 @@ if (GetDouble(row[1+8*DIR_NUM], &td->tariffConf.passiveCost, 0.0) < 0)
 
     str = row[4+8*DIR_NUM];
     param = "TraffType";
 
     str = row[4+8*DIR_NUM];
     param = "TraffType";
-    
+
     if (str.length() == 0)
         {
         mysql_free_result(res);
     if (str.length() == 0)
         {
         mysql_free_result(res);
@@ -1536,62 +1643,99 @@ if (GetDouble(row[1+8*DIR_NUM], &td->tariffConf.passiveCost, 0.0) < 0)
         return -1;
         }
 
         return -1;
         }
 
-if (!strcasecmp(str.c_str(), "up"))
-    td->tariffConf.traffType = TRAFF_UP;
+td->tariffConf.traffType = TARIFF::StringToTraffType(str);
+
+if (schemaVersion > 0)
+{
+    str = row[5+8*DIR_NUM];
+    param = "Period";
+
+    if (str.length() == 0)
+        {
+        mysql_free_result(res);
+        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+        mysql_close(sock);
+        return -1;
+        }
+
+    td->tariffConf.period = TARIFF::StringToPeriod(str);
+    }
 else
 else
-    if (!strcasecmp(str.c_str(), "down"))
-        td->tariffConf.traffType = TRAFF_DOWN;
-    else
-        if (!strcasecmp(str.c_str(), "up+down"))
-            td->tariffConf.traffType = TRAFF_UP_DOWN;
-        else
-            if (!strcasecmp(str.c_str(), "max"))
-                td->tariffConf.traffType = TRAFF_MAX;
-            else
-                {
-                mysql_free_result(res);
-                errorStr = "Cannot read tariff " + tariffName + ". Parameter TraffType incorrect";
-                mysql_close(sock);
-                return -1;
-                }
+    {
+    td->tariffConf.period = TARIFF::MONTH;
+    }
+
+if (schemaVersion > 1)
+    {
+    str = row[6+8*DIR_NUM];
+    param = "ChangePolicy";
+
+    if (str.length() == 0)
+        {
+        mysql_free_result(res);
+        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+        mysql_close(sock);
+        return -1;
+        }
+
+    td->tariffConf.changePolicy = TARIFF::StringToChangePolicy(str);
+
+    str = row[7+8*DIR_NUM];
+    param = "ChangePolicyTimeout";
+
+    if (str.length() == 0)
+        {
+        mysql_free_result(res);
+        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+        mysql_close(sock);
+        return -1;
+        }
+
+    td->tariffConf.changePolicyTimeout = readTime(str);
+    }
+else
+    {
+    td->tariffConf.changePolicy = TARIFF::ALLOW;
+    td->tariffConf.changePolicyTimeout = 0;
+    }
 
 mysql_free_result(res);
 mysql_close(sock);
 return 0;
 }
 //-----------------------------------------------------------------------------
 
 mysql_free_result(res);
 mysql_close(sock);
 return 0;
 }
 //-----------------------------------------------------------------------------
-int MYSQL_STORE::SaveTariff(const TARIFF_DATA & td, const string & tariffName) const
+int MYSQL_STORE::SaveTariff(const TARIFF_DATA & td, const std::string & tariffName) const
 {
 {
-string param;
+std::string param;
 
 
-string res="UPDATE tariffs SET";
+std::string res="UPDATE tariffs SET";
 
 for (int i = 0; i < DIR_NUM; i++)
     {
 
 for (int i = 0; i < DIR_NUM; i++)
     {
-    strprintf(&param, " PriceDayA%d=%f,", i, 
+    strprintf(&param, " PriceDayA%d=%f,", i,
         td.dirPrice[i].priceDayA * pt_mega);
     res += param;
 
         td.dirPrice[i].priceDayA * pt_mega);
     res += param;
 
-    strprintf(&param, " PriceDayB%d=%f,", i, 
-        td.dirPrice[i].priceDayB * pt_mega);        
+    strprintf(&param, " PriceDayB%d=%f,", i,
+        td.dirPrice[i].priceDayB * pt_mega);
     res += param;
     res += param;
-        
+
     strprintf(&param, " PriceNightA%d=%f,", i,
         td.dirPrice[i].priceNightA * pt_mega);
     res += param;
 
     strprintf(&param, " PriceNightA%d=%f,", i,
         td.dirPrice[i].priceNightA * pt_mega);
     res += param;
 
-    strprintf(&param, " PriceNightB%d=%f,", i, 
+    strprintf(&param, " PriceNightB%d=%f,", i,
         td.dirPrice[i].priceNightB * pt_mega);
     res += param;
         td.dirPrice[i].priceNightB * pt_mega);
     res += param;
-        
-    strprintf(&param, " Threshold%d=%d,", i, 
+
+    strprintf(&param, " Threshold%d=%d,", i,
         td.dirPrice[i].threshold);
     res += param;
 
         td.dirPrice[i].threshold);
     res += param;
 
-    string s;
+    std::string s;
     strprintf(&param, " Time%d", i);
 
     strprintf(&param, " Time%d", i);
 
-    strprintf(&s, "%0d:%0d-%0d:%0d", 
+    strprintf(&s, "%0d:%0d-%0d:%0d",
             td.dirPrice[i].hDay,
             td.dirPrice[i].mDay,
             td.dirPrice[i].hNight,
             td.dirPrice[i].hDay,
             td.dirPrice[i].mDay,
             td.dirPrice[i].hNight,
@@ -1599,11 +1743,11 @@ for (int i = 0; i < DIR_NUM; i++)
 
     res += (param + "='" + s + "',");
 
 
     res += (param + "='" + s + "',");
 
-    strprintf(&param, " NoDiscount%d=%d,", i, 
+    strprintf(&param, " NoDiscount%d=%d,", i,
         td.dirPrice[i].noDiscount);
     res += param;
 
         td.dirPrice[i].noDiscount);
     res += param;
 
-    strprintf(&param, " SinglePrice%d=%d,", i, 
+    strprintf(&param, " SinglePrice%d=%d,", i,
         td.dirPrice[i].singlePrice);
     res += param;
     }
         td.dirPrice[i].singlePrice);
     res += param;
     }
@@ -1617,27 +1761,21 @@ res += param;
 strprintf(&param, " Free=%f,", td.tariffConf.free);
 res += param;
 
 strprintf(&param, " Free=%f,", td.tariffConf.free);
 res += param;
 
-switch (td.tariffConf.traffType)
-    {
-    case TRAFF_UP:
-        res += " TraffType='up'";
-        break;
-    case TRAFF_DOWN:
-        res += " TraffType='down'";
-        break;
-    case TRAFF_UP_DOWN:
-        res += " TraffType='up+down'";
-        break;
-    case TRAFF_MAX:
-        res += " TraffType='max'";
-        break;
-    }
+res += " TraffType='" + TARIFF::TraffTypeToString(td.tariffConf.traffType) + "'";
+
+if (schemaVersion > 0)
+    res += ", Period='" + TARIFF::PeriodToString(td.tariffConf.period) + "'";
+
+if (schemaVersion > 1)
+    res += ", change_policy='" + TARIFF::ChangePolicyToString(td.tariffConf.changePolicy) + "'"\
+           ", change_policy_timeout='" + formatTime(td.tariffConf.changePolicy) + "'";
+
 strprintf(&param, " WHERE name='%s' LIMIT 1", tariffName.c_str());
 res += param;
 
 if(MysqlSetQuery(res.c_str()))
 {
 strprintf(&param, " WHERE name='%s' LIMIT 1", tariffName.c_str());
 res += param;
 
 if(MysqlSetQuery(res.c_str()))
 {
-    errorStr = "Couldn't save admin:\n";
+    errorStr = "Couldn't save tariff:\n";
     //errorStr += mysql_error(sock);
     return -1;
 }
     //errorStr += mysql_error(sock);
     return -1;
 }
@@ -1645,11 +1783,11 @@ if(MysqlSetQuery(res.c_str()))
 return 0;
 }
 //-----------------------------------------------------------------------------
 return 0;
 }
 //-----------------------------------------------------------------------------
-int MYSQL_STORE::WriteDetailedStat(const map<IP_DIR_PAIR, STAT_NODE> & statTree, 
-                                   time_t lastStat, 
-                                   const string & login) const
+int MYSQL_STORE::WriteDetailedStat(const std::map<IP_DIR_PAIR, STAT_NODE> & statTree,
+                                   time_t lastStat,
+                                   const std::string & login) const
 {
 {
-string res, stTime, endTime, tempStr;
+std::string res, stTime, endTime, tempStr;
 time_t t;
 tm * lt;
 
 time_t t;
 tm * lt;
 
@@ -1679,7 +1817,7 @@ if (!(result=mysql_list_tables(sock,tempStr.c_str() )))
     return -1;
 }
 
     return -1;
 }
 
-unsigned int num_rows =  mysql_num_rows(result);
+my_ulonglong num_rows =  mysql_num_rows(result);
 
 mysql_free_result(result);
 
 
 mysql_free_result(result);
 
@@ -1690,7 +1828,7 @@ if (num_rows < 1)
         "IP VARCHAR(17) DEFAULT '',dir INT DEFAULT 0,"\
         "down BIGINT DEFAULT 0,up BIGINT DEFAULT 0, cash DOUBLE DEFAULT 0.0, INDEX (login), INDEX(dir), INDEX(day), INDEX(IP))",
     lt->tm_mon+1, lt->tm_year+1900);
         "IP VARCHAR(17) DEFAULT '',dir INT DEFAULT 0,"\
         "down BIGINT DEFAULT 0,up BIGINT DEFAULT 0, cash DOUBLE DEFAULT 0.0, INDEX (login), INDEX(dir), INDEX(day), INDEX(IP))",
     lt->tm_mon+1, lt->tm_year+1900);
-    
+
     if(MysqlQuery(qbuf,sock))
     {
         errorStr = "Couldn't create WriteDetailedStat table:\n";
     if(MysqlQuery(qbuf,sock))
     {
         errorStr = "Couldn't create WriteDetailedStat table:\n";
@@ -1717,12 +1855,12 @@ lt2 = localtime(&t);
 h2 = lt2->tm_hour;
 m2 = lt2->tm_min;
 s2 = lt2->tm_sec;
 h2 = lt2->tm_hour;
 m2 = lt2->tm_min;
 s2 = lt2->tm_sec;
-    
+
 strprintf(&stTime, "%02d:%02d:%02d", h1, m1, s1);
 strprintf(&endTime, "%02d:%02d:%02d", h2, m2, s2);
 
 strprintf(&res,"INSERT INTO detailstat_%02d_%4d SET login='%s',"\
 strprintf(&stTime, "%02d:%02d:%02d", h1, m1, s1);
 strprintf(&endTime, "%02d:%02d:%02d", h2, m2, s2);
 
 strprintf(&res,"INSERT INTO detailstat_%02d_%4d SET login='%s',"\
-    "day=%d,startTime='%s',endTime='%s',", 
+    "day=%d,startTime='%s',endTime='%s',",
     lt->tm_mon+1, lt->tm_year+1900,
     login.c_str(),
     lt->tm_mday,
     lt->tm_mon+1, lt->tm_year+1900,
     login.c_str(),
     lt->tm_mday,
@@ -1730,19 +1868,19 @@ strprintf(&res,"INSERT INTO detailstat_%02d_%4d SET login='%s',"\
     endTime.c_str()
     );
 
     endTime.c_str()
     );
 
-map<IP_DIR_PAIR, STAT_NODE>::const_iterator stIter;
+std::map<IP_DIR_PAIR, STAT_NODE>::const_iterator stIter;
 stIter = statTree.begin();
 
 while (stIter != statTree.end())
     {
 stIter = statTree.begin();
 
 while (stIter != statTree.end())
     {
-        strprintf(&tempStr,"IP='%s', dir=%d, down=%lld, up=%lld, cash=%f", 
+        strprintf(&tempStr,"IP='%s', dir=%d, down=%lld, up=%lld, cash=%f",
                 inet_ntostring(stIter->first.ip).c_str(),
                 inet_ntostring(stIter->first.ip).c_str(),
-                stIter->first.dir, 
-                stIter->second.down, 
-                stIter->second.up, 
+                stIter->first.dir,
+                stIter->second.down,
+                stIter->second.up,
                 stIter->second.cash
             );
                 stIter->second.cash
             );
-    
+
         if( MysqlQuery((res+tempStr).c_str(),sock) )
         {
             errorStr = "Couldn't insert data in WriteDetailedStat:\n";
         if( MysqlQuery((res+tempStr).c_str(),sock) )
         {
             errorStr = "Couldn't insert data in WriteDetailedStat:\n";
@@ -1761,19 +1899,19 @@ mysql_close(sock);
 return 0;
 }
 //-----------------------------------------------------------------------------
 return 0;
 }
 //-----------------------------------------------------------------------------
-int MYSQL_STORE::AddMessage(STG_MSG * msg, const string & login) const
+int MYSQL_STORE::AddMessage(STG_MSG * msg, const std::string & login) const
 {
 struct timeval tv;
 
 gettimeofday(&tv, NULL);
 
 {
 struct timeval tv;
 
 gettimeofday(&tv, NULL);
 
-msg->header.id = ((long long)tv.tv_sec) * 1000000 + ((long long)tv.tv_usec);
+msg->header.id = static_cast<uint64_t>(tv.tv_sec) * 1000000 + static_cast<uint64_t>(tv.tv_usec);
 
 
-sprintf(qbuf,"INSERT INTO messages SET login='%s', id=%lld", 
+sprintf(qbuf,"INSERT INTO messages SET login='%s', id=%lld",
     login.c_str(),
     login.c_str(),
-    (long long)msg->header.id
+    static_cast<long long>(msg->header.id)
     );
     );
-    
+
 if(MysqlSetQuery(qbuf))
 {
     errorStr = "Couldn't add message:\n";
 if(MysqlSetQuery(qbuf))
 {
     errorStr = "Couldn't add message:\n";
@@ -1784,13 +1922,13 @@ if(MysqlSetQuery(qbuf))
 return EditMessage(*msg, login);
 }
 //-----------------------------------------------------------------------------
 return EditMessage(*msg, login);
 }
 //-----------------------------------------------------------------------------
-int MYSQL_STORE::EditMessage(const STG_MSG & msg, const string & login) const
+int MYSQL_STORE::EditMessage(const STG_MSG & msg, const std::string & login) const
 {
 {
-string res;
+std::string res;
 
 strprintf(&res,"UPDATE messages SET type=%d, lastSendTime=%u, creationTime=%u, "\
     "showTime=%u, stgRepeat=%d, repeatPeriod=%u, text='%s' "\
 
 strprintf(&res,"UPDATE messages SET type=%d, lastSendTime=%u, creationTime=%u, "\
     "showTime=%u, stgRepeat=%d, repeatPeriod=%u, text='%s' "\
-    "WHERE login='%s' AND id=%lld LIMIT 1", 
+    "WHERE login='%s' AND id=%lld LIMIT 1",
     msg.header.type,
     msg.header.lastSendTime,
     msg.header.creationTime,
     msg.header.type,
     msg.header.lastSendTime,
     msg.header.creationTime,
@@ -1799,7 +1937,7 @@ strprintf(&res,"UPDATE messages SET type=%d, lastSendTime=%u, creationTime=%u, "
     msg.header.repeatPeriod,
     (ReplaceStr(msg.text,badSyms,repSym)).c_str(),
     login.c_str(),
     msg.header.repeatPeriod,
     (ReplaceStr(msg.text,badSyms,repSym)).c_str(),
     login.c_str(),
-    (long long)msg.header.id
+    msg.header.id
     );
 
 if(MysqlSetQuery(res.c_str()))
     );
 
 if(MysqlSetQuery(res.c_str()))
@@ -1812,7 +1950,7 @@ if(MysqlSetQuery(res.c_str()))
 return 0;
 }
 //-----------------------------------------------------------------------------
 return 0;
 }
 //-----------------------------------------------------------------------------
-int MYSQL_STORE::GetMessage(uint64_t id, STG_MSG * msg, const string & login) const
+int MYSQL_STORE::GetMessage(uint64_t id, STG_MSG * msg, const std::string & login) const
 {
 MYSQL_RES *res;
 MYSQL_ROW row;
 {
 MYSQL_RES *res;
 MYSQL_ROW row;
@@ -1820,7 +1958,7 @@ MYSQL * sock;
 
 sprintf(qbuf,"SELECT * FROM messages WHERE login='%s' AND id=%llu LIMIT 1",
         login.c_str(), static_cast<unsigned long long>(id));
 
 sprintf(qbuf,"SELECT * FROM messages WHERE login='%s' AND id=%llu LIMIT 1",
         login.c_str(), static_cast<unsigned long long>(id));
-    
+
 if(MysqlGetQuery(qbuf,sock))
 {
     errorStr = "Couldn't GetMessage:\n";
 if(MysqlGetQuery(qbuf,sock))
 {
     errorStr = "Couldn't GetMessage:\n";
@@ -1895,11 +2033,11 @@ mysql_close(sock);
 return 0;
 }
 //-----------------------------------------------------------------------------
 return 0;
 }
 //-----------------------------------------------------------------------------
-int MYSQL_STORE::DelMessage(uint64_t id, const string & login) const
+int MYSQL_STORE::DelMessage(uint64_t id, const std::string & login) const
 {
 {
-sprintf(qbuf,"DELETE FROM messages WHERE login='%s' AND id=%lld LIMIT 1", 
-    login.c_str(),(long long)id);
-    
+sprintf(qbuf,"DELETE FROM messages WHERE login='%s' AND id=%lld LIMIT 1",
+        login.c_str(), static_cast<long long>(id));
+
 if(MysqlSetQuery(qbuf))
 {
     errorStr = "Couldn't delete Message:\n";
 if(MysqlSetQuery(qbuf))
 {
     errorStr = "Couldn't delete Message:\n";
@@ -1910,13 +2048,13 @@ if(MysqlSetQuery(qbuf))
 return 0;
 }
 //-----------------------------------------------------------------------------
 return 0;
 }
 //-----------------------------------------------------------------------------
-int MYSQL_STORE::GetMessageHdrs(vector<STG_MSG_HDR> * hdrsList, const string & login) const
+int MYSQL_STORE::GetMessageHdrs(std::vector<STG_MSG_HDR> * hdrsList, const std::string & login) const
 {
 MYSQL_RES *res;
 MYSQL_ROW row;
 MYSQL * sock;
 sprintf(qbuf,"SELECT * FROM messages WHERE login='%s'", login.c_str());
 {
 MYSQL_RES *res;
 MYSQL_ROW row;
 MYSQL * sock;
 sprintf(qbuf,"SELECT * FROM messages WHERE login='%s'", login.c_str());
-    
+
 if(MysqlGetQuery(qbuf,sock))
 {
     errorStr = "Couldn't GetMessageHdrs:\n";
 if(MysqlGetQuery(qbuf,sock))
 {
     errorStr = "Couldn't GetMessageHdrs:\n";
@@ -1933,17 +2071,18 @@ if (!(res=mysql_store_result(sock)))
     return -1;
 }
 
     return -1;
 }
 
-unsigned int i, num_rows =  mysql_num_rows(res);
-long long int unsigned id = 0;
+unsigned int i;
+my_ulonglong num_rows = mysql_num_rows(res);
+uint64_t id = 0;
 
 
-for (i=0; i<num_rows; i++)
+for (i = 0; i < num_rows; i++)
 {
     row = mysql_fetch_row(res);
     if (str2x(row[1], id))
         continue;
 {
     row = mysql_fetch_row(res);
     if (str2x(row[1], id))
         continue;
-    
+
     STG_MSG_HDR hdr;
     STG_MSG_HDR hdr;
-    if (row[2]) 
+    if (row[2])
         if(str2x(row[2], hdr.type))
             continue;
 
         if(str2x(row[2], hdr.type))
             continue;