]> git.stg.codes - stg.git/blobdiff - projects/stargazer/plugins/store/mysql/mysql_store.cpp
Tarball generation cleanup.
[stg.git] / projects / stargazer / plugins / store / mysql / mysql_store.cpp
index 3e61498f5785f8e40bb7cb293f3c47586883c96b..cef72671b1c5e6b68b4b0d88c5e22b65d16d5ebd 100644 (file)
@@ -7,6 +7,7 @@
 #include <mysql.h>
 #include <errmsg.h>
 
 #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/user_ips.h"
 #include "stg/user_conf.h"
 #include "stg/user_stat.h"
@@ -30,10 +31,10 @@ template <typename T>
 int GetInt(const std::string & str, T * val, T defaultVal = T())
 {
     char *res;
 int GetInt(const std::string & str, T * val, T defaultVal = T())
 {
     char *res;
-    
+
     *val = static_cast<T>(strtoll(str.c_str(), &res, 10));
     *val = static_cast<T>(strtoll(str.c_str(), &res, 10));
-    
-    if (*res != 0) 
+
+    if (*res != 0)
     {
         *val = defaultVal; //Error!
         return EINVAL;
     {
         *val = defaultVal; //Error!
         return EINVAL;
@@ -45,10 +46,10 @@ int GetInt(const std::string & str, T * val, T defaultVal = T())
 int GetDouble(const std::string & str, double * val, double defaultVal)
 {
     char *res;
 int GetDouble(const std::string & str, double * val, double defaultVal)
 {
     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;
@@ -60,10 +61,10 @@ int GetDouble(const std::string & str, double * val, double defaultVal)
 int GetTime(const std::string & str, time_t * val, time_t defaultVal)
 {
     char *res;
 int GetTime(const std::string & str, time_t * val, time_t defaultVal)
 {
     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;
@@ -86,17 +87,17 @@ std::string ReplaceStr(std::string source, const std::string & symlist, const ch
 int GetULongLongInt(const std::string & str, uint64_t * val, uint64_t defaultVal)
 {
     char *res;
 int GetULongLongInt(const std::string & str, uint64_t * val, uint64_t defaultVal)
 {
     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;
 }
@@ -111,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 std::vector<PARAM_VALUE> & moduleParams, 
-                        const std::string & name, std::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;
 std::vector<PARAM_VALUE>::const_iterator pvi;
 pvi = find(moduleParams.begin(), moduleParams.end(), pv);
 {
 PARAM_VALUE pv;
 pv.param = name;
 std::vector<PARAM_VALUE>::const_iterator pvi;
 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;
@@ -159,10 +155,7 @@ 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"))
 {
       schemaVersion(0),
       logger(GetPluginLogger(GetStgLogger(), "store_mysql"))
 {
@@ -182,7 +175,7 @@ int    MYSQL_STORE::MysqlQuery(const char* sQuery,MYSQL * sock) const
                 return 0;
         }
     }
                 return 0;
         }
     }
-    
+
     return ret;
 }
 //-----------------------------------------------------------------------------
     return ret;
 }
 //-----------------------------------------------------------------------------
@@ -217,7 +210,7 @@ else
          if(mysql_select_db(sock, storeSettings.GetDBName().c_str()))
          {
              std::string res = "CREATE DATABASE " + storeSettings.GetDBName();
          if(mysql_select_db(sock, storeSettings.GetDBName().c_str()))
          {
              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";
@@ -229,12 +222,13 @@ 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
             }
         }
         else
@@ -319,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";
@@ -331,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";
@@ -346,38 +340,40 @@ 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')";
-    
+        "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";
@@ -387,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',period='month'";
-    
+        "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";
@@ -449,7 +446,7 @@ if(!IsTablePresent("tariffs",sock))
         mysql_close(sock);
         return -1;
     }
         mysql_close(sock);
         return -1;
     }
-    schemaVersion = 1;
+    schemaVersion = 2;
 }
 
 //users-----------------------------------------------------------------------
 }
 
 //users-----------------------------------------------------------------------
@@ -460,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";
@@ -501,25 +498,25 @@ if(!IsTablePresent("users",sock))
         "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='',NAS='',";
         "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='',NAS='',";
-    
+
     for (int i = 0; i < USERDATA_NUM; i++)
         {
         strprintf(&param, " Userdata%d='',", i);
         res += param;
         }
     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";
@@ -533,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";
@@ -548,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";
@@ -562,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";
@@ -607,22 +604,43 @@ if (schemaVersion  < 1)
     schemaVersion = 1;
     logger("MYSQL_STORE: Updated DB schema to version %d", schemaVersion);
     }
     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;
 }
 //-----------------------------------------------------------------------------
 
 return 0;
 }
 //-----------------------------------------------------------------------------
 
-int MYSQL_STORE::GetAllParams(std::vector<std::string> * ParamList, 
+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;
 my_ulonglong num, i;
                             const std::string & table, const std::string & name) const
 {
 MYSQL_RES *res;
 MYSQL_ROW row;
 MYSQL * sock=NULL;
 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: ";
@@ -644,7 +662,7 @@ 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]);
 }
 
@@ -699,7 +717,7 @@ return 0;
 int MYSQL_STORE::DelUser(const std::string & login) const
 {
 sprintf(qbuf,"DELETE FROM users WHERE login='%s' LIMIT 1", login.c_str());
 int MYSQL_STORE::DelUser(const std::string & login) const
 {
 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";
@@ -731,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";
@@ -801,7 +819,7 @@ if (GetInt(row[5], &conf->alwaysOnline) != 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.";
@@ -832,7 +850,7 @@ for (int i = 0; i < USERDATA_NUM; i++)
     }
 
 GetTime(row[15+USERDATA_NUM], &conf->creditExpire, 0);
     }
 
 GetTime(row[15+USERDATA_NUM], &conf->creditExpire, 0);
-    
+
 std::string ipStr = row[16+USERDATA_NUM];
 USER_IPS i;
 try
 std::string ipStr = row[16+USERDATA_NUM];
 USER_IPS i;
 try
@@ -875,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";
@@ -984,7 +1002,7 @@ 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,
@@ -1003,11 +1021,11 @@ 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;
 
@@ -1047,7 +1065,7 @@ for (int i = 0; i < DIR_NUM; i++)
     }
 
 strprintf(&param, " Cash=%f, FreeMb=%f, LastCashAdd=%f, LastCashAddTime=%d,"\
     }
 
 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,
@@ -1102,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";
@@ -1192,24 +1210,24 @@ logStr += "\'";
 return WriteLogString(logStr, login);
 }
 //-----------------------------------------------------------------------------
 return WriteLogString(logStr, login);
 }
 //-----------------------------------------------------------------------------
-int MYSQL_STORE::SaveMonthStat(const USER_STAT & stat, int month, int year, 
+int MYSQL_STORE::SaveMonthStat(const USER_STAT & stat, int month, int year,
                                 const std::string & login) const
 {
 std::string param, res;
 
                                 const std::string & login) const
 {
 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.monthUp[i]); 
+    strprintf(&param, " U%d=%lld,", i, stat.monthUp[i]);
     res += param;
 
     res += param;
 
-    strprintf(&param, " D%d=%lld,", i, stat.monthDown[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()))
@@ -1225,7 +1243,7 @@ return 0;
 int MYSQL_STORE::AddAdmin(const std::string & login) const
 {
 sprintf(qbuf,"INSERT INTO admins SET login='%s'", login.c_str());
 int MYSQL_STORE::AddAdmin(const std::string & login) const
 {
 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";
@@ -1239,7 +1257,7 @@ return 0;
 int MYSQL_STORE::DelAdmin(const std::string & login) const
 {
 sprintf(qbuf,"DELETE FROM admins where login='%s' LIMIT 1", login.c_str());
 int MYSQL_STORE::DelAdmin(const std::string & login) const
 {
 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";
@@ -1275,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,
@@ -1311,7 +1329,7 @@ MYSQL_RES *res;
 MYSQL_ROW row;
 MYSQL * sock;
 sprintf(qbuf,"SELECT * FROM admins WHERE login='%s' LIMIT 1", login.c_str());
 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";
@@ -1335,7 +1353,7 @@ 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];
@@ -1372,7 +1390,7 @@ ac->password = password;
 
 uint16_t a;
 
 
 uint16_t a;
 
-if (GetInt(row[2], &a) == 0) 
+if (GetInt(row[2], &a) == 0)
     ac->priv.userConf = a;
 else
     {
     ac->priv.userConf = a;
 else
     {
@@ -1382,7 +1400,7 @@ else
     return -1;
     }
 
     return -1;
     }
 
-if (GetInt(row[3], &a) == 0) 
+if (GetInt(row[3], &a) == 0)
     ac->priv.userPasswd = a;
 else
     {
     ac->priv.userPasswd = a;
 else
     {
@@ -1392,7 +1410,7 @@ else
     return -1;
     }
 
     return -1;
     }
 
-if (GetInt(row[4], &a) == 0) 
+if (GetInt(row[4], &a) == 0)
     ac->priv.userStat = a;
 else
     {
     ac->priv.userStat = a;
 else
     {
@@ -1402,7 +1420,7 @@ else
     return -1;
     }
 
     return -1;
     }
 
-if (GetInt(row[5], &a) == 0) 
+if (GetInt(row[5], &a) == 0)
     ac->priv.userCash = a;
 else
     {
     ac->priv.userCash = a;
 else
     {
@@ -1412,7 +1430,7 @@ else
     return -1;
     }
 
     return -1;
     }
 
-if (GetInt(row[6], &a) == 0) 
+if (GetInt(row[6], &a) == 0)
     ac->priv.userAddDel = a;
 else
     {
     ac->priv.userAddDel = a;
 else
     {
@@ -1422,7 +1440,7 @@ else
     return -1;
     }
 
     return -1;
     }
 
-if (GetInt(row[7], &a) == 0) 
+if (GetInt(row[7], &a) == 0)
     ac->priv.tariffChg = a;
 else
     {
     ac->priv.tariffChg = a;
 else
     {
@@ -1432,7 +1450,7 @@ else
     return -1;
     }
 
     return -1;
     }
 
-if (GetInt(row[8], &a) == 0) 
+if (GetInt(row[8], &a) == 0)
     ac->priv.adminChg = a;
 else
     {
     ac->priv.adminChg = a;
 else
     {
@@ -1450,7 +1468,7 @@ return 0;
 int MYSQL_STORE::AddTariff(const std::string & name) const
 {
 sprintf(qbuf,"INSERT INTO tariffs SET name='%s'", name.c_str());
 int MYSQL_STORE::AddTariff(const std::string & name) const
 {
 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";
@@ -1464,7 +1482,7 @@ return 0;
 int MYSQL_STORE::DelTariff(const std::string & name) const
 {
 sprintf(qbuf,"DELETE FROM tariffs WHERE name='%s' LIMIT 1", name.c_str());
 int MYSQL_STORE::DelTariff(const std::string & name) const
 {
 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: ";
@@ -1481,7 +1499,7 @@ MYSQL_RES *res;
 MYSQL_ROW row;
 MYSQL * sock;
 sprintf(qbuf,"SELECT * FROM tariffs WHERE name='%s' LIMIT 1", tariffName.c_str());
 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";
@@ -1516,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);
@@ -1616,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);
@@ -1625,24 +1643,7 @@ 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;
-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.traffType = TARIFF::StringToTraffType(str);
 
 if (schemaVersion > 0)
 {
 
 if (schemaVersion > 0)
 {
@@ -1664,6 +1665,40 @@ else
     td->tariffConf.period = TARIFF::MONTH;
     }
 
     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;
@@ -1677,30 +1712,30 @@ 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;
 
     std::string s;
     strprintf(&param, " Time%d", i);
 
         td.dirPrice[i].threshold);
     res += param;
 
     std::string s;
     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,
@@ -1708,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;
     }
@@ -1726,25 +1761,15 @@ 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 > 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;
 
 strprintf(&param, " WHERE name='%s' LIMIT 1", tariffName.c_str());
 res += param;
 
@@ -1758,8 +1783,8 @@ if(MysqlSetQuery(res.c_str()))
 return 0;
 }
 //-----------------------------------------------------------------------------
 return 0;
 }
 //-----------------------------------------------------------------------------
-int MYSQL_STORE::WriteDetailedStat(const std::map<IP_DIR_PAIR, STAT_NODE> & statTree, 
-                                   time_t lastStat, 
+int MYSQL_STORE::WriteDetailedStat(const std::map<IP_DIR_PAIR, STAT_NODE> & statTree,
+                                   time_t lastStat,
                                    const std::string & login) const
 {
 std::string res, stTime, endTime, tempStr;
                                    const std::string & login) const
 {
 std::string res, stTime, endTime, tempStr;
@@ -1803,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";
@@ -1830,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,
@@ -1848,14 +1873,14 @@ stIter = statTree.begin();
 
 while (stIter != statTree.end())
     {
 
 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";
@@ -1882,11 +1907,11 @@ gettimeofday(&tv, NULL);
 
 msg->header.id = static_cast<uint64_t>(tv.tv_sec) * 1000000 + static_cast<uint64_t>(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(),
     static_cast<long long>(msg->header.id)
     );
     login.c_str(),
     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";
@@ -1903,7 +1928,7 @@ 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,
@@ -1933,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";
@@ -2010,9 +2035,9 @@ return 0;
 //-----------------------------------------------------------------------------
 int MYSQL_STORE::DelMessage(uint64_t id, const std::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", 
+sprintf(qbuf,"DELETE FROM messages WHERE login='%s' AND id=%lld LIMIT 1",
         login.c_str(), static_cast<long long>(id));
         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";
@@ -2029,7 +2054,7 @@ MYSQL_RES *res;
 MYSQL_ROW row;
 MYSQL * sock;
 sprintf(qbuf,"SELECT * FROM messages WHERE login='%s'", login.c_str());
 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";
@@ -2055,9 +2080,9 @@ 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;