174 lines
4.1 KiB
C
174 lines
4.1 KiB
C
|
|
#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;
|
|||
|
|
}
|
|||
|
|
};
|