From 98026db71efb6a3f94329f11f0d39fc10a8b35a0 Mon Sep 17 00:00:00 2001 From: "E. Stuart Hicks" Date: Fri, 24 Jul 2026 17:06:13 -0400 Subject: [PATCH] builds and runs now. haven't tested functionality yet. --- src/common/pm3process.cpp | 31 +++++------ src/common/pm3process.h | 4 +- src/common/util.cpp | 36 ++++++++++--- src/main.cpp | 9 ++-- src/module/mifare.cpp | 12 ++--- src/ui/mainwindow.cpp | 37 +++++++++----- src/ui/mainwindow.h | 82 +----------------------------- src/ui/mf_trailerdecoderdialog.cpp | 8 +-- src/ui/mf_trailerdecoderdialog.h | 3 +- 9 files changed, 88 insertions(+), 134 deletions(-) diff --git a/src/common/pm3process.cpp b/src/common/pm3process.cpp index bb102e4..81ff5e1 100644 --- a/src/common/pm3process.cpp +++ b/src/common/pm3process.cpp @@ -1,6 +1,6 @@ #include "pm3process.h" -PM3Process::PM3Process(QThread* thread, QObject* parent): QProcess(parent) +PM3Process::PM3Process(QThread* thread, QObject* parent): QProcess(parent), serialPort(new QSerialPort(this)) { moveToThread(thread); setProcessChannelMode(PM3Process::MergedChannels); @@ -12,7 +12,7 @@ PM3Process::PM3Process(QThread* thread, QObject* parent): QProcess(parent) serialListener->setTimerType(Qt::VeryCoarseTimer); connect(serialListener, &QTimer::timeout, this, &PM3Process::onTimeout); connect(this, &PM3Process::readyRead, this, &PM3Process::onReadyRead); - portInfo = nullptr; + serialPort = nullptr; qRegisterMetaType("QProcess::ProcessError"); } @@ -100,17 +100,23 @@ void PM3Process::setSerialListener(const QString& name, bool state) if(state) { currPort = name; - portInfo = new QSerialPortInfo(name); - serialListener->start(); - qDebug() << serialListener->thread(); + serialPort->setPortName(name); // Set the port name + if(!serialPort->open(QIODevice::ReadWrite)) + { + qDebug() << "Failed to open serial port:" << name; + } + else + { + serialListener->start(); + qDebug() << serialListener->thread(); + } } else { serialListener->stop(); - if(portInfo != nullptr) + if(serialPort->isOpen()) { - delete portInfo; - portInfo = nullptr; + serialPort->close(); // Close the serial port } } } @@ -120,14 +126,9 @@ void PM3Process::setSerialListener(bool state) setSerialListener(currPort, state); } -void PM3Process::onTimeout() //when the proxmark3 client is unexpectedly terminated or the PM3 hardware is removed, the isBusy() will return false(only tested on Windows); +void PM3Process::onTimeout() //when the proxmark3 client is unexpectedly terminated or the PM3 hardware is removed, the isOpen() will return false { -// isBusy() is a deprecated function because it will block the serial port when the port is not in use. -// However, the PM3 client is supposed to use the target serial port exclusively, so it should be fine -// isBusy() will always return false on Raspbian, in this case, check "Keep the client active" in the Settings panel. -// -// qDebug()<isBusy(); - if(!portInfo->isBusy()) + if(!serialPort->isOpen()) { killPM3(); } diff --git a/src/common/pm3process.h b/src/common/pm3process.h index 5ae747b..75cbb06 100644 --- a/src/common/pm3process.h +++ b/src/common/pm3process.h @@ -31,18 +31,20 @@ public slots: void setProcEnv(const QStringList* env); void setWorkingDir(const QString& dir); void killPM3(); + private slots: void onTimeout(); void onReadyRead(); + private: bool isRequiringOutput; QString* requiredOutput; // It only works in this class now void setRequiringOutput(bool st);// It only works in this class now QTimer* serialListener; - QSerialPortInfo* portInfo; QString currPath; QString currPort = ""; QStringList currArgs; + QSerialPort* serialPort; // Declare serialPort as a member variable signals: void PM3StatedChanged(bool st, const QString& info = ""); diff --git a/src/common/util.cpp b/src/common/util.cpp index 24b5ab4..d07b1b3 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -1,4 +1,6 @@ #include "util.h" +#include +#include Util::ClientType Util::clientType = CLIENTTYPE_OFFICIAL; @@ -15,7 +17,6 @@ Util::Util(QObject *parent) : QObject(parent) qRegisterMetaType("Util::ClientType"); } - void Util::processOutput(const QString& output) { // qDebug() << "Util::processOutput:" << output; @@ -114,14 +115,33 @@ bool Util::chooseLanguage(QSettings* guiSettings, QMainWindow* window) // make sure the GUISettings is not in any group QSettings* langSettings = new QSettings(":/i18n/languages.ini", QSettings::IniFormat); QMap langMap; - langSettings->setIniCodec("UTF-8"); - langSettings->beginGroup("Languages"); - QStringList langList = langSettings->allKeys(); - for(int i = 0; i < langList.size(); i++) - langMap.insert(langSettings->value(langList[i]).toString(), langList[i]); - langMap.insert(tr("Load from external file"), "(ext)"); - langSettings->endGroup(); + QFile file(":/i18n/languages.ini"); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + qDebug() << "Failed to open languages.ini file."; + delete langSettings; + return false; + } + QByteArray data = file.readAll(); + QString content = QString::fromUtf8(data); + QStringList lines = content.split('\n', Qt::SkipEmptyParts); + for (const QString& line : lines) { + if (line.startsWith("[Languages]")) { + while (!lines.isEmpty()) { + QString line = lines.takeFirst(); + if (line.isEmpty() || line.startsWith("[")) break; + int index = line.indexOf('='); + if (index > 0) { + QString key = line.left(index).trimmed(); + QString value = line.mid(index + 1).trimmed(); + langMap.insert(value, key); + } + } + } + } + file.close(); delete langSettings; + + langMap.insert(tr("Load from external file"), "(ext)"); bool isOk = false; QString selectedText = QInputDialog::getItem(window, "", tr("Choose a language:"), langMap.keys(), 0, false, &isOk); if(!isOk) diff --git a/src/main.cpp b/src/main.cpp index 5e45f45..a973f26 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include int main(int argc, char *argv[]) @@ -20,12 +20,10 @@ int main(int argc, char *argv[]) } delete pluginDir; - QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); - QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8")); QApplication a(argc, argv); QSettings* settings = new QSettings("GUIsettings.ini", QSettings::IniFormat); - settings->setIniCodec("UTF-8"); + QLocale::setDefault(QLocale::system()); settings->beginGroup("language"); QString languageFile = settings->value("extPath").toString(); QString languageName = settings->value("name").toString(); @@ -91,7 +89,6 @@ int main(int argc, char *argv[]) MainWindow w; w.initUI(); w.show(); + return a.exec(); } - - diff --git a/src/module/mifare.cpp b/src/module/mifare.cpp index ca6b9ff..e83e9ab 100644 --- a/src/module/mifare.cpp +++ b/src/module/mifare.cpp @@ -865,11 +865,11 @@ void Mifare::data_syncWithDataWidget(bool syncAll, int block) tmp = ""; if(dataList->at(i) != "") { - tmp += dataList->at(i).midRef(0, 2); + tmp += dataList->at(i).mid(0, 2); for(int j = 1; j < 16; j++) { tmp += " "; - tmp += dataList->at(i).midRef(j * 2, 2); + tmp += dataList->at(i).mid(j * 2, 2); } } ui->MF_dataWidget->item(i, 2)->setText(tmp); @@ -880,11 +880,11 @@ void Mifare::data_syncWithDataWidget(bool syncAll, int block) tmp = ""; if(dataList->at(block) != "") { - tmp += dataList->at(block).midRef(0, 2); + tmp += dataList->at(block).mid(0, 2); for(int j = 1; j < 16; j++) { tmp += " "; - tmp += dataList->at(block).midRef(j * 2, 2); + tmp += dataList->at(block).mid(j * 2, 2); } } ui->MF_dataWidget->item(block, 2)->setText(tmp); @@ -1159,7 +1159,7 @@ bool Mifare::data_saveDataFile(const QString& filename, bool isBin) { for(int i = 0; i < cardType.block_size; i++) { - buff += dataList->at(i); + buff += dataList->at(i).toUtf8(); buff += "\n"; } } @@ -1238,7 +1238,7 @@ void Mifare::data_key2Data() if(dataList->at(getTrailerBlockId(i)) == "") tmp += "FF078069"; // default control bytes else - tmp += dataList->at(getTrailerBlockId(i)).midRef(12, 8); + tmp += dataList->at(getTrailerBlockId(i)).mid(12, 8); if(data_isKeyValid(keyBList->at(i))) tmp += keyBList->at(i); diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp index 3dd3e57..90cd971 100644 --- a/src/ui/mainwindow.cpp +++ b/src/ui/mainwindow.cpp @@ -7,28 +7,29 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent) , ui(new Ui::MainWindow) + , MFCardTypeBtnGroup(new QButtonGroup(this)) { ui->setupUi(this); dockAllWindows = new QAction(tr("Dock all windows"), this); myInfo = new QAction("wh201906", this); currVersion = new QAction(tr("Ver: ") + QApplication::applicationVersion().section('.', 0, -2), this); // ignore the 4th version number checkUpdate = new QAction(tr("Check Update"), this); - connect(dockAllWindows, &QAction::triggered, [ = ]() + connect(dockAllWindows, &QAction::triggered, [this]() { for(int i = 0; i < dockList.size(); i++) dockList[i]->setFloating(false); }); - connect(myInfo, &QAction::triggered, [ = ]() + connect(myInfo, &QAction::triggered, [this]() { QDesktopServices::openUrl(QUrl("https://github.com/wh201906")); }); - connect(checkUpdate, &QAction::triggered, [ = ]() + connect(checkUpdate, &QAction::triggered, [this]() { QDesktopServices::openUrl(QUrl("https://github.com/wh201906/Proxmark3GUI/releases")); }); + connect(MFCardTypeBtnGroup, &QButtonGroup::buttonToggled, this, &MainWindow::MF_onMFCardTypeChanged); settings = new QSettings("GUIsettings.ini", QSettings::IniFormat); - settings->setIniCodec("UTF-8"); pm3Thread = new QThread(this); connect(QApplication::instance(), &QApplication::aboutToQuit, pm3Thread, &QThread::quit); @@ -101,6 +102,13 @@ void MainWindow::loadConfig() void MainWindow::initUI() // will be called by main.app { +// int numberOfButtons = 10; // No idea what this should be set to. Stupid Qwen. +// for (int i = 0; i < numberOfButtons; ++i) { +// QRadioButton* button = new QRadioButton("Button " + QString::number(i), this); +// MFCardTypeBtnGroup->addButton(button); +// button->setProperty("id", i); // Set the id property +// } + ui->retranslateUi(this); uiInit(); signalInit(); @@ -451,14 +459,14 @@ void MainWindow::on_MF_keyWidget_resized(QObject* obj_addr, QEvent& event) } } -void MainWindow::MF_onMFCardTypeChanged(int id, bool st) +void MainWindow::MF_onMFCardTypeChanged(QAbstractButton* button, bool checked) { MFCardTypeBtnGroup->blockSignals(true); - qDebug() << id << MFCardTypeBtnGroup->checkedId(); - if(!st) + qDebug() << button->property("id").toInt() << MFCardTypeBtnGroup->checkedId(); + if (!checked) { int result; - if(id > MFCardTypeBtnGroup->checkedId()) // id is specified in uiInit() with a proper order, so I can compare the size by id. + if (button->property("id").toInt() > MFCardTypeBtnGroup->checkedId()) { result = QMessageBox::question(this, tr("Info"), tr("Some of the data and key will be cleared.") + "\n" + tr("Continue?"), QMessageBox::Yes | QMessageBox::No); } @@ -466,7 +474,7 @@ void MainWindow::MF_onMFCardTypeChanged(int id, bool st) { result = QMessageBox::Yes; } - if(result == QMessageBox::Yes) + if (result == QMessageBox::Yes) { qDebug() << "Yes"; mifare->setCardType(MFCardTypeBtnGroup->checkedId()); @@ -477,7 +485,7 @@ void MainWindow::MF_onMFCardTypeChanged(int id, bool st) else { qDebug() << "No"; - MFCardTypeBtnGroup->button(id)->setChecked(true); + button->setChecked(true); } } MFCardTypeBtnGroup->blockSignals(false); @@ -975,7 +983,7 @@ void MainWindow::on_MF_Sniff_loadButton_clicked() // use a tmp file to support c qDebug() << filename; if(filename != "") { - QString tmpFile = "tmp" + QString::number(QDateTime::currentDateTimeUtc().toTime_t()) + defaultExtension; + QString tmpFile = "tmp" + QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch()) + defaultExtension; if(QFile::copy(filename, clientTracePath.absolutePath() + "/" + tmpFile)) { mifare->loadSniff(tmpFile); @@ -1012,7 +1020,7 @@ void MainWindow::on_MF_Sniff_saveButton_clicked() qDebug() << filename; if(filename != "") { - QString tmpFile = "tmp" + QString::number(QDateTime::currentDateTimeUtc().toTime_t()) + defaultExtension; + QString tmpFile = "tmp" + QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch()) + defaultExtension; mifare->saveSniff(tmpFile); for(int i = 0; i < 100; i++) { @@ -1130,7 +1138,8 @@ void MainWindow::uiInit() MFCardTypeBtnGroup->addButton(ui->MF_Type_1kButton, 1); MFCardTypeBtnGroup->addButton(ui->MF_Type_2kButton, 2); MFCardTypeBtnGroup->addButton(ui->MF_Type_4kButton, 4); - connect(MFCardTypeBtnGroup, QOverload::of(&QButtonGroup::buttonToggled), this, &MainWindow::MF_onMFCardTypeChanged); + //connect(MFCardTypeBtnGroup, QOverload::of(&QButtonGroup::buttonToggled), this, &MainWindow::MF_onMFCardTypeChanged); + connect(MFCardTypeBtnGroup, &QButtonGroup::buttonToggled, this, &MainWindow::MF_onMFCardTypeChanged); ui->MF_keyWidget->installEventFilter(this); ui->MF_dataWidget->installEventFilter(this); @@ -1442,7 +1451,7 @@ void MainWindow::loadClientPathList() settings->endGroup(); ui->PM3_pathBox->clear(); - for(const QString& clientPath : qAsConst(m_clientPathList)) + for(const QString& clientPath : std::as_const(m_clientPathList)) ui->PM3_pathBox->addItem(clientPath); } diff --git a/src/ui/mainwindow.h b/src/ui/mainwindow.h index b28a70b..e491f44 100644 --- a/src/ui/mainwindow.h +++ b/src/ui/mainwindow.h @@ -52,174 +52,96 @@ class MainWindow : public QMainWindow void initUI(); bool eventFilter(QObject *watched, QEvent *event) override; + public slots: void refreshOutput(const QString& output); void refreshCMD(const QString& cmd); void setStatusBar(QLabel* target, const QString& text); void onPM3StateChanged(bool st, const QString& info); - void MF_onMFCardTypeChanged(int id, bool st); + void MF_onMFCardTypeChanged(QAbstractButton* button, bool checked); void on_Raw_keyPressed(QObject *obj_addr, QEvent &event); void on_MF_keyWidget_resized(QObject *obj_addr, QEvent &event); void onPM3ErrorOccurred(QProcess::ProcessError error); void onPM3HWConnectFailed(); private slots: - void on_PM3_connectButton_clicked(); - void on_Raw_sendCMDButton_clicked(); - void on_PM3_disconnectButton_clicked(); - void on_Raw_clearOutputButton_clicked(); - void sendMSG(); - void on_portSearchTimer_timeout(); - void on_Raw_CMDHistoryBox_stateChanged(int arg1); - void on_Raw_clearHistoryButton_clicked(); - void on_Raw_CMDHistoryWidget_itemDoubleClicked(QListWidgetItem *item); - void on_MF_Attack_chkButton_clicked(); - void on_MF_Attack_nestedButton_clicked(); - void on_MF_Attack_hardnestedButton_clicked(); - void on_MF_Sniff_sniffButton_clicked(); - void on_MF_Sniff_listButton_clicked(); - void on_MF_RW_readSelectedButton_clicked(); - void on_MF_RW_readBlockButton_clicked(); - void on_MF_RW_writeBlockButton_clicked(); - void on_MF_Attack_infoButton_clicked(); - void on_MF_RW_writeSelectedButton_clicked(); - void on_MF_RW_dumpButton_clicked(); - void on_MF_RW_restoreButton_clicked(); - void on_MF_UID_readSelectedButton_clicked(); - void on_MF_UID_readBlockButton_clicked(); - void on_MF_UID_writeSelectedButton_clicked(); - void on_MF_UID_writeBlockButton_clicked(); - void on_MF_File_loadButton_clicked(); - void on_MF_File_saveButton_clicked(); - void on_MF_data2KeyButton_clicked(); - void on_MF_key2DataButton_clicked(); - void on_MF_dataWidget_itemChanged(QTableWidgetItem *item); - void on_MF_File_clearButton_clicked(); - void on_MF_keyWidget_itemChanged(QTableWidgetItem *item); - void on_MF_UID_wipeButton_clicked(); - void on_MF_UID_aboutUIDButton_clicked(); - void on_MF_UID_setParaButton_clicked(); - void on_MF_UID_lockButton_clicked(); - void on_MF_Sim_readSelectedButton_clicked(); - void on_MF_Sim_writeSelectedButton_clicked(); - void on_MF_Sim_clearButton_clicked(); - void on_MF_Sim_simButton_clicked(); - void on_MF_Sniff_loadButton_clicked(); - void on_MF_Sniff_saveButton_clicked(); - void on_GroupBox_clicked(bool checked); - void on_MF_selectAllBox_stateChanged(int arg1); - void on_MF_fillKeysButton_clicked(); - void on_MF_14aSniff_snoopButton_clicked(); - void on_MF_trailerDecoderButton_clicked(); - void on_MF_selectTrailerBox_stateChanged(int arg1); - void on_stopButton_clicked(); - void on_Raw_CMDEdit_textChanged(const QString &arg1); - void on_MF_Attack_darksideButton_clicked(); - void on_Set_Client_startArgsEdit_editingFinished(); - void on_Set_Client_forceEnabledBox_stateChanged(int arg1); - void on_Set_UI_setLanguageButton_clicked(); - void setButtonsEnabled(bool st); - void on_PM3_refreshPortButton_clicked(); - void on_Set_Client_envScriptEdit_editingFinished(); - void on_Set_Client_keepClientActiveBox_stateChanged(int arg1); - void on_LF_LFConf_freqSlider_valueChanged(int value); - void on_LF_LFConf_freqDivisorBox_valueChanged(int arg1); - void on_LF_LFConf_freq125kButton_clicked(); - void on_LF_LFConf_freq134kButton_clicked(); - void on_LF_Op_searchButton_clicked(); - void on_LF_Op_readButton_clicked(); - void on_LF_Op_tuneButton_clicked(); - void on_LF_Op_sniffButton_clicked(); - void on_LF_LFConf_getButton_clicked(); - void on_LF_LFConf_setButton_clicked(); - void on_LF_LFConf_resetButton_clicked(); - void on_Set_Client_workingDirEdit_editingFinished(); - void on_Set_Client_configPathEdit_editingFinished(); - void setState(bool st); - void on_Set_Client_configFileBox_currentIndexChanged(int index); - void on_Set_UI_Opacity_Box_valueChanged(int arg1); - void on_Set_UI_Theme_setButton_clicked(); - void on_Set_UI_Font_setButton_clicked(); - void on_Set_UI_DataFont_setButton_clicked(); - void on_Set_UI_CMDFont_setButton_clicked(); - void onLFfreqConfChanged(int divisor, bool isCustomized); private: diff --git a/src/ui/mf_trailerdecoderdialog.cpp b/src/ui/mf_trailerdecoderdialog.cpp index 904cd39..691b461 100644 --- a/src/ui/mf_trailerdecoderdialog.cpp +++ b/src/ui/mf_trailerdecoderdialog.cpp @@ -14,7 +14,7 @@ MF_trailerDecoderDialog::MF_trailerDecoderDialog(QWidget *parent) : sizeGroup = new QButtonGroup(this); sizeGroup->addButton(ui->size4Button, 4); sizeGroup->addButton(ui->size16Button, 16); - connect(sizeGroup, QOverload::of(&QButtonGroup::buttonToggled), this, &MF_trailerDecoderDialog::on_blockSizeChanged); + connect(sizeGroup, &QButtonGroup::buttonToggled, this, &MF_trailerDecoderDialog::on_blockSizeChanged); connect(ui->C0Box, QOverload::of(&QSpinBox::valueChanged), this, &MF_trailerDecoderDialog::on_boxChanged); connect(ui->C1Box, QOverload::of(&QSpinBox::valueChanged), this, &MF_trailerDecoderDialog::on_boxChanged); connect(ui->C2Box, QOverload::of(&QSpinBox::valueChanged), this, &MF_trailerDecoderDialog::on_boxChanged); @@ -32,6 +32,7 @@ MF_trailerDecoderDialog::~MF_trailerDecoderDialog() { delete ui; } + void MF_trailerDecoderDialog::on_accessBitsEdit_textChanged(const QString &arg1) { ui->C0Box->blockSignals(true); @@ -96,10 +97,11 @@ void MF_trailerDecoderDialog::on_accessBitsEdit_textChanged(const QString &arg1) ui->C3Box->blockSignals(false); } -void MF_trailerDecoderDialog::on_blockSizeChanged(int id, bool st) +void MF_trailerDecoderDialog::on_blockSizeChanged(QAbstractButton* button, bool checked) { - if(st) + if(checked) { + int id = sizeGroup->id(button); if(id == 4) { ui->dataBlockWidget->verticalHeaderItem(0)->setText(tr("Block") + "0"); diff --git a/src/ui/mf_trailerdecoderdialog.h b/src/ui/mf_trailerdecoderdialog.h index 8a83f50..e2a34d7 100644 --- a/src/ui/mf_trailerdecoderdialog.h +++ b/src/ui/mf_trailerdecoderdialog.h @@ -25,7 +25,8 @@ private slots: void on_accessBitsEdit_textChanged(const QString& arg1); - void on_blockSizeChanged(int id, bool st); + // Change the parameter types here + void on_blockSizeChanged(QAbstractButton* button, bool checked); void on_boxChanged(); private: