#include "licensedata.h" #include #include LicenseData::LicenseData() : productId(0), verMajor(0), verMinor(0), activeState(0) { } QByteArray LicenseData::toBinary() const { QByteArray data; data.reserve(64); QDataStream stream(&data, QIODevice::WriteOnly); stream.setByteOrder(QDataStream::BigEndian); // 1. 主板UUID:固定16字节 QByteArray uuid = boardUuid.left(16); uuid.append(QByteArray(16 - uuid.size(), '\0')); stream.writeRawData(uuid.constData(), 16); // 2. CPU序列号:固定8字节 QByteArray cpu = cpuSerial.left(8); cpu.append(QByteArray(8 - cpu.size(), '\0')); stream.writeRawData(cpu.constData(), 8); // 3. 用户名:长度前缀(1B) + UTF-8数据 QByteArray userBytes = userName.toUtf8(); if (userBytes.size() > 255) { userBytes = userBytes.left(255); } stream << static_cast(userBytes.size()); stream.writeRawData(userBytes.constData(), userBytes.size()); // 4. 失效日期:2字节(距2000-01-01的天数) stream << dateToDays(expireDate); // 5. 产品号:1字节 stream << productId; // 6. 版本号:主版本 + 次版本,各1字节 stream << verMajor << verMinor; // 7. 激活状态:1字节 stream << activeState; return data; } bool LicenseData::fromBinary(const QByteArray &data) { if (data.size() < 30) { qWarning() << "LicenseData::fromBinary: data too short, need at least 30 bytes"; return false; } QDataStream stream(data); stream.setByteOrder(QDataStream::BigEndian); // 1. UUID boardUuid.resize(16); stream.readRawData(boardUuid.data(), 16); // 2. CPU序列号 cpuSerial.resize(8); stream.readRawData(cpuSerial.data(), 8); // 3. 用户名 quint8 nameLen = 0; stream >> nameLen; if (data.size() < 25 + nameLen + 5) { qWarning() << "LicenseData::fromBinary: insufficient data for remaining fields"; return false; } QByteArray userBytes(nameLen, '\0'); stream.readRawData(userBytes.data(), nameLen); userName = QString::fromUtf8(userBytes); // 4. 日期 quint16 days = 0; stream >> days; expireDate = daysToDate(days); // 5. 产品号 stream >> productId; // 6. 版本 stream >> verMajor >> verMinor; // 7. 激活状态 stream >> activeState; return true; } QString LicenseData::toDebugString() const { return QString("{UUID:%1, CPU:%2, User:%3, Expire:%4, Prod:%5, Ver:%6.%7, State:%8}") .arg(uuidBinaryToString(boardUuid)) .arg(binaryToHexString(cpuSerial)) .arg(userName) .arg(expireDate.toString("yyyy-MM-dd")) .arg(productId) .arg(verMajor).arg(verMinor) .arg(activeState); } quint16 LicenseData::dateToDays(const QDate &date) const { QDate base(BASE_YEAR, BASE_MONTH, BASE_DAY); if (!date.isValid() || date < base) { return 0; } return static_cast(base.daysTo(date)); } QDate LicenseData::daysToDate(quint16 days) const { QDate base(BASE_YEAR, BASE_MONTH, BASE_DAY); return base.addDays(days); } QByteArray LicenseData::uuidStringToBinary(const QString &uuidStr) { QString clean = uuidStr; clean.remove('-'); clean.remove('{'); clean.remove('}'); clean = clean.toUpper(); if (clean.size() != 32) { return QByteArray(); } return hexStringToBinary(clean); } QString LicenseData::uuidBinaryToString(const QByteArray &bin) { if (bin.size() != 16) { return QString(); } QString hex = binaryToHexString(bin); return QString("%1-%2-%3-%4-%5") .arg(hex.mid(0, 8)) .arg(hex.mid(8, 4)) .arg(hex.mid(12, 4)) .arg(hex.mid(16, 4)) .arg(hex.mid(20, 12)); } QByteArray LicenseData::hexStringToBinary(const QString &hexStr) { QString clean = hexStr; clean.remove(' '); QByteArray result; result.reserve(clean.size() / 2); for (int i = 0; i + 1 < clean.size(); i += 2) { bool ok; result.append(static_cast(clean.mid(i, 2).toUInt(&ok, 16))); } return result; } QString LicenseData::binaryToHexString(const QByteArray &bin) { return QString::fromLatin1(bin.toHex()).toUpper(); }