2023-04-09 05:35:35 +00:00
|
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
|
2023-03-20 06:53:56 +00:00
|
|
|
#include "client.h"
|
2023-01-03 15:37:14 +00:00
|
|
|
#ifndef Q_OS_WASM
|
2022-01-24 02:23:08 +00:00
|
|
|
#include "server.h"
|
2023-02-15 11:54:35 +00:00
|
|
|
#include "packman.h"
|
2023-01-03 15:37:14 +00:00
|
|
|
#endif
|
2022-01-24 02:23:08 +00:00
|
|
|
|
2022-12-18 04:52:52 +00:00
|
|
|
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
|
|
|
|
#include "shell.h"
|
|
|
|
#endif
|
|
|
|
|
2022-12-18 07:08:01 +00:00
|
|
|
#if defined(Q_OS_WIN32)
|
|
|
|
#include "applink.c"
|
|
|
|
#endif
|
|
|
|
|
2023-03-08 04:14:02 +00:00
|
|
|
#ifndef FK_SERVER_ONLY
|
2022-12-18 04:52:52 +00:00
|
|
|
#include <QSplashScreen>
|
|
|
|
#include <QScreen>
|
2023-01-03 15:37:14 +00:00
|
|
|
#include <QFileDialog>
|
2023-03-08 04:14:02 +00:00
|
|
|
# ifndef Q_OS_ANDROID
|
|
|
|
# include <QQuickStyle>
|
|
|
|
# endif
|
|
|
|
#include "qmlbackend.h"
|
2023-01-29 10:11:41 +00:00
|
|
|
#endif
|
2022-12-18 04:52:52 +00:00
|
|
|
|
2023-01-03 15:37:14 +00:00
|
|
|
#if defined(Q_OS_ANDROID) || defined(Q_OS_WASM)
|
2022-09-14 05:01:10 +00:00
|
|
|
static bool copyPath(const QString &srcFilePath, const QString &tgtFilePath)
|
|
|
|
{
|
|
|
|
QFileInfo srcFileInfo(srcFilePath);
|
|
|
|
if (srcFileInfo.isDir()) {
|
|
|
|
QDir targetDir(tgtFilePath);
|
|
|
|
if (!targetDir.exists()) {
|
|
|
|
targetDir.cdUp();
|
|
|
|
if (!targetDir.mkdir(QFileInfo(tgtFilePath).fileName()))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
QDir sourceDir(srcFilePath);
|
|
|
|
QStringList fileNames = sourceDir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System);
|
|
|
|
foreach (const QString &fileName, fileNames) {
|
|
|
|
const QString newSrcFilePath
|
|
|
|
= srcFilePath + QLatin1Char('/') + fileName;
|
|
|
|
const QString newTgtFilePath
|
|
|
|
= tgtFilePath + QLatin1Char('/') + fileName;
|
|
|
|
if (!copyPath(newSrcFilePath, newTgtFilePath))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
QFile::remove(tgtFilePath);
|
|
|
|
if (!QFile::copy(srcFilePath, tgtFilePath))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2023-03-08 04:14:02 +00:00
|
|
|
static void installFkAssets(const QString &src, const QString &dest) {
|
2023-03-09 05:32:09 +00:00
|
|
|
QFile f(dest + "/fk_ver");
|
2023-03-08 04:14:02 +00:00
|
|
|
if (f.exists() && f.open(QIODevice::ReadOnly)) {
|
2023-03-09 05:32:09 +00:00
|
|
|
auto ver = f.readLine().simplified();
|
2023-03-08 04:14:02 +00:00
|
|
|
if (ver == FK_VERSION) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#ifdef Q_OS_ANDROID
|
|
|
|
copyPath(src, dest);
|
|
|
|
#elif defined(Q_OS_LINUX)
|
|
|
|
system(QString("cp -r %1 %2").arg(src).arg(dest).toUtf8());
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2023-02-15 19:54:53 +00:00
|
|
|
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
static void prepareForLinux() {
|
|
|
|
// if user executes /usr/bin/FreeKill, that means freekill is installed by
|
|
|
|
// package manager, and then we need to copy assets to ~/.local and change cwd
|
|
|
|
char buf[256] = {0};
|
|
|
|
int len = readlink("/proc/self/exe", buf, 256);
|
|
|
|
if (!strcmp(buf, "/usr/bin/FreeKill")) {
|
|
|
|
system("mkdir -p ~/.local/share/FreeKill");
|
2023-03-08 04:14:02 +00:00
|
|
|
installFkAssets("/usr/share/FreeKill", "~/.local/share");
|
2023-02-15 19:54:53 +00:00
|
|
|
chdir(getenv("HOME"));
|
|
|
|
chdir(".local/share/FreeKill");
|
|
|
|
} else if (!strcmp(buf, "/usr/local/bin/FreeKill")) {
|
|
|
|
system("mkdir -p ~/.local/share/FreeKill");
|
2023-03-08 04:14:02 +00:00
|
|
|
installFkAssets("/usr/local/share/FreeKill", "~/.local/share");
|
2023-02-15 19:54:53 +00:00
|
|
|
chdir(getenv("HOME"));
|
|
|
|
chdir(".local/share/FreeKill");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2022-12-18 04:52:52 +00:00
|
|
|
void fkMsgHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) {
|
|
|
|
fprintf(stderr, "\r[%s] ", QTime::currentTime().toString("hh:mm:ss").toLatin1().constData());
|
2022-12-18 13:19:35 +00:00
|
|
|
auto localMsg = msg.toUtf8();
|
2023-01-29 10:11:41 +00:00
|
|
|
auto threadName = QThread::currentThread()->objectName().toLatin1();
|
2022-12-18 04:52:52 +00:00
|
|
|
switch (type) {
|
|
|
|
case QtDebugMsg:
|
2023-01-29 10:11:41 +00:00
|
|
|
fprintf(stderr, "[%s/DEBUG] %s\n", threadName.constData(), localMsg.constData());
|
2022-12-18 04:52:52 +00:00
|
|
|
break;
|
|
|
|
case QtInfoMsg:
|
2023-01-29 10:11:41 +00:00
|
|
|
fprintf(stderr, "[%s/INFO] %s\n", threadName.constData(), localMsg.constData());
|
2022-12-18 04:52:52 +00:00
|
|
|
break;
|
|
|
|
case QtWarningMsg:
|
2023-01-29 10:11:41 +00:00
|
|
|
fprintf(stderr, "[%s/WARNING] %s\n", threadName.constData(), localMsg.constData());
|
2023-02-21 05:44:24 +00:00
|
|
|
// if (Backend != nullptr) {
|
|
|
|
// Backend->notifyUI("ErrorDialog", localMsg);
|
|
|
|
// }
|
2022-12-18 04:52:52 +00:00
|
|
|
break;
|
|
|
|
case QtCriticalMsg:
|
2023-01-29 10:11:41 +00:00
|
|
|
fprintf(stderr, "[%s/CRITICAL] %s\n", threadName.constData(), localMsg.constData());
|
2023-03-08 04:14:02 +00:00
|
|
|
#ifndef FK_SERVER_ONLY
|
2023-02-15 11:54:35 +00:00
|
|
|
if (Backend != nullptr) {
|
|
|
|
Backend->notifyUI("ErrorDialog", QString("⛔ %1/Error occured!\n %2")
|
|
|
|
.arg(threadName).arg(localMsg));
|
|
|
|
}
|
2023-03-08 04:14:02 +00:00
|
|
|
#endif
|
2022-12-18 04:52:52 +00:00
|
|
|
break;
|
|
|
|
case QtFatalMsg:
|
2023-01-29 10:11:41 +00:00
|
|
|
fprintf(stderr, "[%s/FATAL] %s\n", threadName.constData(), localMsg.constData());
|
2022-12-18 04:52:52 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-24 02:23:08 +00:00
|
|
|
int main(int argc, char *argv[])
|
|
|
|
{
|
2022-12-18 04:52:52 +00:00
|
|
|
QThread::currentThread()->setObjectName("Main");
|
|
|
|
qInstallMessageHandler(fkMsgHandler);
|
2022-04-30 07:27:56 +00:00
|
|
|
QCoreApplication *app;
|
|
|
|
QCoreApplication::setApplicationName("FreeKill");
|
2023-03-08 04:14:02 +00:00
|
|
|
QCoreApplication::setApplicationVersion(FK_VERSION);
|
2022-04-30 07:27:56 +00:00
|
|
|
|
2023-02-15 19:54:53 +00:00
|
|
|
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
|
|
|
|
prepareForLinux();
|
|
|
|
#endif
|
|
|
|
|
2023-03-08 04:14:02 +00:00
|
|
|
#ifndef FK_CLIENT_ONLY
|
2022-04-30 07:27:56 +00:00
|
|
|
QCommandLineParser parser;
|
|
|
|
parser.setApplicationDescription("FreeKill server");
|
|
|
|
parser.addHelpOption();
|
|
|
|
parser.addVersionOption();
|
|
|
|
parser.addOption({{"s", "server"}, "start server at <port>", "port"});
|
|
|
|
QStringList cliOptions;
|
|
|
|
for (int i = 0; i < argc; i++)
|
|
|
|
cliOptions << argv[i];
|
|
|
|
|
|
|
|
parser.parse(cliOptions);
|
|
|
|
|
|
|
|
bool startServer = parser.isSet("server");
|
|
|
|
ushort serverPort = 9527;
|
|
|
|
|
|
|
|
if (startServer) {
|
|
|
|
app = new QCoreApplication(argc, argv);
|
|
|
|
bool ok = false;
|
|
|
|
if (parser.value("server").toInt(&ok) && ok)
|
|
|
|
serverPort = parser.value("server").toInt();
|
|
|
|
Server *server = new Server;
|
|
|
|
if (!server->listen(QHostAddress::Any, serverPort)) {
|
2022-12-18 04:52:52 +00:00
|
|
|
qFatal("cannot listen on port %d!\n", serverPort);
|
2022-04-30 07:27:56 +00:00
|
|
|
app->exit(1);
|
2022-12-18 04:52:52 +00:00
|
|
|
} else {
|
|
|
|
qInfo("Server is listening on port %d", serverPort);
|
2023-03-08 04:14:02 +00:00
|
|
|
# if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
|
2022-12-18 04:52:52 +00:00
|
|
|
auto shell = new Shell;
|
2023-02-15 11:54:35 +00:00
|
|
|
Pacman = new PackMan;
|
2022-12-18 04:52:52 +00:00
|
|
|
shell->start();
|
2023-03-08 04:14:02 +00:00
|
|
|
# endif
|
2022-01-24 02:23:08 +00:00
|
|
|
}
|
2022-04-30 07:27:56 +00:00
|
|
|
return app->exec();
|
|
|
|
}
|
2023-03-08 04:14:02 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef FK_SERVER_ONLY
|
|
|
|
qFatal("This is server-only build and have no GUI support.\n\
|
|
|
|
Please use ./FreeKill -s to start a server in command line.");
|
2023-01-03 15:37:14 +00:00
|
|
|
#else
|
2023-03-08 04:14:02 +00:00
|
|
|
|
|
|
|
# ifdef Q_OS_WASM
|
2023-01-03 15:37:14 +00:00
|
|
|
copyPath(":/", QDir::currentPath());
|
2023-03-08 04:14:02 +00:00
|
|
|
# endif
|
2022-04-30 07:27:56 +00:00
|
|
|
|
2022-12-18 04:52:52 +00:00
|
|
|
app = new QApplication(argc, argv);
|
2023-03-08 04:14:02 +00:00
|
|
|
# ifdef DESKTOP_BUILD
|
2023-01-12 14:53:22 +00:00
|
|
|
((QApplication *)app)->setWindowIcon(QIcon("image/icon.png"));
|
2023-03-08 04:14:02 +00:00
|
|
|
# endif
|
2022-12-18 04:52:52 +00:00
|
|
|
|
2023-03-08 04:14:02 +00:00
|
|
|
# define SHOW_SPLASH_MSG(msg) \
|
2022-12-18 04:52:52 +00:00
|
|
|
splash.showMessage(msg, Qt::AlignHCenter | Qt::AlignBottom);
|
|
|
|
|
2023-03-08 04:14:02 +00:00
|
|
|
# ifdef Q_OS_ANDROID
|
2023-03-04 22:39:03 +00:00
|
|
|
QJniObject::callStaticMethod <void>("org/notify/FreeKill/Helper", "InitView", "()V");
|
|
|
|
QDir::setCurrent("/storage/emulated/0/Android/data/org.notify.FreeKill/files");
|
|
|
|
|
2022-12-18 04:52:52 +00:00
|
|
|
QScreen *screen = qobject_cast<QApplication *>(app)->primaryScreen();
|
|
|
|
QRect screenGeometry = screen->geometry();
|
|
|
|
int screenWidth = screenGeometry.width();
|
|
|
|
int screenHeight = screenGeometry.height();
|
|
|
|
QSplashScreen splash(QPixmap("assets:/res/image/splash.jpg").scaled(screenWidth, screenHeight));
|
|
|
|
splash.showFullScreen();
|
|
|
|
SHOW_SPLASH_MSG("Copying resources...");
|
2023-03-08 04:14:02 +00:00
|
|
|
installFkAssets("assets:/res", QDir::currentPath());
|
|
|
|
# else
|
2022-12-18 04:52:52 +00:00
|
|
|
QSplashScreen splash(QPixmap("image/splash.jpg"));
|
|
|
|
splash.show();
|
2023-03-08 04:14:02 +00:00
|
|
|
# endif
|
2022-04-30 07:27:56 +00:00
|
|
|
|
2022-12-18 04:52:52 +00:00
|
|
|
SHOW_SPLASH_MSG("Loading qml files...");
|
2022-04-30 07:27:56 +00:00
|
|
|
QQmlApplicationEngine *engine = new QQmlApplicationEngine;
|
2023-03-08 04:14:02 +00:00
|
|
|
# ifndef Q_OS_ANDROID
|
2023-01-16 13:57:05 +00:00
|
|
|
QQuickStyle::setStyle("Material");
|
2023-03-08 04:14:02 +00:00
|
|
|
# endif
|
2023-02-15 11:54:35 +00:00
|
|
|
|
|
|
|
QTranslator translator;
|
|
|
|
Q_UNUSED(translator.load("zh_CN.qm"));
|
|
|
|
QCoreApplication::installTranslator(&translator);
|
2023-02-26 08:51:29 +00:00
|
|
|
|
2022-04-30 07:27:56 +00:00
|
|
|
QmlBackend backend;
|
|
|
|
backend.setEngine(engine);
|
2023-02-15 11:54:35 +00:00
|
|
|
|
2023-03-08 04:14:02 +00:00
|
|
|
# ifndef Q_OS_WASM
|
2023-02-15 11:54:35 +00:00
|
|
|
Pacman = new PackMan;
|
2023-03-08 04:14:02 +00:00
|
|
|
# endif
|
2023-02-26 08:51:29 +00:00
|
|
|
|
2023-03-20 06:53:56 +00:00
|
|
|
engine->rootContext()->setContextProperty("FkVersion", FK_VERSION);
|
2022-04-30 07:27:56 +00:00
|
|
|
engine->rootContext()->setContextProperty("Backend", &backend);
|
2023-02-15 11:54:35 +00:00
|
|
|
engine->rootContext()->setContextProperty("Pacman", Pacman);
|
2023-01-03 15:37:14 +00:00
|
|
|
|
2023-03-08 04:14:02 +00:00
|
|
|
# ifdef QT_DEBUG
|
2022-04-30 07:27:56 +00:00
|
|
|
bool debugging = true;
|
2023-03-08 04:14:02 +00:00
|
|
|
# else
|
2022-04-30 07:27:56 +00:00
|
|
|
bool debugging = false;
|
2023-03-08 04:14:02 +00:00
|
|
|
# endif
|
2022-04-30 07:27:56 +00:00
|
|
|
engine->rootContext()->setContextProperty("Debugging", debugging);
|
2023-01-03 15:37:14 +00:00
|
|
|
|
|
|
|
|
|
|
|
QString system;
|
2023-03-08 04:14:02 +00:00
|
|
|
# if defined(Q_OS_ANDROID)
|
2023-01-03 15:37:14 +00:00
|
|
|
system = "Android";
|
2023-03-08 04:14:02 +00:00
|
|
|
# elif defined(Q_OS_WASM)
|
2023-01-03 15:37:14 +00:00
|
|
|
system = "Web";
|
2023-02-26 07:01:14 +00:00
|
|
|
engine->rootContext()->setContextProperty("ServerAddr", "127.0.0.1:9527");
|
2023-03-08 04:14:02 +00:00
|
|
|
# elif defined(Q_OS_WIN32)
|
2023-01-03 15:37:14 +00:00
|
|
|
system = "Win";
|
2023-02-15 11:54:35 +00:00
|
|
|
::system("chcp 65001");
|
2023-03-08 04:14:02 +00:00
|
|
|
# elif defined(Q_OS_LINUX)
|
2023-01-03 15:37:14 +00:00
|
|
|
system = "Linux";
|
2023-03-08 04:14:02 +00:00
|
|
|
# else
|
2023-01-03 15:37:14 +00:00
|
|
|
system = "Other";
|
2023-03-08 04:14:02 +00:00
|
|
|
# endif
|
2023-01-03 15:37:14 +00:00
|
|
|
engine->rootContext()->setContextProperty("OS", system);
|
|
|
|
|
|
|
|
engine->rootContext()->setContextProperty("AppPath", QUrl::fromLocalFile(QDir::currentPath()));
|
2022-04-30 07:27:56 +00:00
|
|
|
engine->load("qml/main.qml");
|
2023-01-03 15:37:14 +00:00
|
|
|
|
2022-04-30 07:27:56 +00:00
|
|
|
if (engine->rootObjects().isEmpty())
|
|
|
|
return -1;
|
2022-01-24 02:23:08 +00:00
|
|
|
|
2022-12-18 04:52:52 +00:00
|
|
|
splash.close();
|
2022-04-30 07:27:56 +00:00
|
|
|
int ret = app->exec();
|
2022-03-27 12:00:29 +00:00
|
|
|
|
2022-04-30 07:27:56 +00:00
|
|
|
// delete the engine first
|
|
|
|
// to avoid "TypeError: Cannot read property 'xxx' of null"
|
|
|
|
delete engine;
|
2023-02-15 11:54:35 +00:00
|
|
|
delete Pacman;
|
2022-03-27 12:00:29 +00:00
|
|
|
|
2022-04-30 07:27:56 +00:00
|
|
|
return ret;
|
2023-03-08 04:14:02 +00:00
|
|
|
#endif
|
2022-01-24 02:23:08 +00:00
|
|
|
}
|