Improvement: Add serial number generate menu
This commit is contained in:
Binary file not shown.
@@ -23,6 +23,7 @@
|
||||
#include "InputDlg.h"
|
||||
#include "CPasswordDlg.h"
|
||||
#include "pwd_gen.h"
|
||||
#include "DateVerify.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
@@ -196,6 +197,7 @@ BEGIN_MESSAGE_MAP(CMy2015RemoteDlg, CDialogEx)
|
||||
ON_MESSAGE(WM_OPENKEYBOARDDIALOG, OnOpenKeyboardDialog)
|
||||
ON_WM_HELPINFO()
|
||||
ON_COMMAND(ID_ONLINE_SHARE, &CMy2015RemoteDlg::OnOnlineShare)
|
||||
ON_COMMAND(ID_TOOL_AUTH, &CMy2015RemoteDlg::OnToolAuth)
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
@@ -925,98 +927,16 @@ std::string joinString(const std::vector<std::string>& tokens, char delimiter) {
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
#define REG_SETTINGS "Software\\YAMA\\Settings"
|
||||
|
||||
// д<><D0B4><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD><C3A3><EFBFBD><EFBFBD>ֽڰ棩
|
||||
bool WriteAppSettingA(const std::string& keyName, const std::string& value) {
|
||||
HKEY hKey;
|
||||
bool CMy2015RemoteDlg::CheckValid() {
|
||||
DateVerify verify;
|
||||
#ifdef _DEBUG
|
||||
BOOL isTrail = verify.isTrail(0);
|
||||
#else
|
||||
BOOL isTrail = verify.isTrail(14);
|
||||
#endif
|
||||
|
||||
LONG result = RegCreateKeyExA(
|
||||
HKEY_CURRENT_USER,
|
||||
REG_SETTINGS,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
KEY_WRITE,
|
||||
NULL,
|
||||
&hKey,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (result != ERROR_SUCCESS) {
|
||||
Mprintf("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: %d\n", result);
|
||||
return false;
|
||||
}
|
||||
|
||||
result = RegSetValueExA(
|
||||
hKey,
|
||||
keyName.c_str(),
|
||||
0,
|
||||
REG_SZ,
|
||||
reinterpret_cast<const BYTE*>(value.c_str()),
|
||||
static_cast<DWORD>(value.length() + 1)
|
||||
);
|
||||
|
||||
RegCloseKey(hKey);
|
||||
return result == ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
// <20><>ȡ<EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD><C3A3><EFBFBD><EFBFBD>ֽڰ棩
|
||||
bool ReadAppSettingA(const std::string& keyName, std::string& outValue) {
|
||||
HKEY hKey;
|
||||
|
||||
LONG result = RegOpenKeyExA(
|
||||
HKEY_CURRENT_USER,
|
||||
REG_SETTINGS,
|
||||
0,
|
||||
KEY_READ,
|
||||
&hKey
|
||||
);
|
||||
|
||||
if (result != ERROR_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char buffer[256];
|
||||
DWORD bufferSize = sizeof(buffer);
|
||||
DWORD type = 0;
|
||||
|
||||
result = RegQueryValueExA(
|
||||
hKey,
|
||||
keyName.c_str(),
|
||||
nullptr,
|
||||
&type,
|
||||
reinterpret_cast<LPBYTE>(buffer),
|
||||
&bufferSize
|
||||
);
|
||||
|
||||
RegCloseKey(hKey);
|
||||
|
||||
if (result == ERROR_SUCCESS && type == REG_SZ) {
|
||||
outValue = buffer;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>õĴ<C3B5><C4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͻ<EFBFBD><CFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD>룬<EFBFBD><EBA3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD>ȥ<EFBFBD><C8A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܵ<EFBFBD><DCB5><EFBFBD>Ȩ<EFBFBD><C8A8><EFBFBD><EFBFBD>
|
||||
int CanBuildClient() {
|
||||
std::string freeTrail;
|
||||
auto b = ReadAppSettingA("free_trial", freeTrail);
|
||||
if (!b || freeTrail.empty())
|
||||
freeTrail = "10";
|
||||
return atoi(freeTrail.c_str());
|
||||
}
|
||||
|
||||
bool UpdateFreeTrial(int n) {
|
||||
return WriteAppSettingA("free_trial", std::to_string(n));
|
||||
}
|
||||
|
||||
void CMy2015RemoteDlg::OnOnlineBuildClient()
|
||||
{
|
||||
auto n = CanBuildClient();
|
||||
if (n<=0) {
|
||||
if (!isTrail) {
|
||||
auto THIS_APP = (CMy2015RemoteApp*)AfxGetApp();
|
||||
auto settings = "settings", pwdKey = "Password";
|
||||
// <20><>֤<EFBFBD><D6A4><EFBFBD><EFBFBD>
|
||||
@@ -1029,7 +949,7 @@ void CMy2015RemoteDlg::OnOnlineBuildClient()
|
||||
dlg.m_sDeviceID = deviceID.c_str();
|
||||
dlg.m_sPassword = pwd;
|
||||
if (pwd.IsEmpty() && IDOK != dlg.DoModal() || dlg.m_sPassword.IsEmpty())
|
||||
return;
|
||||
return false;
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD>20250209 - 20350209: SHA256
|
||||
auto v = splitString(dlg.m_sPassword.GetBuffer(), '-');
|
||||
@@ -1037,7 +957,7 @@ void CMy2015RemoteDlg::OnOnlineBuildClient()
|
||||
{
|
||||
THIS_APP->m_iniFile.SetStr(settings, pwdKey, "");
|
||||
MessageBox("<EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!", "<EFBFBD><EFBFBD>ʾ", MB_ICONINFORMATION);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
std::vector<std::string> subvector(v.begin() + 2, v.end());
|
||||
std::string password = v[0] + " - " + v[1] + ": " + PWD_HASH256;
|
||||
@@ -1049,7 +969,7 @@ void CMy2015RemoteDlg::OnOnlineBuildClient()
|
||||
if (pwd.IsEmpty() || (IDOK != dlg.DoModal() || hash256 != fixedKey)) {
|
||||
if (!dlg.m_sPassword.IsEmpty())
|
||||
MessageBox("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><EFBFBD><DEB7><EFBFBD><EFBFBD>ɷ<EFBFBD><C9B7><EFBFBD><EFBFBD><EFBFBD>!", "<EFBFBD><EFBFBD>ʾ", MB_ICONWARNING);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// <20>ж<EFBFBD><D0B6>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>
|
||||
@@ -1059,19 +979,30 @@ void CMy2015RemoteDlg::OnOnlineBuildClient()
|
||||
if (curDate < v[0] || curDate > v[1]) {
|
||||
THIS_APP->m_iniFile.SetStr(settings, pwdKey, "");
|
||||
MessageBox("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!", "<EFBFBD><EFBFBD>ʾ", MB_ICONINFORMATION);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
if (dlg.m_sPassword != pwd)
|
||||
THIS_APP->m_iniFile.SetStr(settings, pwdKey, dlg.m_sPassword);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CMy2015RemoteDlg::OnOnlineBuildClient()
|
||||
{
|
||||
// <20><><EFBFBD>±<EFBFBD><C2B1><EFBFBD><EFBFBD>ij<EFBFBD><C4B3><EFBFBD>14<31><34><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڣ<EFBFBD><DAA3><EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD><D6AE><EFBFBD><EFBFBD><EFBFBD>ɷ<EFBFBD><C9B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>"<22><><EFBFBD>к<EFBFBD>"<22><>
|
||||
// <20><><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><DFBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>if<69><66><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD><D3B5><EFBFBD>Ӧ<EFBFBD>ط<EFBFBD><D8B7><EFBFBD><EFBFBD>ɡ<EFBFBD>
|
||||
// <20><><EFBFBD>кŰ<D0BA><C5B0><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><C8A8><EFBFBD>ڷ<EFBFBD>Χ<EFBFBD><CEA7>ȷ<EFBFBD><C8B7>һ<EFBFBD><D2BB>һ<EFBFBD>룻<EFBFBD><EBA3BB>Ȩ<EFBFBD><EFBFBD><DFBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><CEB4><EFBFBD>۸<EFBFBD>!
|
||||
// ע<><D7A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD> if <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>θ<EFBFBD><CEB8><EFBFBD>Ȩ<EFBFBD><EFBFBD>.
|
||||
// 2025/04/20
|
||||
if (!CheckValid())
|
||||
return;
|
||||
|
||||
// TODO: <20>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EEB4A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
CBuildDlg Dlg;
|
||||
Dlg.m_strIP = ((CMy2015RemoteApp*)AfxGetApp())->m_iniFile.GetStr("settings", "localIp", "");
|
||||
int Port = ((CMy2015RemoteApp*)AfxGetApp())->m_iniFile.GetInt("settings", "ghost");
|
||||
Dlg.m_strPort = Port <= 0 ? "6543" : std::to_string(Port).c_str();
|
||||
if (IDOK == Dlg.DoModal() && n > 0) {
|
||||
UpdateFreeTrial(n - 1);
|
||||
}
|
||||
Dlg.DoModal();
|
||||
}
|
||||
|
||||
|
||||
@@ -1806,3 +1737,15 @@ void CMy2015RemoteDlg::OnOnlineShare()
|
||||
memcpy(bToken + 2, dlg.m_str, dlg.m_str.GetLength());
|
||||
SendSelectedCommand(bToken, sizeof(bToken));
|
||||
}
|
||||
|
||||
|
||||
void CMy2015RemoteDlg::OnToolAuth()
|
||||
{
|
||||
CPwdGenDlg dlg;
|
||||
std::string hardwareID = getHardwareID();
|
||||
std::string hashedID = hashSHA256(hardwareID);
|
||||
std::string deviceID = getFixedLengthID(hashedID);
|
||||
dlg.m_sDeviceID = deviceID.c_str();
|
||||
|
||||
dlg.DoModal();
|
||||
}
|
||||
|
||||
@@ -80,6 +80,7 @@ public:
|
||||
BOOL isClosed;
|
||||
|
||||
CBitmap m_bmOnline[4];
|
||||
bool CheckValid();
|
||||
afx_msg void OnTimer(UINT_PTR nIDEvent);
|
||||
afx_msg void OnClose();
|
||||
void Release();
|
||||
@@ -121,4 +122,5 @@ public:
|
||||
afx_msg BOOL OnHelpInfo(HELPINFO* pHelpInfo);
|
||||
virtual BOOL PreTranslateMessage(MSG* pMsg);
|
||||
afx_msg void OnOnlineShare();
|
||||
afx_msg void OnToolAuth();
|
||||
};
|
||||
|
||||
@@ -50,3 +50,89 @@ BOOL CPasswordDlg::OnInitDialog()
|
||||
return TRUE; // return TRUE unless you set the focus to a control
|
||||
// 异常: OCX 属性页应返回 FALSE
|
||||
}
|
||||
|
||||
|
||||
// CPasswordDlg 消息处理程序
|
||||
|
||||
IMPLEMENT_DYNAMIC(CPwdGenDlg, CDialogEx)
|
||||
|
||||
CPwdGenDlg::CPwdGenDlg(CWnd* pParent /*=nullptr*/)
|
||||
: CDialogEx(IDD_DIALOG_KEYGEN, pParent)
|
||||
, m_sDeviceID(_T(""))
|
||||
, m_sPassword(_T(""))
|
||||
, m_sUserPwd(_T(""))
|
||||
, m_ExpireTm(COleDateTime::GetCurrentTime())
|
||||
, m_StartTm(COleDateTime::GetCurrentTime())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CPwdGenDlg::~CPwdGenDlg()
|
||||
{
|
||||
}
|
||||
|
||||
void CPwdGenDlg::DoDataExchange(CDataExchange* pDX)
|
||||
{
|
||||
CDialogEx::DoDataExchange(pDX);
|
||||
DDX_Control(pDX, IDC_EDIT_DEVICEID, m_EditDeviceID);
|
||||
DDX_Control(pDX, IDC_EDIT_DEVICEPWD, m_EditPassword);
|
||||
DDX_Control(pDX, IDC_EDIT_USERPWD, m_EditUserPwd);
|
||||
DDX_Text(pDX, IDC_EDIT_DEVICEID, m_sDeviceID);
|
||||
DDV_MaxChars(pDX, m_sDeviceID, 19);
|
||||
DDX_Text(pDX, IDC_EDIT_DEVICEPWD, m_sPassword);
|
||||
DDV_MaxChars(pDX, m_sPassword, 37);
|
||||
DDX_Text(pDX, IDC_EDIT_USERPWD, m_sUserPwd);
|
||||
DDV_MaxChars(pDX, m_sUserPwd, 24);
|
||||
DDX_Control(pDX, IDC_EXPIRE_DATE, m_PwdExpireDate);
|
||||
DDX_DateTimeCtrl(pDX, IDC_EXPIRE_DATE, m_ExpireTm);
|
||||
DDX_Control(pDX, IDC_START_DATE, m_StartDate);
|
||||
DDX_DateTimeCtrl(pDX, IDC_START_DATE, m_StartTm);
|
||||
}
|
||||
|
||||
|
||||
BEGIN_MESSAGE_MAP(CPwdGenDlg, CDialogEx)
|
||||
ON_BN_CLICKED(IDC_BUTTON_GENKEY, &CPwdGenDlg::OnBnClickedButtonGenkey)
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
void CPwdGenDlg::OnBnClickedButtonGenkey()
|
||||
{
|
||||
// TODO: 在此添加控件通知处理程序代码
|
||||
UpdateData(TRUE);
|
||||
if (m_sUserPwd.IsEmpty())return;
|
||||
std::string pwdHash = hashSHA256(m_sUserPwd.GetString());
|
||||
if (pwdHash != PWD_HASH256) {
|
||||
Mprintf("hashSHA256 [%s]: %s\n", m_sUserPwd, pwdHash.c_str());
|
||||
MessageBoxA("您输入的密码不正确,无法生成口令!", "提示", MB_OK | MB_ICONWARNING);
|
||||
return;
|
||||
}
|
||||
CString strBeginDate = m_StartTm.Format("%Y%m%d");
|
||||
CString strEndDate = m_ExpireTm.Format("%Y%m%d");
|
||||
// 密码形式:20250209 - 20350209: SHA256
|
||||
std::string password = std::string(strBeginDate.GetString()) + " - " + strEndDate.GetBuffer() + ": " + PWD_HASH256;
|
||||
std::string finalKey = deriveKey(password, m_sDeviceID.GetString());
|
||||
std::string fixedKey = strBeginDate.GetString() + std::string("-") + strEndDate.GetBuffer() + std::string("-") +
|
||||
getFixedLengthID(finalKey);
|
||||
m_EditPassword.SetWindowTextA(fixedKey.c_str());
|
||||
std::string hardwareID = getHardwareID();
|
||||
std::string hashedID = hashSHA256(hardwareID);
|
||||
std::string deviceID = getFixedLengthID(hashedID);
|
||||
if (deviceID == m_sDeviceID.GetString()) { // 授权的是当前主控程序
|
||||
auto THIS_APP = (CMy2015RemoteApp*)AfxGetApp();
|
||||
auto settings = "settings", pwdKey = "Password";
|
||||
THIS_APP->m_iniFile.SetStr(settings, pwdKey, fixedKey.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BOOL CPwdGenDlg::OnInitDialog()
|
||||
{
|
||||
CDialogEx::OnInitDialog();
|
||||
|
||||
// TODO: 在此添加额外的初始化
|
||||
m_hIcon = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_ICON_PASSWORD));
|
||||
SetIcon(m_hIcon, FALSE);
|
||||
|
||||
return TRUE; // return TRUE unless you set the focus to a control
|
||||
// 异常: OCX 属性页应返回 FALSE
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "Resource.h"
|
||||
|
||||
// 密码的哈希值
|
||||
// 提示:请用hashSHA256函数获得密码的哈希值,你应该用自己的密码生成哈希值,并替换这个默认值.
|
||||
#define PWD_HASH256 "61f04dd637a74ee34493fc1025de2c131022536da751c29e3ff4e9024d8eec43"
|
||||
|
||||
// CPasswordDlg 对话框
|
||||
@@ -31,3 +32,36 @@ public:
|
||||
CString m_sPassword;
|
||||
virtual BOOL OnInitDialog();
|
||||
};
|
||||
|
||||
|
||||
class CPwdGenDlg : public CDialogEx
|
||||
{
|
||||
DECLARE_DYNAMIC(CPwdGenDlg)
|
||||
|
||||
public:
|
||||
CPwdGenDlg(CWnd* pParent = nullptr); // 标准构造函数
|
||||
virtual ~CPwdGenDlg();
|
||||
|
||||
enum {
|
||||
IDD = IDD_DIALOG_KEYGEN
|
||||
};
|
||||
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
|
||||
|
||||
DECLARE_MESSAGE_MAP()
|
||||
public:
|
||||
HICON m_hIcon;
|
||||
CEdit m_EditDeviceID;
|
||||
CEdit m_EditPassword;
|
||||
CEdit m_EditUserPwd;
|
||||
CString m_sDeviceID;
|
||||
CString m_sPassword;
|
||||
CString m_sUserPwd;
|
||||
afx_msg void OnBnClickedButtonGenkey();
|
||||
CDateTimeCtrl m_PwdExpireDate;
|
||||
COleDateTime m_ExpireTm;
|
||||
CDateTimeCtrl m_StartDate;
|
||||
COleDateTime m_StartTm;
|
||||
virtual BOOL OnInitDialog();
|
||||
};
|
||||
|
||||
173
server/2015Remote/DateVerify.h
Normal file
173
server/2015Remote/DateVerify.h
Normal file
@@ -0,0 +1,173 @@
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <ctime>
|
||||
#include <WinSock2.h>
|
||||
#include <Windows.h>
|
||||
#pragma comment(lib, "ws2_32.lib")
|
||||
|
||||
// <20>й<EFBFBD><D0B9><EFBFBD>½<EFBFBD>Ż<EFBFBD><C5BB><EFBFBD>NTP<54><50><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD>
|
||||
const char* CN_NTP_SERVERS[] = {
|
||||
"ntp.aliyun.com",
|
||||
"time1.aliyun.com",
|
||||
"ntp1.tencent.com",
|
||||
"time.edu.cn",
|
||||
"ntp.tuna.tsinghua.edu.cn",
|
||||
"cn.ntp.org.cn",
|
||||
};
|
||||
const int CN_NTP_COUNT = sizeof(CN_NTP_SERVERS) / sizeof(CN_NTP_SERVERS[0]);
|
||||
const int NTP_PORT = 123;
|
||||
const uint64_t NTP_EPOCH_OFFSET = 2208988800ULL;
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
class DateVerify
|
||||
{
|
||||
private:
|
||||
// <20><>ʼ<EFBFBD><CABC>Winsock
|
||||
bool initWinsock() {
|
||||
WSADATA wsaData;
|
||||
return WSAStartup(MAKEWORD(2, 2), &wsaData) == 0;
|
||||
}
|
||||
|
||||
// <20><>ָ<EFBFBD><D6B8>NTP<54><50><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡʱ<C8A1><CAB1>
|
||||
time_t getTimeFromServer(const char* server) {
|
||||
SOCKET sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if (sock == INVALID_SOCKET) return 0;
|
||||
|
||||
sockaddr_in serverAddr{};
|
||||
serverAddr.sin_family = AF_INET;
|
||||
serverAddr.sin_port = htons(NTP_PORT);
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
hostent* host = gethostbyname(server);
|
||||
if (!host) {
|
||||
closesocket(sock);
|
||||
return 0;
|
||||
}
|
||||
serverAddr.sin_addr.s_addr = *((unsigned long*)host->h_addr_list[0]);
|
||||
|
||||
// <20><><EFBFBD>ó<EFBFBD>ʱ
|
||||
DWORD timeout = 2000; // 2<>볬ʱ
|
||||
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));
|
||||
|
||||
// <><D7BC>NTP<54><50><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
char ntpPacket[48] = { 0 };
|
||||
ntpPacket[0] = 0x1B; // LI=0, VN=3, Mode=3
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
if (sendto(sock, ntpPacket, sizeof(ntpPacket), 0,
|
||||
(sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
|
||||
closesocket(sock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ
|
||||
if (recv(sock, ntpPacket, sizeof(ntpPacket), 0) <= 0) {
|
||||
closesocket(sock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
closesocket(sock);
|
||||
|
||||
// <20><><EFBFBD><EFBFBD>NTPʱ<50><CAB1>
|
||||
uint32_t ntpTime = ntohl(*((uint32_t*)(ntpPacket + 40)));
|
||||
return ntpTime - NTP_EPOCH_OFFSET;
|
||||
}
|
||||
|
||||
// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>ʱ<EFBFBD>䣨<EFBFBD><E4A3A8><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
time_t getNetworkTimeInChina() {
|
||||
if (!initWinsock()) return 0;
|
||||
|
||||
time_t result = 0;
|
||||
for (int i = 0; i < CN_NTP_COUNT && result == 0; i++) {
|
||||
result = getTimeFromServer(CN_NTP_SERVERS[i]);
|
||||
if (result != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
WSACleanup();
|
||||
return result;
|
||||
}
|
||||
|
||||
// <20><><EFBFBD>·<EFBFBD><C2B7><EFBFBD>дת<D0B4><D7AA>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>(1-12)
|
||||
int monthAbbrevToNumber(const std::string& month) {
|
||||
static const std::map<std::string, int> months = {
|
||||
{"Jan", 1}, {"Feb", 2}, {"Mar", 3}, {"Apr", 4},
|
||||
{"May", 5}, {"Jun", 6}, {"Jul", 7}, {"Aug", 8},
|
||||
{"Sep", 9}, {"Oct", 10}, {"Nov", 11}, {"Dec", 12}
|
||||
};
|
||||
auto it = months.find(month);
|
||||
return (it != months.end()) ? it->second : 0;
|
||||
}
|
||||
|
||||
// <20><><EFBFBD><EFBFBD>__DATE__<5F>ַ<EFBFBD><D6B7><EFBFBD>Ϊtm<74>ṹ
|
||||
tm parseCompileDate(const char* compileDate) {
|
||||
tm tmCompile = { 0 };
|
||||
std::string monthStr(compileDate, 3);
|
||||
std::string dayStr(compileDate + 4, 2);
|
||||
std::string yearStr(compileDate + 7, 4);
|
||||
|
||||
tmCompile.tm_year = std::stoi(yearStr) - 1900;
|
||||
tmCompile.tm_mon = monthAbbrevToNumber(monthStr) - 1;
|
||||
tmCompile.tm_mday = std::stoi(dayStr);
|
||||
|
||||
return tmCompile;
|
||||
}
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD><D6AE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
int daysBetweenDates(const tm& date1, const tm& date2) {
|
||||
auto timeToTimePoint = [](const tm& tmTime) {
|
||||
std::time_t tt = mktime(const_cast<tm*>(&tmTime));
|
||||
return std::chrono::system_clock::from_time_t(tt);
|
||||
};
|
||||
|
||||
auto tp1 = timeToTimePoint(date1);
|
||||
auto tp2 = timeToTimePoint(date2);
|
||||
|
||||
auto duration = tp1 > tp2 ? tp1 - tp2 : tp2 - tp1;
|
||||
return std::chrono::duration_cast<std::chrono::hours>(duration).count() / 24;
|
||||
}
|
||||
|
||||
// <20><>ȡ<EFBFBD><C8A1>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD>
|
||||
tm getCurrentDate() {
|
||||
std::time_t now = std::time(nullptr);
|
||||
tm tmNow = *std::localtime(&now);
|
||||
tmNow.tm_hour = 0;
|
||||
tmNow.tm_min = 0;
|
||||
tmNow.tm_sec = 0;
|
||||
return tmNow;
|
||||
}
|
||||
|
||||
// <20><>֤<EFBFBD><D6A4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>
|
||||
bool isLocalDateModified() {
|
||||
time_t networkTime = getNetworkTimeInChina();
|
||||
if (networkTime == 0) {
|
||||
return true; // <20><EFBFBD><DEB7><EFBFBD>֤
|
||||
}
|
||||
|
||||
time_t localTime = time(nullptr);
|
||||
double diffDays = difftime(networkTime, localTime) / 86400.0;
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>1<EFBFBD><31><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EEA3A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӳٺ<D3B3>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>أ<EFBFBD>
|
||||
if (fabs(diffDays) > 1.0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
bool isTrail(int trailDays=7) {
|
||||
if (isLocalDateModified())
|
||||
return false;
|
||||
|
||||
tm tmCompile = parseCompileDate(__DATE__), tmCurrent = getCurrentDate();
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
int daysDiff = daysBetweenDates(tmCompile, tmCurrent);
|
||||
|
||||
return daysDiff <= trailDays;
|
||||
}
|
||||
};
|
||||
Binary file not shown.
Reference in New Issue
Block a user