Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 44 additions & 1 deletion include/global/Configs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,54 @@
#include "Const.hpp"
#include "Utils.hpp"
#include "include/database/DatabaseManager.h"
#include <srslist.h>
#include <map>
#include <vector>

// Switch core support

namespace Configs {
inline QString GetRuleSetRemoteUrl(const QString& tag) {
if (tag.startsWith("geosite-")) {
return "https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/" + tag + ".srs";
}
if (tag.startsWith("geoip-")) {
return "https://raw.githubusercontent.com/SagerNet/sing-geoip/rule-set/" + tag + ".srs";
}
return {};
}

inline const std::vector<std::string> kDefaultRuleSetTags = {
"geosite-geolocation-!cn",
"geosite-geolocation-cn",
"geosite-cn",
"geosite-category-ads-all",
"geosite-openai",
"geosite-github",
"geosite-google",
"geosite-youtube",
"geosite-telegram",
"geosite-discord",
"geosite-reddit",
"geosite-netflix",
"geosite-disney",
"geosite-spotify",
"geosite-tiktok",
"geosite-private",
"geoip-private",
"geoip-cn",
"geoip-ir",
"geoip-ru",
"geoip-us"
};

inline const std::map<std::string, std::string> ruleSetMap = [] {
std::map<std::string, std::string> value;
for (const auto& tag : kDefaultRuleSetTags) {
value.emplace(tag, GetRuleSetRemoteUrl(QString::fromStdString(tag)).toStdString());
}
return value;
}();

void initDB(const std::string& dbPath);

QString FindCoreRealPath();
Expand Down
4 changes: 4 additions & 0 deletions src/api/RPC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,10 @@ namespace API {

bool Client::IsPrivileged(bool* rpcOK) const
{
if (rpcOK != nullptr) *rpcOK = false;
if (!channel) {
return false;
}
libcore::EmptyReq request;
libcore::IsPrivilegedResponse reply;
std::vector<uint8_t> resp;
Expand Down
8 changes: 5 additions & 3 deletions src/configs/generate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1146,15 +1146,17 @@ namespace Configs {
{"url", item},
};
}
else
if(ruleSetMap.contains(item.toStdString())) {
else {
const auto remoteUrl = GetRuleSetRemoteUrl(item);
if (!remoteUrl.isEmpty()) {
ruleSetArray += QJsonObject{
{"type", "remote"},
{"tag", item},
{"format", "binary"},
{"url", get_jsdelivr_link(QString::fromStdString(ruleSetMap.at(item.toStdString())))},
{"url", get_jsdelivr_link(remoteUrl)},
};
}
}
}

// add block
Expand Down
10 changes: 7 additions & 3 deletions src/global/Configs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,13 @@ namespace Configs {
admin = Windows_IsInAdmin();
Configs::dataManager->settingsRepo->windows_set_admin = admin;
#else
bool ok;
auto isPrivileged = API::defaultClient->IsPrivileged(&ok);
admin = ok && isPrivileged;
if (API::defaultClient != nullptr) {
bool ok = false;
auto isPrivileged = API::defaultClient->IsPrivileged(&ok);
admin = ok && isPrivileged;
} else {
admin = false;
}
#endif
isAdminCache = admin;
return admin;
Expand Down
88 changes: 67 additions & 21 deletions src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <csignal>
#include <exception>

#include <QApplication>
#include <QCryptographicHash>
Expand All @@ -9,6 +10,8 @@
#include <QLocalSocket>
#include <QLocalServer>
#include <QThread>
#include <QFileInfo>
#include <QRegularExpression>
#include <3rdparty/WinCommander.hpp>


Expand All @@ -35,6 +38,48 @@ void signal_handler(int signum) {
QTranslator* trans = nullptr;
QTranslator* trans_qt = nullptr;

namespace {
QDir getWorkingDirectory(const QStringList& arguments) {
auto wd = QDir(QApplication::applicationDirPath());

if (arguments.contains("-appdata")) {
QString appDataDir;
const int appdataIndex = arguments.indexOf("-appdata");
if (arguments.size() > appdataIndex + 1 && !arguments.at(appdataIndex + 1).startsWith("-")) {
appDataDir = arguments.at(appdataIndex + 1);
}
QApplication::setApplicationName("Throne");
if (!appDataDir.isEmpty()) {
wd.setPath(appDataDir);
} else {
wd.setPath(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation));
}
return wd;
}

#if defined(Q_OS_MACOS) || defined(NKR_CPP_USE_APPDATA)
QApplication::setApplicationName("Throne");
wd.setPath(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation));
#endif
return wd;
}

QString getInstanceServerName(const QDir& wd) {
QByteArray hashBytes = QCryptographicHash::hash(wd.absolutePath().toUtf8(), QCryptographicHash::Md5).toBase64(QByteArray::OmitTrailingEquals);
hashBytes.replace('+', '0').replace('/', '1');
auto serverName = QStringLiteral("throne-") + QString::fromUtf8(hashBytes);
#ifdef Q_OS_MACOS
QString runtimeBase = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
auto ipcDir = QDir(runtimeBase + "/throne-ipc");
if (!ipcDir.exists()) ipcDir.mkpath(".");
const auto safeName = QString(serverName).replace(QRegularExpression("[^A-Za-z0-9._-]"), "_");
return ipcDir.absoluteFilePath(safeName + ".sock");
#else
return serverName;
#endif
}
}

void loadTranslate(const QString& locale) {
QT_TRANSLATE_NOOP("QPlatformTheme", "Cancel");
QT_TRANSLATE_NOOP("QPlatformTheme", "Apply");
Expand Down Expand Up @@ -98,27 +143,22 @@ int main(int argc, char* argv[]) {
QStringList arguments = QApplication::arguments();

// dirs & clean
auto wd = QDir(QApplication::applicationDirPath());
if (arguments.contains("-appdata")) {
QString appDataDir;
int appdataIndex = arguments.indexOf("-appdata");
if (arguments.size() > appdataIndex + 1 && !arguments.at(appdataIndex + 1).startsWith("-")) {
appDataDir = arguments.at(appdataIndex + 1);
}
QApplication::setApplicationName("Throne");
if (!appDataDir.isEmpty()) {
wd.setPath(appDataDir);
} else {
wd.setPath(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation));
}
}
auto wd = getWorkingDirectory(arguments);
if (!wd.exists()) wd.mkpath(wd.absolutePath());
if (!wd.exists("config")) wd.mkdir("config");
QDir::setCurrent(wd.absoluteFilePath("config"));
QDir("temp").removeRecursively();

// Load database
Configs::initDB(QString(QDir::currentPath() + QDir::separator() + "throne.db").toStdString());
try {
Configs::initDB(QString(QDir::currentPath() + QDir::separator() + "throne.db").toStdString());
} catch (const std::exception& e) {
MessageBoxWarning(
"Database initialization failed",
QString("Failed to open the database in:\n%1\n\n%2").arg(QDir::currentPath(), e.what())
);
return 1;
}

// Store Flags
Configs::dataManager->settingsRepo->argv = arguments;
Expand All @@ -134,7 +174,7 @@ int main(int argc, char* argv[]) {
if (Configs::dataManager->settingsRepo->argv.contains("-debug")) Configs::dataManager->settingsRepo->flag_debug = true;
if (Configs::dataManager->settingsRepo->argv.contains("-flag_restart_tun_on")) Configs::dataManager->settingsRepo->flag_restart_tun_on = true;
if (Configs::dataManager->settingsRepo->argv.contains("-flag_restart_dns_set")) Configs::dataManager->settingsRepo->flag_dns_set = true;
#ifdef NKR_CPP_USE_APPDATA
#if defined(Q_OS_MACOS) || defined(NKR_CPP_USE_APPDATA)
Configs::dataManager->settingsRepo->flag_use_appdata = true; // Example: Package & MacOS
#endif
#ifdef NKR_CPP_DEBUG
Expand Down Expand Up @@ -197,9 +237,7 @@ int main(int argc, char* argv[]) {
loadTranslate(locale);

// Check if another instance is running
QByteArray hashBytes = QCryptographicHash::hash(wd.absolutePath().toUtf8(), QCryptographicHash::Md5).toBase64(QByteArray::OmitTrailingEquals);
hashBytes.replace('+', '0').replace('/', '1');
auto serverName = LOCAL_SERVER_PREFIX + QString::fromUtf8(hashBytes);
auto serverName = getInstanceServerName(wd);
qDebug() << "server name: " << serverName;
QLocalSocket socket;
socket.connectToServer(serverName);
Expand All @@ -212,10 +250,18 @@ int main(int argc, char* argv[]) {

// QLocalServer
QLocalServer server(qApp);
#ifndef Q_OS_MACOS
server.setSocketOptions(QLocalServer::WorldAccessOption);
#endif
QLocalServer::removeServer(serverName);
if (!server.listen(serverName)) {
qWarning() << "Failed to start QLocalServer! Error:" << server.errorString();
return 1;
qWarning() << "Failed to start QLocalServer, retrying after cleanup. Error:" << server.errorString();
server.close();
QLocalServer::removeServer(serverName);
if (!server.listen(serverName)) {
qWarning() << "Failed to start QLocalServer! Error:" << server.errorString();
return 1;
}
}
QObject::connect(&server, &QLocalServer::newConnection, qApp, [&] {
auto s = server.nextPendingConnection();
Expand Down
4 changes: 2 additions & 2 deletions src/ui/setting/RouteItem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ RouteItem::RouteItem(QWidget *parent, const std::shared_ptr<Configs::RouteProfil
}
}

for (const auto& item : ruleSetMap) {
for (const auto& item : Configs::ruleSetMap) {
geo_items.append(QString::fromStdString(item.first));
}

Expand Down Expand Up @@ -121,7 +121,7 @@ RouteItem::RouteItem(QWidget *parent, const std::shared_ptr<Configs::RouteProfil
ui->def_out->setCurrentText(Configs::outboundIDToString(chain->defaultOutboundID));

QStringList ruleItems = {"domain:", "suffix:", "regex:", "keyword:", "ip:", "processName:", "processPath:", "ruleset:"};
for (const auto& item : ruleSetMap) {
for (const auto& item : Configs::ruleSetMap) {
ruleItems.append("ruleset:" + QString::fromStdString(item.first));
}
simpleDirect = new AutoCompleteTextEdit("", ruleItems, this);
Expand Down
2 changes: 1 addition & 1 deletion src/ui/setting/dialog_manage_routes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ DialogManageRoutes::DialogManageRoutes(QWidget *parent) : QDialog(parent), ui(ne
});

QStringList ruleItems = {"domain:", "suffix:", "regex:"};
for (const auto& item : ruleSetMap) {
for (const auto& item : Configs::ruleSetMap) {
ruleItems.append("ruleset:" + QString::fromStdString(item.first));
}
rule_editor = new AutoCompleteTextEdit("", ruleItems, this);
Expand Down