134 satır
4,3 KiB
MQL5
134 satır
4,3 KiB
MQL5
#ifndef __DUALEA_POLICY_HTTP_BRIDGE_MQH__
|
|
#define __DUALEA_POLICY_HTTP_BRIDGE_MQH__
|
|
|
|
#include <Files/File.mqh>
|
|
#include "LogMiddleware.mqh"
|
|
|
|
class CPolicyHttpBridge
|
|
{
|
|
private:
|
|
string m_policy_file; // where EA reads policy from (Common Files path allowed)
|
|
int m_reload_secs; // minimum interval between checks
|
|
datetime m_last_check;
|
|
long m_last_size;
|
|
bool m_warned_whitelist;
|
|
|
|
public:
|
|
CPolicyHttpBridge(): m_policy_file(""), m_reload_secs(10), m_last_check(0), m_last_size(-1), m_warned_whitelist(false) {}
|
|
|
|
void Configure(const string policy_file, const int reload_secs)
|
|
{
|
|
m_policy_file = policy_file;
|
|
m_reload_secs = (reload_secs>0? reload_secs:10);
|
|
m_last_check = 0;
|
|
m_last_size = -1;
|
|
}
|
|
|
|
bool VerifyAccess(const string url)
|
|
{
|
|
string trimmed = url;
|
|
StringTrimLeft(trimmed);
|
|
StringTrimRight(trimmed);
|
|
if(StringLen(trimmed) == 0)
|
|
return true;
|
|
|
|
char payload[];
|
|
ArrayResize(payload, 0);
|
|
char response[];
|
|
string response_headers = "";
|
|
int status = WebRequest("HEAD", trimmed, "", 3000, payload, response, response_headers);
|
|
if(status == -1)
|
|
{
|
|
int err = GetLastError();
|
|
if((err == 4014 || err == 5204) && !m_warned_whitelist)
|
|
{
|
|
string guidance = StringFormat(
|
|
"Policy HTTP access blocked (error %d). Enable WebRequest in MT5: Tools → Options → Expert Advisors → 'Allow WebRequest for listed URL' and add %s. Then press OK and restart the EA.",
|
|
err, trimmed);
|
|
LOG(guidance);
|
|
m_warned_whitelist = true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
if(status >= 400 && !m_warned_whitelist)
|
|
{
|
|
LOG(StringFormat("Policy HTTP verification returned status %d for %s", status, trimmed));
|
|
}
|
|
|
|
return (status >= 200 && status < 500);
|
|
}
|
|
|
|
// Returns true if the on-disk policy file size changed since last check
|
|
bool UpdateIfStale()
|
|
{
|
|
datetime now = TimeCurrent();
|
|
if(m_policy_file=="") return false;
|
|
if(m_last_check!=0 && (now - m_last_check) < m_reload_secs) return false;
|
|
m_last_check = now;
|
|
|
|
// Check file in Common first
|
|
int h = FileOpen(m_policy_file, FILE_READ|FILE_TXT|FILE_COMMON);
|
|
if(h == INVALID_HANDLE)
|
|
{
|
|
// Fall back to user Files
|
|
h = FileOpen(m_policy_file, FILE_READ|FILE_TXT);
|
|
if(h == INVALID_HANDLE)
|
|
{
|
|
// File absent is not an error; simply no update
|
|
return false;
|
|
}
|
|
}
|
|
|
|
long sz = (long)FileSize(h);
|
|
FileClose(h);
|
|
if(sz != m_last_size)
|
|
{
|
|
m_last_size = sz;
|
|
LOG(StringFormat("Policy file changed, size=%ld", sz));
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// Pull policy JSON from HTTP endpoint and write to file. Requires MT5 WebRequest whitelist.
|
|
bool Pull(const string url)
|
|
{
|
|
if(m_policy_file=="") return false;
|
|
string headers = "Content-Type: application/json\r\n";
|
|
char data[]; ArrayResize(data, 0);
|
|
char result[]; string result_headers;
|
|
int status = WebRequest("GET", url, headers, 5000, data, result, result_headers);
|
|
if(status==200 || status==201)
|
|
{
|
|
string body = CharArrayToString(result, 0, -1);
|
|
int h = FileOpen(m_policy_file, FILE_WRITE|FILE_TXT|FILE_COMMON);
|
|
if(h == INVALID_HANDLE)
|
|
{
|
|
h = FileOpen(m_policy_file, FILE_WRITE|FILE_TXT);
|
|
}
|
|
if(h == INVALID_HANDLE)
|
|
{
|
|
LOG(StringFormat("PolicyHttpBridge: Cannot open %s for write, error=%d", m_policy_file, GetLastError()));
|
|
return false;
|
|
}
|
|
FileWriteString(h, body);
|
|
FileClose(h);
|
|
LOG(StringFormat("Policy pull success: %s (len=%d)", url, StringLen(body)));
|
|
// Force stale so UpdateIfStale will report change on next call
|
|
m_last_size = -1;
|
|
return true;
|
|
}
|
|
if(status==-1)
|
|
{
|
|
LOG(StringFormat("Policy pull failed: %s (error=%d). Ensure URL is whitelisted in MT5 WebRequest.", url, GetLastError()));
|
|
}
|
|
else
|
|
{
|
|
LOG(StringFormat("Policy pull HTTP status: %d for %s", status, url));
|
|
}
|
|
return false;
|
|
}
|
|
};
|
|
|
|
#endif // __DUALEA_POLICY_HTTP_BRIDGE_MQH__
|