/*
специальная версия для trading-shop.ru
для использования разработчиками в магазине
*/
/*
в начале кода подключаем и настраиваем на ID товара. ID берем из вкладки Дополнительно при создании товара, либо в EA Protect - Продукты
const int PRODUCT_ID=3265;//Index Scalper PRO MT4
const string VERSION="3.50"; //номер версии при обновлении меняем тоже, это на будущее когда будет доступна првоерка версий и обновления
#include <EA_Protect/Protect.mqh>
SHOW_LICENSE_PARAMS
PROTECT_CREATE
----
Данные макросы нужно встроить в указаные функции.
PROTECT_INIT - в функцию OnInit, инициализация
PROTECT_DEINIT в функцию OnDeinit, деинициализация
PROTECT_EVENT в функцию OnChartEvent, прием сообщений внутренних и резервный таймер
PROTECT_TIMER в функцию OnTimer, опрос по таймеру данных с сайта
статус защиты в любом месте можно получить через переменную PROTECT_STATUS
возвращает true - если все в порядке или false если проблемы. Статус при опросах пишет в журнал.
После компиляции компилируем дополнительно с помощью защиты от MQL5 Сервис - MQL5 Cloud Protector - это обязательно делать необходимо.
void OnTimer() { PROTECT_TIMER }
void OnChartEvent(const int id,const long& lparam,const double& dparam,const string& sparam){PROTECT_EVENT}
На сайт загружать все в архиве zip
желательно в архиве чтобы было все по папкам
MQL4 / MQL5
Experts
Indicators
*/
#ifndef __CPROTECT__
#define __CPROTECT__ sovetnikov_net_protect
#property strict
#include <EA_Protect\defines.mqh>
#include <EA_Protect\Draw.mqh>
#include <EA_Protect\Bcrypt.mqh>
#include <EA_Protect\Time.mqh>
#define RESTART_PROTECT CHARTEVENT_CUSTOM+321
#ifndef LICENSE_OFF
#define SHOW_LICENSE_PARAMS input string LicenseKey=""; //LicenseKey
#endif
#define READURL_BUFFER_SIZE 1024
#define LICENSE_ACCOUNT 1
#define LICENSE_VPS 2
#define SERVERS_FILE_NAME "servers-protect.ini"
#ifdef IS_INDICATOR
#ifndef WININET_API_LIB
#define HINTERNET int
#define BOOL int
#define INTERNET_PORT int
#define DWORD int
#define DWORD_PTR int
#define LPDWORD int&
#define LPVOID uchar&
#define LPCTSTR string&
#endif
#import "wininet.dll"
DWORD InternetAttemptConnect(DWORD dwReserved);
HINTERNET InternetOpenW(LPCTSTR lpszAgent, DWORD dwAccessType, LPCTSTR lpszProxyName, LPCTSTR lpszProxyBypass, DWORD dwFlags);
HINTERNET InternetConnectW(HINTERNET hInternet, LPCTSTR lpszServerName, INTERNET_PORT nServerPort, LPCTSTR lpszUsername, LPCTSTR lpszPassword, DWORD dwService, DWORD dwFlags, DWORD_PTR dwContext);
HINTERNET HttpOpenRequestW(HINTERNET hConnect, LPCTSTR lpszVerb, LPCTSTR lpszObjectName, LPCTSTR lpszVersion, LPCTSTR lpszReferer, int /*LPCTSTR* */ lplpszAcceptTypes, uint/*DWORD*/ dwFlags, DWORD_PTR dwContext);
BOOL HttpSendRequestW(HINTERNET hRequest, LPCTSTR lpszHeaders, DWORD dwHeadersLength, LPVOID lpOptional[], DWORD dwOptionalLength);
HINTERNET InternetOpenUrlW(HINTERNET hInternet, LPCTSTR lpszUrl, LPCTSTR lpszHeaders, DWORD dwHeadersLength, uint/*DWORD*/ dwFlags, DWORD_PTR dwContext);
BOOL InternetReadFile(HINTERNET hFile, LPVOID lpBuffer[], DWORD dwNumberOfBytesToRead, LPDWORD lpdwNumberOfBytesRead);
BOOL InternetCloseHandle(HINTERNET hInternet);
BOOL InternetSetOptionW(HINTERNET hInternet, DWORD dwOption, LPDWORD lpBuffer, DWORD dwBufferLength);
BOOL InternetQueryOptionW(HINTERNET hInternet, DWORD dwOption, LPDWORD lpBuffer, LPDWORD lpdwBufferLength);
#import
#else
int InternetOpenW(string&,int,string&,string&,int) {return 0;}
int InternetOpenUrlW(int,string&,string&,uint,uint,uint) {return 0;}
int InternetCloseHandle(int) {return 0;}
int InternetReadFile(int,uchar &arr[],int ic,int &iarr[]) {return 0;}
bool DeleteUrlCacheEntry(string url) {return false;}
#endif
#ifdef __MQL5__
#ifndef __MQL4__TO__MQL5__
double AccountBalance()
{
return AccountInfoDouble(ACCOUNT_BALANCE);
}
double AccountEquity()
{
return AccountInfoDouble(ACCOUNT_EQUITY);
}
double AccountMargin()
{
return AccountInfoDouble(ACCOUNT_MARGIN);
}
double AccountFreeMargin()
{
return AccountInfoDouble(ACCOUNT_MARGIN_FREE);
}
string AccountCurrency()
{
return AccountInfoString(ACCOUNT_CURRENCY);
}
#endif
#endif
string SystemDriveSerialNumber()
{
string sVolumeSerialNumber="1234-4321";
#ifndef LICENSE_OFF
sVolumeSerialNumber=md5(IntegerToString(AccountInfoInteger(ACCOUNT_LOGIN)));
if(!IsTesting() && !IsOptimization())
{
if(FileIsExist("hwid.ini",FILE_COMMON))
{
int ihwid=FileOpen("hwid.ini",FILE_READ|FILE_SHARE_READ|FILE_COMMON|FILE_ANSI);
if(ihwid!=INVALID_HANDLE)
{
sVolumeSerialNumber=FileReadString(ihwid);
FileClose(ihwid);
}
}
else
{
int ihwid=FileOpen("hwid.ini",FILE_WRITE|FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_COMMON|FILE_ANSI);
if(ihwid!=INVALID_HANDLE)
{
FileWriteString(ihwid,sVolumeSerialNumber);
FileClose(ihwid);
}
}
}
#endif
return sVolumeSerialNumber;
}
string IntToHexString(int integer_number)
{
string hex_string="00000000";
int value,shift=28;
for(int i=0; i<8; i++)
{
value=(integer_number>>shift)&0x0F;
if(value<10)
StringSetCharacter(hex_string,i,ushort(value+'0'));
else
StringSetCharacter(hex_string,i,ushort((value-10)+'A'));
shift-=4;
}
return(hex_string);
}
string md5(const string value)
{
const string EMPTY_MD5 = "d41d8cd98f00b204e9800998ecf8427e";
if(value == "")
{
return EMPTY_MD5;
}
uchar result[];
const uchar key[1]= {0};
uchar data[];
StringToCharArray(value, data, 0, StringLen(value));
CryptEncode(CRYPT_HASH_MD5, data, key, result);
string resultStr = "";
for(int i = 0; i < ArraySize(result); i++)
{
resultStr = resultStr + StringFormat("%02x", result[i]);
}
ArrayFree(result);
ArrayFree(data);
return resultStr;
}
#ifndef LICENSE_OFF
#define PROTECT_CREATE protect_config config;\
CProtect protect;
#ifdef LICENSE_PANEL
#define PROTECT_INIT config.product_id=PRODUCT_ID;\
config.version=VERSION;\
config.admin_id=ADMIN_ID;\
config.token=LicenseKey;\
protect.OnInit(config);
#else
#define PROTECT_INIT config.product_id=PRODUCT_ID;\
config.version=VERSION;\
config.token=LicenseKey;\
protect.OnInit(config);
#endif
#define PROTECT_DEINIT protect.OnDeinit();
#define PROTECT_EVENT protect.OnChartEvent(id,lparam,dparam,sparam);
#define PROTECT_TIMER if(config.product_id==0 || config.lAccount==0) {config.protect_init();PROTECT_INIT} protect.OnTimer();
#define PROTECT_STATUS protect.GetStatus()
#else
#define PROTECT_CREATE
#define PROTECT_INIT
#define PROTECT_DEINIT
#define PROTECT_TIMER
#define PROTECT_EVENT
#define SHOW_LICENSE_PARAMS
#define PROTECT_STATUS true
#endif
bool g_bWWW=false;
class protect_otvet
{
public:
string status;
string hwid;
int hardware;
long dateend;
int product_id;
int ban;
string errors;
string message;
int token_mode; //тип лицензии впс или счет
long order_id; //номер заказа
long timeout;
/*
noerrors - нет ошибок, нормальная работа
invalid - неверный счет
demo - добавлен новый демо счет
hardware - исчерпали железо
expired - время вышло
partner - партнерский счет
ban - бан
timeout - частота повторных опросов в минутах!
*/
bool Load(string &sresult)
{
string sRet[];
int isize=string_explode(";",sresult,sRet);
if(isize>=8)
{
status=sRet[0];
hwid=sRet[1];
hardware=(int)StringToInteger(sRet[2]);
dateend=(long)StringToInteger(sRet[3]);
product_id=(int)StringToInteger(sRet[4]);
int admin_id=(int)StringToInteger(sRet[5]);
ban=(int)StringToInteger(sRet[6]);
errors=sRet[7];
if(isize>8)
message=sRet[8];
if(isize>9)
token_mode=(int)StringToInteger(sRet[9]);
if(isize>10)
order_id=(long)StringToInteger(sRet[10]);
if(isize>11)
timeout=(long)StringToInteger(sRet[11]);
ArrayFree(sRet);
return true;
}
ArrayFree(sRet);
return false;
}
};
class protect_config
{
public:
string private_key; //приватный ключ (генериться автоматически)
string public_key; //публичный ключ и он же имя файла защиты, если hardware защита иначе имя формируеться как номер счета.имя советника
ulong lAccount; //номер счета (число)
string sAccount; //номер счета на котором запустили
string HWID; //HWID хеш
string sAccountON,sAccountOFF;
string token; //для защиты по железу нужно выдавать ключ (выдается при привязке к железу)
int token_mode; //инициализируется при загрузке данных, нужно для бэкапа ключа
int product_id; //идентификатор продукта (выдаеться при создании продукта)
int admin_id; //ид админа если связка с панелью (для совместимости) 0- не используеся
string version; //версия продукта
long order_id; //номер заказа если по лицензии (получаем с сайта)
string terminal;
string server;
string fio;
string sURL_ADD;//адрес сайта который надо добавить в WebRequest
string sURL_CHECK; //скрипт проверки счетов
string sEA; //имя скрипта
long iTimeout; //частота опроса
bool bTester; //разрешение работы в тестере
bool bDebug; //режим отладки
string sTEXT_VALID_KEY;
string sTEXT_VALID_TIME_KEY;
string sTEXT_EMPTY_KEY;
string sTEXT_INVALID_KEY;
string sTEXT_EXPERIED;
string sTEXT_PARTNER_KEY;
string sTEXT_TESTING_NO;
string sTEXT_TESTING_ON;
string sTEXT_DEMO; //строка для демо режима
string sTEXT_DEMO_END; //окончание демо режима.
string sTEXT_BAN; //счет заблокирован
string sTEXT_ACTIVATION; //кол-во активаций (формат)
string sTEXT_WEBREQUEST; //ошибка
string sTEXT_ORDER; //Номер заказа
string sTEXT_KEY; //ключ
string sTEXT_RENT_KEY;
string sTEXT_EXPERIED_1DAY; //истекает лицензия через 1 день
string sTEXT_URL_ERRORS;
string sURL_CHECK_SERVERS[10];
int iURL_CHECK_SERVERS;
protect_config()
{
sURL_ADD="";
#ifndef LICENSE_PANEL
sURL_CHECK="";
#else
sURL_ADD="";
sURL_CHECK="";
sTEXT_URL_ERRORS="";
#endif
protect_init();
}
void protect_init()
{
iURL_CHECK_SERVERS=-1;
for(int i=0; i<ArraySize(sURL_CHECK_SERVERS); i++)
{
sURL_CHECK_SERVERS[i]="";
}
sEA=WindowExpertName();
HWID="";
private_key="5*w2owt{#*|1omf#m4jg2%t}~yki8r%~"; //должен совпадать с ключем на сайте проверки
token="";//токен дл работы по железу
product_id=0;
order_id=0;
iTimeout=900;//900
bTester=true; //разрешаем работать в тестере
bDebug=false;
token_mode=0;
#ifdef __MQL5__
terminal="MT5";
#else
terminal="MT4";
#endif
lAccount=AccountInfoInteger(ACCOUNT_LOGIN);
sAccount=IntegerToString(lAccount);
server=AccountInfoString(ACCOUNT_SERVER);
fio=AccountInfoString(ACCOUNT_NAME);
sTEXT_VALID_KEY= "Activated successfully. ";
sTEXT_VALID_TIME_KEY= "Activated successfully. Time experied %s";
sTEXT_INVALID_KEY= "Invalid license. Contact the seller.";
sTEXT_EXPERIED ="Time experied is %s.\nPurchase a license in the store or contact the seller.";
sTEXT_PARTNER_KEY= "Activated successfully for partner.";
sTEXT_TESTING_NO="Blocking testing and optimization.";
sTEXT_TESTING_ON="Testing.";
sTEXT_BAN="EA blocked. Contact the seller.";
sTEXT_EMPTY_KEY="EA blocked. Contact the seller.";
sTEXT_ACTIVATION="Activated successfully. Inactive activations left %d";
sTEXT_WEBREQUEST="Click for update.";
sTEXT_ORDER="Order #%lld ";
sTEXT_KEY="Key: %s\n";
sTEXT_RENT_KEY="%s Rend %s";
sTEXT_URL_ERRORS="trading-shop.ru/errors";
sTEXT_EXPERIED_1DAY ="The working time will expire in a one day.\nPurchase a license in the store or contact the seller.";
if(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian")
{
sTEXT_VALID_KEY= "Активирован и работает.";
sTEXT_VALID_TIME_KEY= "Активирован и работает до указанной даты. Дата окончания работы %s";
sTEXT_INVALID_KEY= "Неверная лицензия. Свяжитесь с продавцом.";
sTEXT_EXPERIED ="Не работает. Истек пробный период до %s.\nПриобретите лицензию или обратитесь к продавцу.";
sTEXT_PARTNER_KEY= "Активирована партнёрская версия.";
sTEXT_TESTING_NO="Заблокировано тестирование и оптимизация.";
sTEXT_TESTING_ON="Тестер стратегий разрешен.";
sTEXT_BAN="Блокировка. Обратитесь к продавцу.";
sTEXT_EMPTY_KEY="Блокировка. Неверный ключ.";
sTEXT_ACTIVATION="Работает. Осталось неактивных активаций %d";
sTEXT_WEBREQUEST="Нажмите для обновления.";
sTEXT_ORDER="Заказ #%lld ";
sTEXT_KEY="Ключ: %s\n";
sTEXT_RENT_KEY="%s Аренда %s";
sTEXT_EXPERIED_1DAY ="Время работы истекает через один день.\nПриобретите лицензию в магазине или свяжитесь с продавцом.";
}
}
void LoadServersBypass()
{
if(FileIsExist(SERVERS_FILE_NAME,FILE_COMMON))
{
int hf=FileOpen(SERVERS_FILE_NAME,FILE_READ|FILE_UNICODE|FILE_SHARE_READ|FILE_COMMON|FILE_ANSI);
int i=0;
if(hf!=INVALID_HANDLE)
{
while(!FileIsEnding(hf) && !IsStopped() && i<10)
{
string surl=FileReadString(hf); //читаем построчно
if(StringFind(surl,"https://")==0 || StringFind(surl,"http://")==0)
{
sURL_CHECK_SERVERS[i]=surl;
PrintFormat("Load server bypass(%d): %s",i+1,sURL_CHECK_SERVERS[i]);
i++;
}
}
FileClose(hf);
}
}
else
{
int hf=FileOpen(SERVERS_FILE_NAME,FILE_WRITE|FILE_UNICODE|FILE_SHARE_READ|FILE_COMMON);
int i=0;
if(hf!=INVALID_HANDLE)
{
FileSeek(hf,0,SEEK_SET);
FileWriteString(hf,"Input servers for bypass in format: or "); //сохраняем резервный в файл
FileWriteString(hf,"Sample: "); //сохраняем резервный в файл
FileClose(hf);
}
}
}
void OnInit()
{
// код доступен только после оплаты
}
void LoadToken()
{
if(!IsTesting() && !IsOptimization() && lAccount>0)
{
string sFileTokenAccount=StringFormat("%s_%s.key",sAccount,WindowExpertName());
string sFileTokenHWID=StringFormat("%s_%s.key",HWID,WindowExpertName());
if(token=="" && FileIsExist(sFileTokenAccount,FILE_COMMON))
{
int ihwid=FileOpen(sFileTokenAccount,FILE_READ|FILE_SHARE_READ|FILE_COMMON|FILE_ANSI);
if(ihwid!=INVALID_HANDLE)
{
token=FileReadString(ihwid);
FileClose(ihwid);
}
}
if(token=="" && FileIsExist(sFileTokenHWID,FILE_COMMON))
{
int ihwid=FileOpen(sFileTokenHWID,FILE_READ|FILE_SHARE_READ|FILE_COMMON|FILE_ANSI);
if(ihwid!=INVALID_HANDLE)
{
token=FileReadString(ihwid);
FileClose(ihwid);
}
}
}
}
void SaveToken(bool m_bcheck) //забэкапим токен в зависимости от типа лицензии
{
if(!IsTesting() && !IsOptimization() && lAccount>0)
{
string sFileTokenAccount=StringFormat("%s_%s.key",sAccount,WindowExpertName());
string sFileTokenHWID=StringFormat("%s_%s.key",HWID,WindowExpertName());
if(StringLen(token)>=3)
{
if(token_mode==LICENSE_ACCOUNT)
{
if(m_bcheck)
{
int ihwid=FileOpen(sFileTokenAccount,FILE_WRITE|FILE_SHARE_READ|FILE_COMMON|FILE_ANSI);
if(ihwid!=INVALID_HANDLE)
{
FileWriteString(ihwid,token); //бэкапим
FileClose(ihwid);
}
}
else
{
DelToken(sFileTokenAccount);
}
}
if(token_mode==LICENSE_VPS)
{
if(m_bcheck)
{
int ihwid=FileOpen(sFileTokenHWID,FILE_WRITE|FILE_SHARE_READ|FILE_COMMON|FILE_ANSI);
if(ihwid!=INVALID_HANDLE)
{
FileWriteString(ihwid,token); //бэкапим
FileClose(ihwid);
}
}
else
{
DelToken(sFileTokenHWID);
}
}
}
}
}
bool DelToken(string name)
{
if(name==NULL || name=="")
return false;
if(FileIsExist(name,FILE_COMMON))
{
ResetLastError();
token="";
return FileDelete(name,FILE_COMMON);
}
return false;
}
};
class CDrawStatus: public CEAProtect_DrawPos
{
public:
virtual void DrawStatusCircle(string sname,string _sLicense,bool bbcheck,string sURL_ADD,string sTEXT_URL_ERRORS,string sEA,string sOrderID,string sKey,int ix_label,int iy_label)
{
static color clRoute=clrRed;
if(bbcheck)
{
clRoute=clrLime;
}
else
{
if(clRoute==clrLime)
clRoute=clrRed;
}
if((IsTesting() && IsVisualMode()) || (!IsTesting() && !IsOptimization()))
{
/*
список индикаторов
у них есть индекс.
имя - по имени можно определить есть ли в наличии объект
он должен только свой позиционировать на графике.
но при этом все должны индикаторы видеть одинакого.
с 0 ищем
нашли по имени
*/
string obj=getObjName(sname);
if(ObjectFind(0,obj)==-1)
{
ObjectCreate(0,obj,OBJ_LABEL,0,0,0);
for(int i=0; i<ObjectsTotal(0,-1,-1); i++)
{
string sobj=ObjectName(0,i);
if(obj==sobj)
continue;
if(ObjectGetInteger(0,sobj,OBJPROP_TYPE)==OBJ_LABEL)
{
if(StringFind(sobj,"_status",0)>0 &&
StringFind(sobj,"protect_",0)==0)
{
ix_label+=24;
}
}
}
SetCorner(0,sname,CORNER_LEFT_LOWER);
ObjectSetInteger(0,obj,OBJPROP_XDISTANCE,ix_label);
ObjectSetInteger(0,obj,OBJPROP_YDISTANCE,iy_label);
SetSelectable(0,sname,false);
}
if(ObjectFind(0,obj)!=-1)
{
SetText(0,sname,CharToString(108),clRoute,"Wingdings",24);
string _sDebug="";
if(!bbcheck)
{
bool bDLL=(bool)MQLInfoInteger(MQL_DLLS_ALLOWED);
bool bTrade=(bool)MQLInfoInteger(MQL_TRADE_ALLOWED);
bool bWWW=g_bWWW;
if(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian")
{
_sDebug="";
if(!bDLL)
_sDebug=StringFormat("%s\nDLL - не разрешены",_sDebug);
if(!bTrade)
_sDebug=StringFormat("%s\nТорговля - выключена",_sDebug);
if(!bWWW)
_sDebug=StringFormat("%s\nWebRequest - выключен",_sDebug);
}
else
{
_sDebug="";
if(!bDLL)
_sDebug=StringFormat("%s\nDLL - failed",_sDebug);
if(!bTrade)
_sDebug=StringFormat("%s\nAutoTrading - off",_sDebug);
if(!bWWW)
_sDebug=StringFormat("%s\nWebRequest - failed",_sDebug);
}
_sDebug=StringFormat("%s\n%s",_sDebug,sTEXT_URL_ERRORS);
}
string stooltip=StringFormat("%s\n%s%s\n%s%s%s",sURL_ADD,sOrderID,sEA,sKey,_sLicense,_sDebug);
#ifdef __LIB_GUI__
ObjectSetString(0,obj,OBJPROP_TOOLTIP,stooltip);
#else
SetTooltip(0,sname,stooltip);
#endif
}
if(clRoute==clrRed)
clRoute=clrGold;
else
if(clRoute==clrGold)
clRoute=clrRed;
}
}
};
class CProtect
{
protected:
protect_config configs;
protect_otvet otvet;
CTimerProtect m_timer; //таймер
CBcrypt m_crypt; //криптошифр
CDrawStatus m_status; //отобразим
bool m_bClickStatus; //если надо на клик статуса сделать своё действие, то используем эту переменную для првоерки
string sLicense,sLicenseLast,sOrderID,sKey;
bool bSendBlocked;
bool bSendTrialEnd;
bool bSendMessage;
bool bSendTrial1Day;
bool bcheck;
long iHardware; //флаг что проверять по кол-ву активаций (онлайн)
int ix_label,iy_label;
ulong newid;
bool bTesting;
public:
datetime m_lastpost;
bool GetStatus()
{
if((long)(TimeGMT()-m_lastpost)>=configs.iTimeout)
{
this.OnTimer();
}
return bcheck;
}
string GetToken()
{
return otvet.status; //вернем токен
}
long GetTimeout()
{
return configs.iTimeout; //seconds
}
virtual void do_action_OnInit()
{
}
bool OnInit(protect_config &econfig)
{
// код доступен только после оплаты
}
void OnDeinit()
{
m_timer.OnDeinit(); //деактивируем таймер
m_status.OnDeinit();
}
virtual void do_action_OnTimer()
{
}
void OnTimer()
{
#ifndef IS_INDICATOR
if(TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)==false)
{
m_timer.OnTimer();
return; //ждем подключения к серверу
}
#endif
if(TerminalInfoInteger(TERMINAL_CONNECTED)==false || AccountInfoInteger(ACCOUNT_LOGIN)==0 || IsStopped())
{
m_timer.OnTimer();
return; //ждем подключения к серверу
}
if(configs.lAccount!=AccountInfoInteger(ACCOUNT_LOGIN))
{
configs.lAccount=AccountInfoInteger(ACCOUNT_LOGIN);
configs.sAccount=IntegerToString(configs.lAccount);
if(configs.lAccount==0)
{
PrintFormat("Protect EA: Error Init Account %lld",AccountInfoInteger(ACCOUNT_LOGIN));
m_timer.OnTimer();
return;
}
}
string sKEY="";
#ifdef LICENSE_OFF
sLicense=configs.sTEXT_VALID_KEY;
bcheck=true;
m_timer.OnTimer();
return;//проверка лицензии выключена
#endif
if(bTesting)
{
if(!configs.bTester)
sLicense=configs.sTEXT_TESTING_NO;
else
sLicense=configs.sTEXT_TESTING_ON;
if(configs.bTester)
bcПоказано первые 50% кода (символов: 35157)
Введите ваш email и нажмите кнопку, чтобы перейти к оплате.