mirror of
https://github.com/chenx-dust/EZ4Connect.git
synced 2026-09-20 10:23:33 +08:00
- Added credential validation in login and settings windows to ensure non-empty and ASCII-only username/password. - Introduced a checkbox to toggle password visibility in both login and settings interfaces. - Updated UI elements for better layout and user experience, including adjustments to labels and button properties. - Refactored signal connections for button actions to improve clarity and functionality.
296 lines
9.8 KiB
C++
296 lines
9.8 KiB
C++
#include <QMessageBox>
|
||
#include <QApplication>
|
||
#include <QNetworkInterface>
|
||
#include <QTextCodec>
|
||
#include <QSettings>
|
||
#include <QProcess>
|
||
#include <QtSystemDetection>
|
||
#include <QDir>
|
||
#include <QFileInfo>
|
||
|
||
#include "utils.h"
|
||
|
||
QString Utils::ConsoleOutputToQString(const QByteArray &byteArray)
|
||
{
|
||
static QString codeName = "";
|
||
if (codeName == "UTF-8")
|
||
{
|
||
return QTextCodec::codecForName("UTF-8")->toUnicode(byteArray);;
|
||
}
|
||
else if (codeName == "GBK")
|
||
{
|
||
return QTextCodec::codecForName("GBK")->toUnicode(byteArray);;
|
||
}
|
||
else if (codeName == "locale")
|
||
{
|
||
return QString::fromLocal8Bit(byteArray);
|
||
}
|
||
else
|
||
{
|
||
QTextCodec *utf8Codec = QTextCodec::codecForName("UTF-8");
|
||
QString utf8Str = utf8Codec->toUnicode(byteArray);
|
||
QByteArray utf8ByteArrayBack = utf8Codec->fromUnicode(utf8Str);
|
||
|
||
QTextCodec *gbkCodec = QTextCodec::codecForName("GBK");
|
||
QString gbkStr = gbkCodec->toUnicode(byteArray);
|
||
QByteArray gbkByteArrayBack = gbkCodec->fromUnicode(gbkStr);
|
||
|
||
if (utf8ByteArrayBack == byteArray && gbkByteArrayBack != byteArray)
|
||
{
|
||
codeName = "UTF-8";
|
||
return utf8Str;
|
||
}
|
||
else if (gbkByteArrayBack == byteArray && utf8ByteArrayBack != byteArray)
|
||
{
|
||
codeName = "GBK";
|
||
return gbkStr;
|
||
}
|
||
else if (gbkByteArrayBack == byteArray && utf8ByteArrayBack == byteArray)
|
||
{
|
||
return utf8Str;
|
||
}
|
||
else
|
||
{
|
||
codeName = "locale";
|
||
return QString::fromLocal8Bit(byteArray);
|
||
}
|
||
}
|
||
}
|
||
|
||
void Utils::setWidgetFixedWhenHidden(QWidget *widget)
|
||
{
|
||
QSizePolicy originPolicy = widget->sizePolicy();
|
||
originPolicy.setRetainSizeWhenHidden(true);
|
||
widget->setSizePolicy(originPolicy);
|
||
}
|
||
|
||
void Utils::showAboutMessageBox(QWidget *parent)
|
||
{
|
||
QMessageBox messageBox(parent);
|
||
messageBox.setWindowTitle("关于");
|
||
messageBox.setTextFormat(Qt::RichText);
|
||
QString aboutText = QApplication::applicationDisplayName() + " " + QApplication::applicationVersion() +
|
||
"<br>专注于 ZJU-Connect 的 ZJU-Connect-for-Windows (HITsz 版)" +
|
||
"<br>作者:<a href='https://github.com/chenx-dust'>Chenx Dust</a>" +
|
||
"<br>项目主页:<a href='https://github.com/" + REPO_NAME + "'>https://github.com/" + REPO_NAME + "</a>" +
|
||
"<br><br>ZJU-Connect-for-Windows" +
|
||
"<br>基于 Qt 编写的 ZJUConnect 图形界面" +
|
||
"<br>作者:<a href='https://myth.cx'>Myth</a>" +
|
||
"<br>项目主页:<a href='https://github.com/Mythologyli/ZJU-Connect-for-Windows'>https://github.com/Mythologyli/ZJU-Connect-for-Windows</a>" +
|
||
"<br><br>zju-connect" +
|
||
"<br>ZJU RVPN 客户端的 Go 语言实现,基于 EasierConnect" +
|
||
"<br>作者:<a href='https://myth.cx'>Myth</a>" +
|
||
"<br>项目主页:<a href='https://github.com/Mythologyli/zju-connect'>https://github.com/Mythologyli/zju-connect</a>" +
|
||
"<br><br>EasierConnect" +
|
||
"<br>EasyConnect 客户端的开源实现" +
|
||
"<br>作者:<a href='https://github.com/lyc8503'>lyc8503</a>" +
|
||
"<br>项目主页:<a href='https://github.com/lyc8503/EasierConnect'>https://github.com/lyc8503/EasierConnect</a>"
|
||
"<br><br>zju-web-login" +
|
||
"<br>ZJU 网页认证登录脚本" +
|
||
"<br>作者:<a href='https://azuk.top'>Azuk 443</a>" +
|
||
"<br>项目主页:<a href='https://github.com/Mythologyli/zju-web-login'>https://github.com/Mythologyli/zju-web-login</a>";
|
||
messageBox.setText(aboutText);
|
||
messageBox.setIconPixmap(QPixmap(":/resource/icon.png").scaled(
|
||
100, 100, Qt::KeepAspectRatio, Qt::SmoothTransformation
|
||
));
|
||
messageBox.exec();
|
||
}
|
||
|
||
QString Utils::getIpv4Address(const QString &interfaceName)
|
||
{
|
||
auto interfaces = QNetworkInterface::allInterfaces();
|
||
for (auto &singleInterface: interfaces)
|
||
{
|
||
if (singleInterface.humanReadableName() == interfaceName)
|
||
{
|
||
auto addresses =
|
||
singleInterface.addressEntries();
|
||
for (auto &address: addresses)
|
||
{
|
||
if (address.ip().protocol() == QAbstractSocket::IPv4Protocol)
|
||
{
|
||
return address.ip().toString();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return "";
|
||
}
|
||
|
||
QString macOSAppBundlePath()
|
||
{
|
||
#ifdef Q_OS_MAC
|
||
QDir dir = QDir(QCoreApplication::applicationDirPath());
|
||
dir.cdUp();
|
||
dir.cdUp();
|
||
QString absolutePath = dir.absolutePath();
|
||
// absolutePath will contain a "/" at the end,
|
||
// but we want the clean path to the .app bundle
|
||
if (absolutePath.length() > 0 && absolutePath.right(1) == "/")
|
||
{
|
||
absolutePath.chop(1);
|
||
}
|
||
return absolutePath;
|
||
#else
|
||
return "";
|
||
#endif
|
||
}
|
||
|
||
QString macOSAppBundleName()
|
||
{
|
||
#ifdef Q_OS_MAC
|
||
QString bundlePath = macOSAppBundlePath();
|
||
QFileInfo fileInfo(bundlePath);
|
||
return fileInfo.baseName();
|
||
#else
|
||
return "";
|
||
#endif
|
||
}
|
||
|
||
QString nativeAppPath()
|
||
{
|
||
return QDir::toNativeSeparators(QCoreApplication::applicationFilePath());
|
||
}
|
||
|
||
void Utils::setAutoStart(bool enable)
|
||
{
|
||
#if defined(Q_OS_WINDOWS)
|
||
QSettings autoStartSettings(R"(HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run)",
|
||
QSettings::NativeFormat);
|
||
if (enable)
|
||
{
|
||
autoStartSettings.setValue(
|
||
QApplication::applicationName(),
|
||
nativeAppPath()
|
||
);
|
||
}
|
||
else
|
||
{
|
||
autoStartSettings.remove(QApplication::applicationName());
|
||
}
|
||
autoStartSettings.sync();
|
||
#elif defined(Q_OS_MACOS)
|
||
{
|
||
QStringList args;
|
||
args << "-e tell application \"System Events\" to delete login item\"" + macOSAppBundleName() + "\"";
|
||
qDebug() << args;
|
||
|
||
// int result = QProcess::execute("osascript", args);
|
||
QProcess process;
|
||
process.start("osascript", args);
|
||
process.waitForFinished();
|
||
QString error = process.readAllStandardError();
|
||
qDebug() << process.readAllStandardOutput();
|
||
qDebug() << error;
|
||
if (!enable && process.error() != QProcess::UnknownError)
|
||
{
|
||
QMessageBox::critical(nullptr, "取消开机自启动失败", "无法删除登录项:" + process.errorString());
|
||
return;
|
||
}
|
||
if (!enable && process.exitCode() != 0)
|
||
{
|
||
QMessageBox::critical(nullptr, "取消开机自启动失败", "无法删除登录项:" + error);
|
||
return;
|
||
}
|
||
}
|
||
if (enable)
|
||
{
|
||
QStringList args;
|
||
args << "-e tell application \"System Events\" to make login item at end with properties {path:\"" +
|
||
macOSAppBundlePath() + "\", hidden:false}";
|
||
qDebug() << args;
|
||
|
||
QProcess process;
|
||
process.start("osascript", args);
|
||
process.waitForFinished();
|
||
qDebug() << process.readAllStandardOutput();
|
||
qDebug() << process.readAllStandardError();
|
||
if (process.error() != QProcess::UnknownError)
|
||
{
|
||
QMessageBox::critical(nullptr, "设置开机自启动失败", "无法创建登录项:" + process.errorString());
|
||
return;
|
||
}
|
||
if (process.exitCode() != 0)
|
||
{
|
||
QMessageBox::critical(nullptr, "设置开机自启动失败", "无法创建登录项:" + process.readAllStandardError());
|
||
return;
|
||
}
|
||
}
|
||
#elif defined(Q_OS_LINUX)
|
||
QString autostartPath = QDir::homePath() + "/.config/autostart/";
|
||
QDir dir(autostartPath);
|
||
QString desktopFilePath = autostartPath + QApplication::applicationName() + ".desktop";
|
||
QFile desktopFile(desktopFilePath);
|
||
|
||
if (dir.exists() && desktopFile.exists())
|
||
{
|
||
if (!desktopFile.remove())
|
||
{
|
||
QMessageBox::critical(nullptr, "取消开机自启动失败", "无法删除 .desktop 文件:" + desktopFilePath);
|
||
return;
|
||
}
|
||
}
|
||
|
||
if (enable)
|
||
{
|
||
if (!dir.exists())
|
||
{
|
||
if (!dir.mkpath("."))
|
||
{
|
||
QMessageBox::critical(nullptr, "设置开机自启动失败", "无法创建 autostart 目录:" + autostartPath);
|
||
return;
|
||
}
|
||
}
|
||
|
||
if (!desktopFile.open(QIODevice::WriteOnly | QIODevice::Text))
|
||
{
|
||
QMessageBox::critical(nullptr, "设置开机自启动失败", "无法创建 .desktop 文件:" + desktopFilePath);
|
||
return;
|
||
}
|
||
|
||
QTextStream out(&desktopFile);
|
||
out << "[Desktop Entry]\n";
|
||
out << "Type=Application\n";
|
||
out << "Name=" << QApplication::applicationName() << "\n";
|
||
out << "Exec=" << nativeAppPath() << "\n";
|
||
out << "X-GNOME-Autostart-enabled=true\n";
|
||
desktopFile.close();
|
||
}
|
||
#endif
|
||
}
|
||
|
||
bool Utils::credentialCheck(const QString &username, const QString &password)
|
||
{
|
||
if (username.isEmpty() || password.isEmpty())
|
||
{
|
||
int status = QMessageBox::warning(nullptr, "警告", "账号或密码为空!\n\n是否继续?", QMessageBox::Ok, QMessageBox::Cancel);
|
||
return status == QMessageBox::Ok;
|
||
}
|
||
|
||
bool asciiOnly = true;
|
||
for (QChar c: username)
|
||
{
|
||
if (c.unicode() > 127)
|
||
{
|
||
asciiOnly = false;
|
||
break;
|
||
}
|
||
}
|
||
for (QChar c: password)
|
||
{
|
||
if (c.unicode() > 127)
|
||
{
|
||
asciiOnly = false;
|
||
break;
|
||
}
|
||
}
|
||
if (!asciiOnly)
|
||
{
|
||
int status = QMessageBox::warning(nullptr, "警告", "账号或密码存在非 ASCII 字符!\n建议检查输入法设置。\n\n是否继续?", QMessageBox::Ok, QMessageBox::Cancel);
|
||
return status == QMessageBox::Ok;
|
||
}
|
||
|
||
return true;
|
||
}
|