mql5/Experts/Advisors/DualEA/Include/PolicyHttpBridge.mqh
Princeec13 12eac37d58
2026-02-04 14:28:59 -05:00

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__