202 lines
6.7 KiB
C++
202 lines
6.7 KiB
C++
#include <QCoreApplication>
|
||
#include <QCommandLineParser>
|
||
#include <QFile>
|
||
#include <QFileInfo>
|
||
#include <QDir>
|
||
#include <QTextStream>
|
||
#include <iostream>
|
||
#include "ConfigEncryption.h"
|
||
|
||
// 打印到控制台(支持中文)
|
||
void printConsole(const QString& message)
|
||
{
|
||
#ifdef _WIN32
|
||
// Windows 控制台输出
|
||
std::wcout << message.toStdWString() << std::endl;
|
||
#else
|
||
std::cout << message.toStdString() << std::endl;
|
||
#endif
|
||
}
|
||
|
||
int main(int argc, char *argv[])
|
||
{
|
||
QCoreApplication app(argc, argv);
|
||
app.setApplicationName("ConfigDecryptor");
|
||
app.setApplicationVersion("1.0.0");
|
||
|
||
// 设置控制台输出编码(Windows)
|
||
#ifdef _WIN32
|
||
system("chcp 65001 > nul");
|
||
#endif
|
||
|
||
// 命令行参数解析
|
||
QCommandLineParser parser;
|
||
parser.setApplicationDescription("配置文件解密工具 - 用于解密 config.encrypt 文件");
|
||
parser.addHelpOption();
|
||
parser.addVersionOption();
|
||
|
||
// 添加位置参数:加密文件路径
|
||
parser.addPositionalArgument("file", "要解密的 config.encrypt 文件路径");
|
||
|
||
// 添加密钥选项
|
||
QCommandLineOption keyOption(QStringList() << "k" << "key",
|
||
"解密密钥(格式:AppName + VisionRobot)",
|
||
"key");
|
||
parser.addOption(keyOption);
|
||
|
||
// 添加输出路径选项(可选)
|
||
QCommandLineOption outputOption(QStringList() << "o" << "output",
|
||
"输出文件路径(默认:与加密文件同级目录下的 config.xml)",
|
||
"output");
|
||
parser.addOption(outputOption);
|
||
|
||
// 添加静默模式选项
|
||
QCommandLineOption silentOption(QStringList() << "s" << "silent",
|
||
"静默模式(不显示详细信息)");
|
||
parser.addOption(silentOption);
|
||
|
||
// 解析命令行参数
|
||
parser.process(app);
|
||
|
||
bool silent = parser.isSet(silentOption);
|
||
|
||
// 显示欢迎信息
|
||
if (!silent) {
|
||
printConsole("========================================");
|
||
printConsole(" 配置文件解密工具 v1.0.0");
|
||
printConsole(" Config Decryptor for VisionRobot");
|
||
printConsole("========================================");
|
||
printConsole("");
|
||
}
|
||
|
||
// 获取位置参数
|
||
QStringList args = parser.positionalArguments();
|
||
if (args.isEmpty()) {
|
||
printConsole("错误:未指定要解密的文件路径");
|
||
printConsole("");
|
||
parser.showHelp(1);
|
||
return 1;
|
||
}
|
||
|
||
QString encryptedFilePath = args.at(0);
|
||
|
||
// 检查文件是否存在
|
||
QFileInfo fileInfo(encryptedFilePath);
|
||
if (!fileInfo.exists()) {
|
||
printConsole(QString("错误:文件不存在: %1").arg(encryptedFilePath));
|
||
return 1;
|
||
}
|
||
|
||
if (!fileInfo.isFile()) {
|
||
printConsole(QString("错误:指定的路径不是文件: %1").arg(encryptedFilePath));
|
||
return 1;
|
||
}
|
||
|
||
// 获取密钥
|
||
QString key = parser.value(keyOption);
|
||
if (key.isEmpty()) {
|
||
printConsole("错误:未指定解密密钥");
|
||
printConsole("请使用 -k 或 --key 选项指定密钥");
|
||
printConsole("密钥格式:应用程序名称 + \"VisionRobot\"");
|
||
printConsole("");
|
||
printConsole("示例:");
|
||
printConsole(" GrabBagApp 的密钥为: GrabBagAppVisionRobot");
|
||
printConsole(" LapWeldApp 的密钥为: LapWeldAppVisionRobot");
|
||
printConsole("");
|
||
parser.showHelp(1);
|
||
return 1;
|
||
}
|
||
|
||
// 确定输出路径
|
||
QString outputFilePath;
|
||
if (parser.isSet(outputOption)) {
|
||
outputFilePath = parser.value(outputOption);
|
||
} else {
|
||
// 默认输出到同级目录下的 config.xml
|
||
QDir fileDir = fileInfo.absoluteDir();
|
||
outputFilePath = fileDir.absoluteFilePath("config.xml");
|
||
}
|
||
|
||
if (!silent) {
|
||
printConsole(QString("加密文件: %1").arg(fileInfo.absoluteFilePath()));
|
||
printConsole(QString("输出文件: %1").arg(outputFilePath));
|
||
printConsole(QString("解密密钥: %1").arg(key));
|
||
printConsole("");
|
||
printConsole("开始解密...");
|
||
}
|
||
|
||
// 读取加密文件
|
||
QFile encryptedFile(encryptedFilePath);
|
||
if (!encryptedFile.open(QIODevice::ReadOnly)) {
|
||
printConsole(QString("错误:无法打开加密文件: %1").arg(encryptedFilePath));
|
||
return 1;
|
||
}
|
||
|
||
QByteArray encryptedData = encryptedFile.readAll();
|
||
encryptedFile.close();
|
||
|
||
if (encryptedData.isEmpty()) {
|
||
printConsole("错误:加密文件为空");
|
||
return 1;
|
||
}
|
||
|
||
// 验证文件格式
|
||
if (!encryptedData.startsWith("VRENC1.0")) {
|
||
printConsole("警告:文件格式不匹配,可能不是有效的加密配置文件");
|
||
printConsole("是否继续尝试解密?(Y/N)");
|
||
|
||
char response;
|
||
std::cin >> response;
|
||
if (response != 'Y' && response != 'y') {
|
||
printConsole("操作已取消");
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
// 解密数据
|
||
QByteArray decryptedData = ConfigEncryption::DecryptConfig(encryptedData, key);
|
||
|
||
if (decryptedData.isEmpty()) {
|
||
printConsole("错误:解密失败!");
|
||
printConsole("可能的原因:");
|
||
printConsole(" 1. 密钥错误");
|
||
printConsole(" 2. 文件已损坏");
|
||
printConsole(" 3. 文件格式不正确");
|
||
return 1;
|
||
}
|
||
|
||
// 写入解密后的文件
|
||
QFile outputFile(outputFilePath);
|
||
if (!outputFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
||
printConsole(QString("错误:无法创建输出文件: %1").arg(outputFilePath));
|
||
return 1;
|
||
}
|
||
|
||
qint64 written = outputFile.write(decryptedData);
|
||
outputFile.close();
|
||
|
||
if (written != decryptedData.size()) {
|
||
printConsole("错误:写入输出文件失败");
|
||
return 1;
|
||
}
|
||
|
||
// 成功
|
||
if (!silent) {
|
||
printConsole("");
|
||
printConsole("========================================");
|
||
printConsole(" 解密成功!");
|
||
printConsole("========================================");
|
||
printConsole(QString("解密后的文件已保存到: %1").arg(outputFilePath));
|
||
printConsole(QString("文件大小: %1 字节").arg(decryptedData.size()));
|
||
printConsole("");
|
||
printConsole("提示:");
|
||
printConsole(" 修改配置后,重新启动应用程序将自动重新加密配置文件。");
|
||
printConsole(" 原始加密文件将被更新,config.xml 将被删除。");
|
||
printConsole("");
|
||
} else {
|
||
printConsole("解密成功");
|
||
}
|
||
|
||
return 0;
|
||
}
|