diff --git a/3rdparty/QHotkey b/3rdparty/QHotkey deleted file mode 160000 index 52e25ac..0000000 --- a/3rdparty/QHotkey +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 52e25acf221e5ac86ce648f6922620fb2d6a7121 diff --git a/3rdparty/QThreadCreateThread.hpp b/3rdparty/QThreadCreateThread.hpp deleted file mode 100644 index ba6fe5f..0000000 --- a/3rdparty/QThreadCreateThread.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include -#include - -// FOR OLD QT - -class QThreadCreateThread : public QThread { -public: - explicit QThreadCreateThread(std::future &&future) - : m_future(std::move(future)) { - // deleteLater - connect(this, &QThread::finished, this, &QThread::deleteLater); - } - -private: - void run() override { - m_future.get(); - } - - std::future m_future; -}; - -inline QThread *createThreadImpl(std::future &&future) { - return new QThreadCreateThread(std::move(future)); -} - -template -QThread *createQThread(Function &&f, Args &&... args) { - using DecayedFunction = typename std::decay::type; - auto threadFunction = - [f = static_cast(std::forward(f))](auto &&... largs) mutable -> void { - (void) std::invoke(std::move(f), std::forward(largs)...); - }; - - return createThreadImpl(std::async(std::launch::deferred, - std::move(threadFunction), - std::forward(args)...)); -} diff --git a/3rdparty/QtExtKeySequenceEdit.cpp b/3rdparty/QtExtKeySequenceEdit.cpp deleted file mode 100644 index 02bb80c..0000000 --- a/3rdparty/QtExtKeySequenceEdit.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "QtExtKeySequenceEdit.h" - -QtExtKeySequenceEdit::QtExtKeySequenceEdit(QWidget *parent) - : QKeySequenceEdit(parent) { -} - -QtExtKeySequenceEdit::~QtExtKeySequenceEdit() { -} - -void QtExtKeySequenceEdit::keyPressEvent(QKeyEvent *pEvent) { - QKeySequenceEdit::keyPressEvent(pEvent); - - QKeySequence keySeq = keySequence(); - if (keySeq.count() <= 0) { - return; - } - int key = keySeq[0]; - if (key == Qt::Key_Backspace || key == Qt::Key_Delete) { - key = 0; - } - setKeySequence(key); -} diff --git a/3rdparty/QtExtKeySequenceEdit.h b/3rdparty/QtExtKeySequenceEdit.h deleted file mode 100644 index ebeb848..0000000 --- a/3rdparty/QtExtKeySequenceEdit.h +++ /dev/null @@ -1,11 +0,0 @@ -#include - -class QtExtKeySequenceEdit : public QKeySequenceEdit { -public: - QtExtKeySequenceEdit(QWidget *parent); - - ~QtExtKeySequenceEdit(); - -protected: - virtual void keyPressEvent(QKeyEvent *pEvent); -}; diff --git a/3rdparty/RunGuard.hpp b/3rdparty/RunGuard.hpp deleted file mode 100644 index 6a38d55..0000000 --- a/3rdparty/RunGuard.hpp +++ /dev/null @@ -1,98 +0,0 @@ -#ifndef RUNGUARD_H -#define RUNGUARD_H - -#include -#include -#include -#include - -class RunGuard { -public: - RunGuard(const QString &key); - - ~RunGuard(); - - bool isAnotherRunning(quint64 *data_out); - - bool tryToRun(quint64 *data_in); - - void release(); - -private: - const QString key; - const QString memLockKey; - const QString sharedmemKey; - - QSharedMemory sharedMem; - QSystemSemaphore memLock; - - Q_DISABLE_COPY(RunGuard) -}; - -namespace { - - QString generateKeyHash(const QString &key, const QString &salt) { - QByteArray data; - - data.append(key.toUtf8()); - data.append(salt.toUtf8()); - data = QCryptographicHash::hash(data, QCryptographicHash::Sha1).toHex(); - - return data; - } - -} // namespace - -RunGuard::RunGuard(const QString &key) - : key(key), memLockKey(generateKeyHash(key, "_memLockKey")), sharedmemKey(generateKeyHash(key, "_sharedmemKey")), sharedMem(sharedmemKey), memLock(memLockKey, 1) { - memLock.acquire(); - { - QSharedMemory fix(sharedmemKey); // Fix for *nix: http://habrahabr.ru/post/173281/ - fix.attach(); - } - memLock.release(); -} - -RunGuard::~RunGuard() { - release(); -} - -bool RunGuard::isAnotherRunning(quint64 *data_out) { - if (sharedMem.isAttached()) - return false; - - memLock.acquire(); - const bool isRunning = sharedMem.attach(); - if (isRunning) { - if (data_out != nullptr) { - memcpy(data_out, sharedMem.data(), sizeof(quint64)); - } - sharedMem.detach(); - } - memLock.release(); - - return isRunning; -} - -bool RunGuard::tryToRun(quint64 *data_in) { - memLock.acquire(); - const bool result = sharedMem.create(sizeof(quint64)); - if (result) memcpy(sharedMem.data(), data_in, sizeof(quint64)); - memLock.release(); - - if (!result) { - release(); - return false; - } - - return true; -} - -void RunGuard::release() { - memLock.acquire(); - if (sharedMem.isAttached()) - sharedMem.detach(); - memLock.release(); -} - -#endif // RUNGUARD_H diff --git a/3rdparty/VT100Parser.hpp b/3rdparty/VT100Parser.hpp deleted file mode 100644 index 9887a3f..0000000 --- a/3rdparty/VT100Parser.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include - -inline QString cleanVT100String(const QString &in) { - QString out; - bool in_033 = false; - for (auto &&chr: in) { - if (chr == '\033') { - in_033 = true; - continue; - } - if (in_033) { - if (chr == 'm') { - in_033 = false; - } - continue; - } - out += chr; - } - return out; -} diff --git a/3rdparty/WinCommander.cpp b/3rdparty/WinCommander.cpp deleted file mode 100644 index 1d65450..0000000 --- a/3rdparty/WinCommander.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 UpdateNode UG (haftungsbeschränkt) -** Contact: code@updatenode.com -** -** This file is part of the UpdateNode Client. -** -** Commercial License Usage -** Licensees holding valid commercial UpdateNode license may use this file -** under the terms of the the Apache License, Version 2.0 -** Full license description file: LICENSE.COM -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation. Please review the following information to ensure the -** GNU General Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** Full license description file: LICENSE.GPL -** -****************************************************************************/ - -#include "WinCommander.hpp" - -#include -#include - -#ifdef Q_OS_WIN -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#include -#include -#include -#define MAX_KEY_LENGTH 255 -#define MAX_VALUE_NAME 16383 -#endif - - -/*! -Executes a command elevated specified by \apath , using paramters \aparameters. -\n -Parameter /aaWait decides if the function should return immediatelly after it's\n -execution or wait for the exit of the launched process -\n -Returns the return value of the executed command -*/ -uint WinCommander::runProcessElevated(const QString &path, - const QStringList ¶meters, - const QString &workingDir, - int nShow, bool aWait) { - uint result = 0; - -#ifdef Q_OS_WIN - QString params; - HWND hwnd = NULL; - LPCTSTR pszPath = (LPCTSTR)path.utf16(); - foreach(QString item, parameters) - params += "\"" + item + "\" "; - - LPCTSTR pszParameters = (LPCTSTR)params.utf16(); - QString dir; - if (workingDir.count() == 0) - dir = QDir::toNativeSeparators(QDir::currentPath()); - else - dir = QDir::toNativeSeparators(workingDir); - LPCTSTR pszDirectory = (LPCTSTR)dir.utf16(); - - SHELLEXECUTEINFO shex; - DWORD dwCode = 0; - - ZeroMemory(&shex, sizeof(shex)); - - shex.cbSize = sizeof(shex); - shex.fMask = SEE_MASK_NOCLOSEPROCESS; - shex.hwnd = hwnd; - shex.lpVerb = TEXT("runas"); - shex.lpFile = pszPath; - shex.lpParameters = pszParameters; - shex.lpDirectory = pszDirectory; - // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow - shex.nShow = nShow; - - ShellExecuteEx(&shex); - if (shex.hProcess) - { - if(aWait) - { - WaitForSingleObject(shex.hProcess, INFINITE ); - GetExitCodeProcess(shex.hProcess, &dwCode); - } - CloseHandle (shex.hProcess) ; - } - else - return -1; - - result = (uint)dwCode; -#else - Q_UNUSED(path); - Q_UNUSED(parameters); - Q_UNUSED(workingDir); - Q_UNUSED(aWait); -#endif - return result; -} diff --git a/3rdparty/WinCommander.hpp b/3rdparty/WinCommander.hpp deleted file mode 100644 index 4aca562..0000000 --- a/3rdparty/WinCommander.hpp +++ /dev/null @@ -1,41 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 UpdateNode UG (haftungsbeschränkt) -** Contact: code@updatenode.com -** -** This file is part of the UpdateNode Client. -** -** Commercial License Usage -** Licensees holding valid commercial UpdateNode license may use this file -** under the terms of the the Apache License, Version 2.0 -** Full license description file: LICENSE.COM -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation. Please review the following information to ensure the -** GNU General Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** Full license description file: LICENSE.GPL -** -****************************************************************************/ - -#ifndef WINCOMMANDER_H -#define WINCOMMANDER_H - -#include -#include - -class WinCommander { -public: - static const int SW_HIDE = 0; - static const int SW_NORMAL = 1; - static const int SW_SHOWMINIMIZED = 2; - - static uint runProcessElevated(const QString &path, - const QStringList ¶meters = QStringList(), - const QString &workingDir = QString(), - int nShow = SW_SHOWMINIMIZED, bool aWait = true); -}; - -#endif // WINCOMMANDER_H \ No newline at end of file diff --git a/3rdparty/ZxingQtReader.hpp b/3rdparty/ZxingQtReader.hpp deleted file mode 100644 index cbd41b7..0000000 --- a/3rdparty/ZxingQtReader.hpp +++ /dev/null @@ -1,454 +0,0 @@ -/* - * Copyright 2020 Axel Waggershauser - */ -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include "ZXing/ReadBarcode.h" - -#include -#include -#include -#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) -#include "qscopeguard.h" -#else -#include -#endif - -#ifdef QT_MULTIMEDIA_LIB -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) -#include -#else -#include -#include -#endif -#include -#endif - -// This is some sample code to start a discussion about how a minimal and header-only Qt wrapper/helper could look like. - -namespace ZXingQt { - -Q_NAMESPACE - -//TODO: find a better way to export these enums to QML than to duplicate their definition -// #ifdef Q_MOC_RUN produces meta information in the moc output but it does end up working in qml -#ifdef QT_QML_LIB -enum class BarcodeFormat -{ - None = 0, ///< Used as a return value if no valid barcode has been detected - Aztec = (1 << 0), ///< Aztec - Codabar = (1 << 1), ///< Codabar - Code39 = (1 << 2), ///< Code39 - Code93 = (1 << 3), ///< Code93 - Code128 = (1 << 4), ///< Code128 - DataBar = (1 << 5), ///< GS1 DataBar, formerly known as RSS 14 - DataBarExpanded = (1 << 6), ///< GS1 DataBar Expanded, formerly known as RSS EXPANDED - DataMatrix = (1 << 7), ///< DataMatrix - EAN8 = (1 << 8), ///< EAN-8 - EAN13 = (1 << 9), ///< EAN-13 - ITF = (1 << 10), ///< ITF (Interleaved Two of Five) - MaxiCode = (1 << 11), ///< MaxiCode - PDF417 = (1 << 12), ///< PDF417 or - QRCode = (1 << 13), ///< QR Code - UPCA = (1 << 14), ///< UPC-A - UPCE = (1 << 15), ///< UPC-E - MicroQRCode = (1 << 16), ///< Micro QR Code - - LinearCodes = Codabar | Code39 | Code93 | Code128 | EAN8 | EAN13 | ITF | DataBar | DataBarExpanded | UPCA | UPCE, - MatrixCodes = Aztec | DataMatrix | MaxiCode | PDF417 | QRCode | MicroQRCode, -}; - -enum class ContentType { Text, Binary, Mixed, GS1, ISO15434, UnknownECI }; - -#else -using ZXing::BarcodeFormat; -using ZXing::ContentType; -#endif - -using ZXing::DecodeHints; -using ZXing::Binarizer; -using ZXing::BarcodeFormats; - -Q_ENUM_NS(BarcodeFormat) -Q_ENUM_NS(ContentType) - -template -QDebug operator<<(QDebug dbg, const T& v) -{ - return dbg.noquote() << QString::fromStdString(ToString(v)); -} - -class Position : public ZXing::Quadrilateral -{ - Q_GADGET - - Q_PROPERTY(QPoint topLeft READ topLeft) - Q_PROPERTY(QPoint topRight READ topRight) - Q_PROPERTY(QPoint bottomRight READ bottomRight) - Q_PROPERTY(QPoint bottomLeft READ bottomLeft) - - using Base = ZXing::Quadrilateral; - -public: - using Base::Base; -}; - -class Result : private ZXing::Result -{ - Q_GADGET - - Q_PROPERTY(BarcodeFormat format READ format) - Q_PROPERTY(QString formatName READ formatName) - Q_PROPERTY(QString text READ text) - Q_PROPERTY(QByteArray bytes READ bytes) - Q_PROPERTY(bool isValid READ isValid) - Q_PROPERTY(ContentType contentType READ contentType) - Q_PROPERTY(Position position READ position) - - QString _text; - QByteArray _bytes; - Position _position; - -public: - Result() = default; // required for qmetatype machinery - - explicit Result(ZXing::Result&& r) : ZXing::Result(std::move(r)) { - _text = QString::fromStdString(ZXing::Result::text()); - _bytes = QByteArray(reinterpret_cast(ZXing::Result::bytes().data()), Size(ZXing::Result::bytes())); - auto& pos = ZXing::Result::position(); - auto qp = [&pos](int i) { return QPoint(pos[i].x, pos[i].y); }; - _position = {qp(0), qp(1), qp(2), qp(3)}; - } - - using ZXing::Result::isValid; - - BarcodeFormat format() const { return static_cast(ZXing::Result::format()); } - ContentType contentType() const { return static_cast(ZXing::Result::contentType()); } - QString formatName() const { return QString::fromStdString(ZXing::ToString(ZXing::Result::format())); } - const QString& text() const { return _text; } - const QByteArray& bytes() const { return _bytes; } - const Position& position() const { return _position; } - - // For debugging/development - int runTime = 0; - Q_PROPERTY(int runTime MEMBER runTime) -}; - -inline QList QListResults(ZXing::Results&& zxres) -{ - QList res; - for (auto&& r : zxres) - res.push_back(Result(std::move(r))); - return res; -} - -inline QList ReadBarcodes(const QImage& img, const DecodeHints& hints = {}) -{ - using namespace ZXing; - - auto ImgFmtFromQImg = [](const QImage& img) { - switch (img.format()) { - case QImage::Format_ARGB32: - case QImage::Format_RGB32: -#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN - return ImageFormat::BGRX; -#else - return ImageFormat::XRGB; -#endif - case QImage::Format_RGB888: return ImageFormat::RGB; - case QImage::Format_RGBX8888: - case QImage::Format_RGBA8888: return ImageFormat::RGBX; - case QImage::Format_Grayscale8: return ImageFormat::Lum; - default: return ImageFormat::None; - } - }; - - auto exec = [&](const QImage& img) { - return QListResults(ZXing::ReadBarcodes( - {img.bits(), img.width(), img.height(), ImgFmtFromQImg(img), static_cast(img.bytesPerLine())}, hints)); - }; - - return ImgFmtFromQImg(img) == ImageFormat::None ? exec(img.convertToFormat(QImage::Format_Grayscale8)) : exec(img); -} - -inline Result ReadBarcode(const QImage& img, const DecodeHints& hints = {}) -{ - auto res = ReadBarcodes(img, DecodeHints(hints).setMaxNumberOfSymbols(1)); - return !res.isEmpty() ? res.takeFirst() : Result(); -} - -#ifdef QT_MULTIMEDIA_LIB -inline QList ReadBarcodes(const QVideoFrame& frame, const DecodeHints& hints = {}) -{ - using namespace ZXing; - - ImageFormat fmt = ImageFormat::None; - int pixStride = 0; - int pixOffset = 0; - -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) -#define FORMAT(F5, F6) QVideoFrame::Format_##F5 -#define FIRST_PLANE -#else -#define FORMAT(F5, F6) QVideoFrameFormat::Format_##F6 -#define FIRST_PLANE 0 -#endif - - switch (frame.pixelFormat()) { - case FORMAT(ARGB32, ARGB8888): - case FORMAT(ARGB32_Premultiplied, ARGB8888_Premultiplied): - case FORMAT(RGB32, RGBX8888): -#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN - fmt = ImageFormat::BGRX; -#else - fmt = ImageFormat::XRGB; -#endif - break; - - case FORMAT(BGRA32, BGRA8888): - case FORMAT(BGRA32_Premultiplied, BGRA8888_Premultiplied): - case FORMAT(BGR32, BGRX8888): -#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN - fmt = ImageFormat::RGBX; -#else - fmt = ImageFormat::XBGR; -#endif - break; - -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) - case QVideoFrame::Format_RGB24: fmt = ImageFormat::RGB; break; - case QVideoFrame::Format_BGR24: fmt = ImageFormat::BGR; break; - case QVideoFrame::Format_YUV444: fmt = ImageFormat::Lum, pixStride = 3; break; -#else - case QVideoFrameFormat::Format_P010: - case QVideoFrameFormat::Format_P016: fmt = ImageFormat::Lum, pixStride = 1; break; -#endif - - case FORMAT(AYUV444, AYUV): - case FORMAT(AYUV444_Premultiplied, AYUV_Premultiplied): -#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN - fmt = ImageFormat::Lum, pixStride = 4, pixOffset = 3; -#else - fmt = ImageFormat::Lum, pixStride = 4, pixOffset = 2; -#endif - break; - - case FORMAT(YUV420P, YUV420P): - case FORMAT(NV12, NV12): - case FORMAT(NV21, NV21): - case FORMAT(IMC1, IMC1): - case FORMAT(IMC2, IMC2): - case FORMAT(IMC3, IMC3): - case FORMAT(IMC4, IMC4): - case FORMAT(YV12, YV12): fmt = ImageFormat::Lum; break; - case FORMAT(UYVY, UYVY): fmt = ImageFormat::Lum, pixStride = 2, pixOffset = 1; break; - case FORMAT(YUYV, YUYV): fmt = ImageFormat::Lum, pixStride = 2; break; - - case FORMAT(Y8, Y8): fmt = ImageFormat::Lum; break; - case FORMAT(Y16, Y16): fmt = ImageFormat::Lum, pixStride = 2, pixOffset = 1; break; - -#if (QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)) - case FORMAT(ABGR32, ABGR8888): -#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN - fmt = ImageFormat::RGBX; -#else - fmt = ImageFormat::XBGR; -#endif - break; -#endif -#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) - case FORMAT(YUV422P, YUV422P): fmt = ImageFormat::Lum; break; -#endif - default: break; - } - - if (fmt != ImageFormat::None) { - auto img = frame; // shallow copy just get access to non-const map() function -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) - if (!img.isValid() || !img.map(QAbstractVideoBuffer::ReadOnly)){ -#else - if (!img.isValid() || !img.map(QVideoFrame::ReadOnly)){ -#endif - qWarning() << "invalid QVideoFrame: could not map memory"; - return {}; - } - QScopeGuard unmap([&] { img.unmap(); }); - - return QListResults(ZXing::ReadBarcodes( - {img.bits(FIRST_PLANE) + pixOffset, img.width(), img.height(), fmt, img.bytesPerLine(FIRST_PLANE), pixStride}, hints)); - } - else { -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) - if (QVideoFrame::imageFormatFromPixelFormat(frame.pixelFormat()) != QImage::Format_Invalid) { - qWarning() << "unsupported QVideoFrame::pixelFormat"; - return {}; - } - auto qimg = frame.image(); -#else - auto qimg = frame.toImage(); -#endif - if (qimg.format() != QImage::Format_Invalid) - return ReadBarcodes(qimg, hints); - qWarning() << "failed to convert QVideoFrame to QImage"; - return {}; - } -} - -inline Result ReadBarcode(const QVideoFrame& frame, const DecodeHints& hints = {}) -{ - auto res = ReadBarcodes(frame, DecodeHints(hints).setMaxNumberOfSymbols(1)); - return !res.isEmpty() ? res.takeFirst() : Result(); -} - -#define ZQ_PROPERTY(Type, name, setter) \ -public: \ - Q_PROPERTY(Type name READ name WRITE setter NOTIFY name##Changed) \ - Type name() const noexcept { return DecodeHints::name(); } \ - Q_SLOT void setter(const Type& newVal) \ - { \ - if (name() != newVal) { \ - DecodeHints::setter(newVal); \ - emit name##Changed(); \ - } \ - } \ - Q_SIGNAL void name##Changed(); - - -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) -class BarcodeReader : public QAbstractVideoFilter, private DecodeHints -#else -class BarcodeReader : public QObject, private DecodeHints -#endif -{ - Q_OBJECT - -public: -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) - BarcodeReader(QObject* parent = nullptr) : QAbstractVideoFilter(parent) {} -#else - BarcodeReader(QObject* parent = nullptr) : QObject(parent) {} -#endif - - // TODO: find out how to properly expose QFlags to QML - // simply using ZQ_PROPERTY(BarcodeFormats, formats, setFormats) - // results in the runtime error "can't assign int to formats" - Q_PROPERTY(int formats READ formats WRITE setFormats NOTIFY formatsChanged) - int formats() const noexcept - { - auto fmts = DecodeHints::formats(); - return *reinterpret_cast(&fmts); - } - Q_SLOT void setFormats(int newVal) - { - if (formats() != newVal) { - DecodeHints::setFormats(static_cast(newVal)); - emit formatsChanged(); - qDebug() << DecodeHints::formats(); - } - } - Q_SIGNAL void formatsChanged(); - - ZQ_PROPERTY(bool, tryRotate, setTryRotate) - ZQ_PROPERTY(bool, tryHarder, setTryHarder) - ZQ_PROPERTY(bool, tryDownscale, setTryDownscale) - -public slots: - ZXingQt::Result process(const QVideoFrame& image) - { - QElapsedTimer t; - t.start(); - - auto res = ReadBarcode(image, *this); - - res.runTime = t.elapsed(); - - emit newResult(res); - if (res.isValid()) - emit foundBarcode(res); - return res; - } - -signals: - void newResult(ZXingQt::Result result); - void foundBarcode(ZXingQt::Result result); - -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) -public: - QVideoFilterRunnable *createFilterRunnable() override; -#else -private: - QVideoSink *_sink = nullptr; - -public: - void setVideoSink(QVideoSink* sink) { - if (_sink == sink) - return; - - if (_sink) - disconnect(_sink, nullptr, this, nullptr); - - _sink = sink; - connect(_sink, &QVideoSink::videoFrameChanged, this, &BarcodeReader::process); - } - Q_PROPERTY(QVideoSink* videoSink WRITE setVideoSink) -#endif - -}; - -#undef ZX_PROPERTY - -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) -class VideoFilterRunnable : public QVideoFilterRunnable -{ - BarcodeReader* _filter = nullptr; - -public: - explicit VideoFilterRunnable(BarcodeReader* filter) : _filter(filter) {} - - QVideoFrame run(QVideoFrame* input, const QVideoSurfaceFormat& /*surfaceFormat*/, RunFlags /*flags*/) override - { - _filter->process(*input); - return *input; - } -}; - -inline QVideoFilterRunnable* BarcodeReader::createFilterRunnable() -{ - return new VideoFilterRunnable(this); -} -#endif - -#endif // QT_MULTIMEDIA_LIB - -} // namespace ZXingQt - - -Q_DECLARE_METATYPE(ZXingQt::Position) -Q_DECLARE_METATYPE(ZXingQt::Result) - -#ifdef QT_QML_LIB - -#include - -namespace ZXingQt { - -inline void registerQmlAndMetaTypes() -{ - qRegisterMetaType("BarcodeFormat"); - qRegisterMetaType("ContentType"); - - // supposedly the Q_DECLARE_METATYPE should be used with the overload without a custom name - // but then the qml side complains about "unregistered type" - qRegisterMetaType("Position"); - qRegisterMetaType("Result"); - - qmlRegisterUncreatableMetaObject( - ZXingQt::staticMetaObject, "ZXing", 1, 0, "ZXing", "Access to enums & flags only"); - qmlRegisterType("ZXing", 1, 0, "BarcodeReader"); -} - -} // namespace ZXingQt - -#endif // QT_QML_LIB \ No newline at end of file diff --git a/3rdparty/base64.cpp b/3rdparty/base64.cpp deleted file mode 100644 index 88aae27..0000000 --- a/3rdparty/base64.cpp +++ /dev/null @@ -1,92 +0,0 @@ -#include "base64.h" - -#ifndef qsizetype -#define qsizetype size_t -#endif - -namespace Qt515Base64 { - namespace { - struct fromBase64_helper_result { - qsizetype decodedLength; - Base64DecodingStatus status; - }; - - fromBase64_helper_result fromBase64_helper(const char *input, qsizetype inputSize, - char *output /* may alias input */, - Base64Options options) { - fromBase64_helper_result result{0, Base64DecodingStatus::Ok}; - - unsigned int buf = 0; - int nbits = 0; - - qsizetype offset = 0; - for (qsizetype i = 0; i < inputSize; ++i) { - int ch = input[i]; - int d; - - if (ch >= 'A' && ch <= 'Z') { - d = ch - 'A'; - } else if (ch >= 'a' && ch <= 'z') { - d = ch - 'a' + 26; - } else if (ch >= '0' && ch <= '9') { - d = ch - '0' + 52; - } else if (ch == '+' && (options & Base64UrlEncoding) == 0) { - d = 62; - } else if (ch == '-' && (options & Base64UrlEncoding) != 0) { - d = 62; - } else if (ch == '/' && (options & Base64UrlEncoding) == 0) { - d = 63; - } else if (ch == '_' && (options & Base64UrlEncoding) != 0) { - d = 63; - } else { - if (options & AbortOnBase64DecodingErrors) { - if (ch == '=') { - // can have 1 or 2 '=' signs, in both cases padding base64Size to - // a multiple of 4. Any other case is illegal. - if ((inputSize % 4) != 0) { - result.status = Base64DecodingStatus::IllegalInputLength; - return result; - } else if ((i == inputSize - 1) || - (i == inputSize - 2 && input[++i] == '=')) { - d = -1; // ... and exit the loop, normally - } else { - result.status = Base64DecodingStatus::IllegalPadding; - return result; - } - } else { - result.status = Base64DecodingStatus::IllegalCharacter; - return result; - } - } else { - d = -1; - } - } - - if (d != -1) { - buf = (buf << 6) | d; - nbits += 6; - if (nbits >= 8) { - nbits -= 8; - Q_ASSERT(offset < i); - output[offset++] = buf >> nbits; - buf &= (1 << nbits) - 1; - } - } - } - - result.decodedLength = offset; - return result; - } - } // namespace - - FromBase64Result QByteArray_fromBase64Encoding(const QByteArray &base64, Base64Options options) { - const auto base64Size = base64.size(); - QByteArray result((base64Size * 3) / 4, Qt::Uninitialized); - const auto base64result = fromBase64_helper(base64.data(), - base64Size, - const_cast(result.constData()), - options); - result.truncate(int(base64result.decodedLength)); - return {std::move(result), base64result.status}; - } -} // namespace Qt515Base64 diff --git a/3rdparty/base64.h b/3rdparty/base64.h deleted file mode 100644 index 1211304..0000000 --- a/3rdparty/base64.h +++ /dev/null @@ -1,47 +0,0 @@ -#include - -namespace Qt515Base64 { - enum Base64Option { - Base64Encoding = 0, - Base64UrlEncoding = 1, - - KeepTrailingEquals = 0, - OmitTrailingEquals = 2, - - IgnoreBase64DecodingErrors = 0, - AbortOnBase64DecodingErrors = 4, - }; - Q_DECLARE_FLAGS(Base64Options, Base64Option) - Q_DECLARE_OPERATORS_FOR_FLAGS(Base64Options) - - enum class Base64DecodingStatus { - Ok, - IllegalInputLength, - IllegalCharacter, - IllegalPadding, - }; - - class FromBase64Result { - public: - QByteArray decoded; - Base64DecodingStatus decodingStatus; - - void swap(FromBase64Result &other) noexcept { - qSwap(decoded, other.decoded); - qSwap(decodingStatus, other.decodingStatus); - } - - explicit operator bool() const noexcept { return decodingStatus == Base64DecodingStatus::Ok; } - -#if defined(Q_COMPILER_REF_QUALIFIERS) && !defined(Q_QDOC) - QByteArray &operator*() &noexcept { return decoded; } - const QByteArray &operator*() const &noexcept { return decoded; } - QByteArray &&operator*() &&noexcept { return std::move(decoded); } -#else - QByteArray &operator*() noexcept { return decoded; } - const QByteArray &operator*() const noexcept { return decoded; } -#endif - }; - - FromBase64Result QByteArray_fromBase64Encoding(const QByteArray &base64, Base64Options options); -} // namespace Qt515Base64 diff --git a/3rdparty/fix_old_qt.h b/3rdparty/fix_old_qt.h deleted file mode 100644 index 2620809..0000000 --- a/3rdparty/fix_old_qt.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include - -#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0) - -inline QString qEnvironmentVariable(const char *varName) { - return qgetenv(varName); -} - -#endif diff --git a/3rdparty/qrcodegen.cpp b/3rdparty/qrcodegen.cpp deleted file mode 100644 index 0957b79..0000000 --- a/3rdparty/qrcodegen.cpp +++ /dev/null @@ -1,830 +0,0 @@ -/* - * QR Code generator library (C++) - * - * Copyright (c) Project Nayuki. (MIT License) - * https://www.nayuki.io/page/qr-code-generator-library - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - The Software is provided "as is", without warranty of any kind, express or - * implied, including but not limited to the warranties of merchantability, - * fitness for a particular purpose and noninfringement. In no event shall the - * authors or copyright holders be liable for any claim, damages or other - * liability, whether in an action of contract, tort or otherwise, arising from, - * out of or in connection with the Software or the use or other dealings in the - * Software. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "qrcodegen.hpp" - -using std::int8_t; -using std::uint8_t; -using std::size_t; -using std::vector; - - -namespace qrcodegen { - -/*---- Class QrSegment ----*/ - -QrSegment::Mode::Mode(int mode, int cc0, int cc1, int cc2) : - modeBits(mode) { - numBitsCharCount[0] = cc0; - numBitsCharCount[1] = cc1; - numBitsCharCount[2] = cc2; -} - - -int QrSegment::Mode::getModeBits() const { - return modeBits; -} - - -int QrSegment::Mode::numCharCountBits(int ver) const { - return numBitsCharCount[(ver + 7) / 17]; -} - - -const QrSegment::Mode QrSegment::Mode::NUMERIC (0x1, 10, 12, 14); -const QrSegment::Mode QrSegment::Mode::ALPHANUMERIC(0x2, 9, 11, 13); -const QrSegment::Mode QrSegment::Mode::BYTE (0x4, 8, 16, 16); -const QrSegment::Mode QrSegment::Mode::KANJI (0x8, 8, 10, 12); -const QrSegment::Mode QrSegment::Mode::ECI (0x7, 0, 0, 0); - - -QrSegment QrSegment::makeBytes(const vector &data) { - if (data.size() > static_cast(INT_MAX)) - throw std::length_error("Data too long"); - BitBuffer bb; - for (uint8_t b : data) - bb.appendBits(b, 8); - return QrSegment(Mode::BYTE, static_cast(data.size()), std::move(bb)); -} - - -QrSegment QrSegment::makeNumeric(const char *digits) { - BitBuffer bb; - int accumData = 0; - int accumCount = 0; - int charCount = 0; - for (; *digits != '\0'; digits++, charCount++) { - char c = *digits; - if (c < '0' || c > '9') - throw std::domain_error("String contains non-numeric characters"); - accumData = accumData * 10 + (c - '0'); - accumCount++; - if (accumCount == 3) { - bb.appendBits(static_cast(accumData), 10); - accumData = 0; - accumCount = 0; - } - } - if (accumCount > 0) // 1 or 2 digits remaining - bb.appendBits(static_cast(accumData), accumCount * 3 + 1); - return QrSegment(Mode::NUMERIC, charCount, std::move(bb)); -} - - -QrSegment QrSegment::makeAlphanumeric(const char *text) { - BitBuffer bb; - int accumData = 0; - int accumCount = 0; - int charCount = 0; - for (; *text != '\0'; text++, charCount++) { - const char *temp = std::strchr(ALPHANUMERIC_CHARSET, *text); - if (temp == nullptr) - throw std::domain_error("String contains unencodable characters in alphanumeric mode"); - accumData = accumData * 45 + static_cast(temp - ALPHANUMERIC_CHARSET); - accumCount++; - if (accumCount == 2) { - bb.appendBits(static_cast(accumData), 11); - accumData = 0; - accumCount = 0; - } - } - if (accumCount > 0) // 1 character remaining - bb.appendBits(static_cast(accumData), 6); - return QrSegment(Mode::ALPHANUMERIC, charCount, std::move(bb)); -} - - -vector QrSegment::makeSegments(const char *text) { - // Select the most efficient segment encoding automatically - vector result; - if (*text == '\0'); // Leave result empty - else if (isNumeric(text)) - result.push_back(makeNumeric(text)); - else if (isAlphanumeric(text)) - result.push_back(makeAlphanumeric(text)); - else { - vector bytes; - for (; *text != '\0'; text++) - bytes.push_back(static_cast(*text)); - result.push_back(makeBytes(bytes)); - } - return result; -} - - -QrSegment QrSegment::makeEci(long assignVal) { - BitBuffer bb; - if (assignVal < 0) - throw std::domain_error("ECI assignment value out of range"); - else if (assignVal < (1 << 7)) - bb.appendBits(static_cast(assignVal), 8); - else if (assignVal < (1 << 14)) { - bb.appendBits(2, 2); - bb.appendBits(static_cast(assignVal), 14); - } else if (assignVal < 1000000L) { - bb.appendBits(6, 3); - bb.appendBits(static_cast(assignVal), 21); - } else - throw std::domain_error("ECI assignment value out of range"); - return QrSegment(Mode::ECI, 0, std::move(bb)); -} - - -QrSegment::QrSegment(const Mode &md, int numCh, const std::vector &dt) : - mode(&md), - numChars(numCh), - data(dt) { - if (numCh < 0) - throw std::domain_error("Invalid value"); -} - - -QrSegment::QrSegment(const Mode &md, int numCh, std::vector &&dt) : - mode(&md), - numChars(numCh), - data(std::move(dt)) { - if (numCh < 0) - throw std::domain_error("Invalid value"); -} - - -int QrSegment::getTotalBits(const vector &segs, int version) { - int result = 0; - for (const QrSegment &seg : segs) { - int ccbits = seg.mode->numCharCountBits(version); - if (seg.numChars >= (1L << ccbits)) - return -1; // The segment's length doesn't fit the field's bit width - if (4 + ccbits > INT_MAX - result) - return -1; // The sum will overflow an int type - result += 4 + ccbits; - if (seg.data.size() > static_cast(INT_MAX - result)) - return -1; // The sum will overflow an int type - result += static_cast(seg.data.size()); - } - return result; -} - - -bool QrSegment::isNumeric(const char *text) { - for (; *text != '\0'; text++) { - char c = *text; - if (c < '0' || c > '9') - return false; - } - return true; -} - - -bool QrSegment::isAlphanumeric(const char *text) { - for (; *text != '\0'; text++) { - if (std::strchr(ALPHANUMERIC_CHARSET, *text) == nullptr) - return false; - } - return true; -} - - -const QrSegment::Mode &QrSegment::getMode() const { - return *mode; -} - - -int QrSegment::getNumChars() const { - return numChars; -} - - -const std::vector &QrSegment::getData() const { - return data; -} - - -const char *QrSegment::ALPHANUMERIC_CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:"; - - - -/*---- Class QrCode ----*/ - -int QrCode::getFormatBits(Ecc ecl) { - switch (ecl) { - case Ecc::LOW : return 1; - case Ecc::MEDIUM : return 0; - case Ecc::QUARTILE: return 3; - case Ecc::HIGH : return 2; - default: throw std::logic_error("Unreachable"); - } -} - - -QrCode QrCode::encodeText(const char *text, Ecc ecl) { - vector segs = QrSegment::makeSegments(text); - return encodeSegments(segs, ecl); -} - - -QrCode QrCode::encodeBinary(const vector &data, Ecc ecl) { - vector segs{QrSegment::makeBytes(data)}; - return encodeSegments(segs, ecl); -} - - -QrCode QrCode::encodeSegments(const vector &segs, Ecc ecl, - int minVersion, int maxVersion, int mask, bool boostEcl) { - if (!(MIN_VERSION <= minVersion && minVersion <= maxVersion && maxVersion <= MAX_VERSION) || mask < -1 || mask > 7) - throw std::invalid_argument("Invalid value"); - - // Find the minimal version number to use - int version, dataUsedBits; - for (version = minVersion; ; version++) { - int dataCapacityBits = getNumDataCodewords(version, ecl) * 8; // Number of data bits available - dataUsedBits = QrSegment::getTotalBits(segs, version); - if (dataUsedBits != -1 && dataUsedBits <= dataCapacityBits) - break; // This version number is found to be suitable - if (version >= maxVersion) { // All versions in the range could not fit the given data - std::ostringstream sb; - if (dataUsedBits == -1) - sb << "Segment too long"; - else { - sb << "Data length = " << dataUsedBits << " bits, "; - sb << "Max capacity = " << dataCapacityBits << " bits"; - } - throw data_too_long(sb.str()); - } - } - assert(dataUsedBits != -1); - - // Increase the error correction level while the data still fits in the current version number - for (Ecc newEcl : {Ecc::MEDIUM, Ecc::QUARTILE, Ecc::HIGH}) { // From low to high - if (boostEcl && dataUsedBits <= getNumDataCodewords(version, newEcl) * 8) - ecl = newEcl; - } - - // Concatenate all segments to create the data bit string - BitBuffer bb; - for (const QrSegment &seg : segs) { - bb.appendBits(static_cast(seg.getMode().getModeBits()), 4); - bb.appendBits(static_cast(seg.getNumChars()), seg.getMode().numCharCountBits(version)); - bb.insert(bb.end(), seg.getData().begin(), seg.getData().end()); - } - assert(bb.size() == static_cast(dataUsedBits)); - - // Add terminator and pad up to a byte if applicable - size_t dataCapacityBits = static_cast(getNumDataCodewords(version, ecl)) * 8; - assert(bb.size() <= dataCapacityBits); - bb.appendBits(0, std::min(4, static_cast(dataCapacityBits - bb.size()))); - bb.appendBits(0, (8 - static_cast(bb.size() % 8)) % 8); - assert(bb.size() % 8 == 0); - - // Pad with alternating bytes until data capacity is reached - for (uint8_t padByte = 0xEC; bb.size() < dataCapacityBits; padByte ^= 0xEC ^ 0x11) - bb.appendBits(padByte, 8); - - // Pack bits into bytes in big endian - vector dataCodewords(bb.size() / 8); - for (size_t i = 0; i < bb.size(); i++) - dataCodewords.at(i >> 3) |= (bb.at(i) ? 1 : 0) << (7 - (i & 7)); - - // Create the QR Code object - return QrCode(version, ecl, dataCodewords, mask); -} - - -QrCode::QrCode(int ver, Ecc ecl, const vector &dataCodewords, int msk) : - // Initialize fields and check arguments - version(ver), - errorCorrectionLevel(ecl) { - if (ver < MIN_VERSION || ver > MAX_VERSION) - throw std::domain_error("Version value out of range"); - if (msk < -1 || msk > 7) - throw std::domain_error("Mask value out of range"); - size = ver * 4 + 17; - size_t sz = static_cast(size); - modules = vector >(sz, vector(sz)); // Initially all light - isFunction = vector >(sz, vector(sz)); - - // Compute ECC, draw modules - drawFunctionPatterns(); - const vector allCodewords = addEccAndInterleave(dataCodewords); - drawCodewords(allCodewords); - - // Do masking - if (msk == -1) { // Automatically choose best mask - long minPenalty = LONG_MAX; - for (int i = 0; i < 8; i++) { - applyMask(i); - drawFormatBits(i); - long penalty = getPenaltyScore(); - if (penalty < minPenalty) { - msk = i; - minPenalty = penalty; - } - applyMask(i); // Undoes the mask due to XOR - } - } - assert(0 <= msk && msk <= 7); - mask = msk; - applyMask(msk); // Apply the final choice of mask - drawFormatBits(msk); // Overwrite old format bits - - isFunction.clear(); - isFunction.shrink_to_fit(); -} - - -int QrCode::getVersion() const { - return version; -} - - -int QrCode::getSize() const { - return size; -} - - -QrCode::Ecc QrCode::getErrorCorrectionLevel() const { - return errorCorrectionLevel; -} - - -int QrCode::getMask() const { - return mask; -} - - -bool QrCode::getModule(int x, int y) const { - return 0 <= x && x < size && 0 <= y && y < size && module(x, y); -} - - -void QrCode::drawFunctionPatterns() { - // Draw horizontal and vertical timing patterns - for (int i = 0; i < size; i++) { - setFunctionModule(6, i, i % 2 == 0); - setFunctionModule(i, 6, i % 2 == 0); - } - - // Draw 3 finder patterns (all corners except bottom right; overwrites some timing modules) - drawFinderPattern(3, 3); - drawFinderPattern(size - 4, 3); - drawFinderPattern(3, size - 4); - - // Draw numerous alignment patterns - const vector alignPatPos = getAlignmentPatternPositions(); - size_t numAlign = alignPatPos.size(); - for (size_t i = 0; i < numAlign; i++) { - for (size_t j = 0; j < numAlign; j++) { - // Don't draw on the three finder corners - if (!((i == 0 && j == 0) || (i == 0 && j == numAlign - 1) || (i == numAlign - 1 && j == 0))) - drawAlignmentPattern(alignPatPos.at(i), alignPatPos.at(j)); - } - } - - // Draw configuration data - drawFormatBits(0); // Dummy mask value; overwritten later in the constructor - drawVersion(); -} - - -void QrCode::drawFormatBits(int msk) { - // Calculate error correction code and pack bits - int data = getFormatBits(errorCorrectionLevel) << 3 | msk; // errCorrLvl is uint2, msk is uint3 - int rem = data; - for (int i = 0; i < 10; i++) - rem = (rem << 1) ^ ((rem >> 9) * 0x537); - int bits = (data << 10 | rem) ^ 0x5412; // uint15 - assert(bits >> 15 == 0); - - // Draw first copy - for (int i = 0; i <= 5; i++) - setFunctionModule(8, i, getBit(bits, i)); - setFunctionModule(8, 7, getBit(bits, 6)); - setFunctionModule(8, 8, getBit(bits, 7)); - setFunctionModule(7, 8, getBit(bits, 8)); - for (int i = 9; i < 15; i++) - setFunctionModule(14 - i, 8, getBit(bits, i)); - - // Draw second copy - for (int i = 0; i < 8; i++) - setFunctionModule(size - 1 - i, 8, getBit(bits, i)); - for (int i = 8; i < 15; i++) - setFunctionModule(8, size - 15 + i, getBit(bits, i)); - setFunctionModule(8, size - 8, true); // Always dark -} - - -void QrCode::drawVersion() { - if (version < 7) - return; - - // Calculate error correction code and pack bits - int rem = version; // version is uint6, in the range [7, 40] - for (int i = 0; i < 12; i++) - rem = (rem << 1) ^ ((rem >> 11) * 0x1F25); - long bits = static_cast(version) << 12 | rem; // uint18 - assert(bits >> 18 == 0); - - // Draw two copies - for (int i = 0; i < 18; i++) { - bool bit = getBit(bits, i); - int a = size - 11 + i % 3; - int b = i / 3; - setFunctionModule(a, b, bit); - setFunctionModule(b, a, bit); - } -} - - -void QrCode::drawFinderPattern(int x, int y) { - for (int dy = -4; dy <= 4; dy++) { - for (int dx = -4; dx <= 4; dx++) { - int dist = std::max(std::abs(dx), std::abs(dy)); // Chebyshev/infinity norm - int xx = x + dx, yy = y + dy; - if (0 <= xx && xx < size && 0 <= yy && yy < size) - setFunctionModule(xx, yy, dist != 2 && dist != 4); - } - } -} - - -void QrCode::drawAlignmentPattern(int x, int y) { - for (int dy = -2; dy <= 2; dy++) { - for (int dx = -2; dx <= 2; dx++) - setFunctionModule(x + dx, y + dy, std::max(std::abs(dx), std::abs(dy)) != 1); - } -} - - -void QrCode::setFunctionModule(int x, int y, bool isDark) { - size_t ux = static_cast(x); - size_t uy = static_cast(y); - modules .at(uy).at(ux) = isDark; - isFunction.at(uy).at(ux) = true; -} - - -bool QrCode::module(int x, int y) const { - return modules.at(static_cast(y)).at(static_cast(x)); -} - - -vector QrCode::addEccAndInterleave(const vector &data) const { - if (data.size() != static_cast(getNumDataCodewords(version, errorCorrectionLevel))) - throw std::invalid_argument("Invalid argument"); - - // Calculate parameter numbers - int numBlocks = NUM_ERROR_CORRECTION_BLOCKS[static_cast(errorCorrectionLevel)][version]; - int blockEccLen = ECC_CODEWORDS_PER_BLOCK [static_cast(errorCorrectionLevel)][version]; - int rawCodewords = getNumRawDataModules(version) / 8; - int numShortBlocks = numBlocks - rawCodewords % numBlocks; - int shortBlockLen = rawCodewords / numBlocks; - - // Split data into blocks and append ECC to each block - vector > blocks; - const vector rsDiv = reedSolomonComputeDivisor(blockEccLen); - for (int i = 0, k = 0; i < numBlocks; i++) { - vector dat(data.cbegin() + k, data.cbegin() + (k + shortBlockLen - blockEccLen + (i < numShortBlocks ? 0 : 1))); - k += static_cast(dat.size()); - const vector ecc = reedSolomonComputeRemainder(dat, rsDiv); - if (i < numShortBlocks) - dat.push_back(0); - dat.insert(dat.end(), ecc.cbegin(), ecc.cend()); - blocks.push_back(std::move(dat)); - } - - // Interleave (not concatenate) the bytes from every block into a single sequence - vector result; - for (size_t i = 0; i < blocks.at(0).size(); i++) { - for (size_t j = 0; j < blocks.size(); j++) { - // Skip the padding byte in short blocks - if (i != static_cast(shortBlockLen - blockEccLen) || j >= static_cast(numShortBlocks)) - result.push_back(blocks.at(j).at(i)); - } - } - assert(result.size() == static_cast(rawCodewords)); - return result; -} - - -void QrCode::drawCodewords(const vector &data) { - if (data.size() != static_cast(getNumRawDataModules(version) / 8)) - throw std::invalid_argument("Invalid argument"); - - size_t i = 0; // Bit index into the data - // Do the funny zigzag scan - for (int right = size - 1; right >= 1; right -= 2) { // Index of right column in each column pair - if (right == 6) - right = 5; - for (int vert = 0; vert < size; vert++) { // Vertical counter - for (int j = 0; j < 2; j++) { - size_t x = static_cast(right - j); // Actual x coordinate - bool upward = ((right + 1) & 2) == 0; - size_t y = static_cast(upward ? size - 1 - vert : vert); // Actual y coordinate - if (!isFunction.at(y).at(x) && i < data.size() * 8) { - modules.at(y).at(x) = getBit(data.at(i >> 3), 7 - static_cast(i & 7)); - i++; - } - // If this QR Code has any remainder bits (0 to 7), they were assigned as - // 0/false/light by the constructor and are left unchanged by this method - } - } - } - assert(i == data.size() * 8); -} - - -void QrCode::applyMask(int msk) { - if (msk < 0 || msk > 7) - throw std::domain_error("Mask value out of range"); - size_t sz = static_cast(size); - for (size_t y = 0; y < sz; y++) { - for (size_t x = 0; x < sz; x++) { - bool invert; - switch (msk) { - case 0: invert = (x + y) % 2 == 0; break; - case 1: invert = y % 2 == 0; break; - case 2: invert = x % 3 == 0; break; - case 3: invert = (x + y) % 3 == 0; break; - case 4: invert = (x / 3 + y / 2) % 2 == 0; break; - case 5: invert = x * y % 2 + x * y % 3 == 0; break; - case 6: invert = (x * y % 2 + x * y % 3) % 2 == 0; break; - case 7: invert = ((x + y) % 2 + x * y % 3) % 2 == 0; break; - default: throw std::logic_error("Unreachable"); - } - modules.at(y).at(x) = modules.at(y).at(x) ^ (invert & !isFunction.at(y).at(x)); - } - } -} - - -long QrCode::getPenaltyScore() const { - long result = 0; - - // Adjacent modules in row having same color, and finder-like patterns - for (int y = 0; y < size; y++) { - bool runColor = false; - int runX = 0; - std::array runHistory = {}; - for (int x = 0; x < size; x++) { - if (module(x, y) == runColor) { - runX++; - if (runX == 5) - result += PENALTY_N1; - else if (runX > 5) - result++; - } else { - finderPenaltyAddHistory(runX, runHistory); - if (!runColor) - result += finderPenaltyCountPatterns(runHistory) * PENALTY_N3; - runColor = module(x, y); - runX = 1; - } - } - result += finderPenaltyTerminateAndCount(runColor, runX, runHistory) * PENALTY_N3; - } - // Adjacent modules in column having same color, and finder-like patterns - for (int x = 0; x < size; x++) { - bool runColor = false; - int runY = 0; - std::array runHistory = {}; - for (int y = 0; y < size; y++) { - if (module(x, y) == runColor) { - runY++; - if (runY == 5) - result += PENALTY_N1; - else if (runY > 5) - result++; - } else { - finderPenaltyAddHistory(runY, runHistory); - if (!runColor) - result += finderPenaltyCountPatterns(runHistory) * PENALTY_N3; - runColor = module(x, y); - runY = 1; - } - } - result += finderPenaltyTerminateAndCount(runColor, runY, runHistory) * PENALTY_N3; - } - - // 2*2 blocks of modules having same color - for (int y = 0; y < size - 1; y++) { - for (int x = 0; x < size - 1; x++) { - bool color = module(x, y); - if ( color == module(x + 1, y) && - color == module(x, y + 1) && - color == module(x + 1, y + 1)) - result += PENALTY_N2; - } - } - - // Balance of dark and light modules - int dark = 0; - for (const vector &row : modules) { - for (bool color : row) { - if (color) - dark++; - } - } - int total = size * size; // Note that size is odd, so dark/total != 1/2 - // Compute the smallest integer k >= 0 such that (45-5k)% <= dark/total <= (55+5k)% - int k = static_cast((std::abs(dark * 20L - total * 10L) + total - 1) / total) - 1; - assert(0 <= k && k <= 9); - result += k * PENALTY_N4; - assert(0 <= result && result <= 2568888L); // Non-tight upper bound based on default values of PENALTY_N1, ..., N4 - return result; -} - - -vector QrCode::getAlignmentPatternPositions() const { - if (version == 1) - return vector(); - else { - int numAlign = version / 7 + 2; - int step = (version == 32) ? 26 : - (version * 4 + numAlign * 2 + 1) / (numAlign * 2 - 2) * 2; - vector result; - for (int i = 0, pos = size - 7; i < numAlign - 1; i++, pos -= step) - result.insert(result.begin(), pos); - result.insert(result.begin(), 6); - return result; - } -} - - -int QrCode::getNumRawDataModules(int ver) { - if (ver < MIN_VERSION || ver > MAX_VERSION) - throw std::domain_error("Version number out of range"); - int result = (16 * ver + 128) * ver + 64; - if (ver >= 2) { - int numAlign = ver / 7 + 2; - result -= (25 * numAlign - 10) * numAlign - 55; - if (ver >= 7) - result -= 36; - } - assert(208 <= result && result <= 29648); - return result; -} - - -int QrCode::getNumDataCodewords(int ver, Ecc ecl) { - return getNumRawDataModules(ver) / 8 - - ECC_CODEWORDS_PER_BLOCK [static_cast(ecl)][ver] - * NUM_ERROR_CORRECTION_BLOCKS[static_cast(ecl)][ver]; -} - - -vector QrCode::reedSolomonComputeDivisor(int degree) { - if (degree < 1 || degree > 255) - throw std::domain_error("Degree out of range"); - // Polynomial coefficients are stored from highest to lowest power, excluding the leading term which is always 1. - // For example the polynomial x^3 + 255x^2 + 8x + 93 is stored as the uint8 array {255, 8, 93}. - vector result(static_cast(degree)); - result.at(result.size() - 1) = 1; // Start off with the monomial x^0 - - // Compute the product polynomial (x - r^0) * (x - r^1) * (x - r^2) * ... * (x - r^{degree-1}), - // and drop the highest monomial term which is always 1x^degree. - // Note that r = 0x02, which is a generator element of this field GF(2^8/0x11D). - uint8_t root = 1; - for (int i = 0; i < degree; i++) { - // Multiply the current product by (x - r^i) - for (size_t j = 0; j < result.size(); j++) { - result.at(j) = reedSolomonMultiply(result.at(j), root); - if (j + 1 < result.size()) - result.at(j) ^= result.at(j + 1); - } - root = reedSolomonMultiply(root, 0x02); - } - return result; -} - - -vector QrCode::reedSolomonComputeRemainder(const vector &data, const vector &divisor) { - vector result(divisor.size()); - for (uint8_t b : data) { // Polynomial division - uint8_t factor = b ^ result.at(0); - result.erase(result.begin()); - result.push_back(0); - for (size_t i = 0; i < result.size(); i++) - result.at(i) ^= reedSolomonMultiply(divisor.at(i), factor); - } - return result; -} - - -uint8_t QrCode::reedSolomonMultiply(uint8_t x, uint8_t y) { - // Russian peasant multiplication - int z = 0; - for (int i = 7; i >= 0; i--) { - z = (z << 1) ^ ((z >> 7) * 0x11D); - z ^= ((y >> i) & 1) * x; - } - assert(z >> 8 == 0); - return static_cast(z); -} - - -int QrCode::finderPenaltyCountPatterns(const std::array &runHistory) const { - int n = runHistory.at(1); - assert(n <= size * 3); - bool core = n > 0 && runHistory.at(2) == n && runHistory.at(3) == n * 3 && runHistory.at(4) == n && runHistory.at(5) == n; - return (core && runHistory.at(0) >= n * 4 && runHistory.at(6) >= n ? 1 : 0) - + (core && runHistory.at(6) >= n * 4 && runHistory.at(0) >= n ? 1 : 0); -} - - -int QrCode::finderPenaltyTerminateAndCount(bool currentRunColor, int currentRunLength, std::array &runHistory) const { - if (currentRunColor) { // Terminate dark run - finderPenaltyAddHistory(currentRunLength, runHistory); - currentRunLength = 0; - } - currentRunLength += size; // Add light border to final run - finderPenaltyAddHistory(currentRunLength, runHistory); - return finderPenaltyCountPatterns(runHistory); -} - - -void QrCode::finderPenaltyAddHistory(int currentRunLength, std::array &runHistory) const { - if (runHistory.at(0) == 0) - currentRunLength += size; // Add light border to initial run - std::copy_backward(runHistory.cbegin(), runHistory.cend() - 1, runHistory.end()); - runHistory.at(0) = currentRunLength; -} - - -bool QrCode::getBit(long x, int i) { - return ((x >> i) & 1) != 0; -} - - -/*---- Tables of constants ----*/ - -const int QrCode::PENALTY_N1 = 3; -const int QrCode::PENALTY_N2 = 3; -const int QrCode::PENALTY_N3 = 40; -const int QrCode::PENALTY_N4 = 10; - - -const int8_t QrCode::ECC_CODEWORDS_PER_BLOCK[4][41] = { - // Version: (note that index 0 is for padding, and is set to an illegal value) - //0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level - {-1, 7, 10, 15, 20, 26, 18, 20, 24, 30, 18, 20, 24, 26, 30, 22, 24, 28, 30, 28, 28, 28, 28, 30, 30, 26, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // Low - {-1, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26, 30, 22, 22, 24, 24, 28, 28, 26, 26, 26, 26, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28}, // Medium - {-1, 13, 22, 18, 26, 18, 24, 18, 22, 20, 24, 28, 26, 24, 20, 30, 24, 28, 28, 26, 30, 28, 30, 30, 30, 30, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // Quartile - {-1, 17, 28, 22, 16, 22, 28, 26, 26, 24, 28, 24, 28, 22, 24, 24, 30, 28, 28, 26, 28, 30, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // High -}; - -const int8_t QrCode::NUM_ERROR_CORRECTION_BLOCKS[4][41] = { - // Version: (note that index 0 is for padding, and is set to an illegal value) - //0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level - {-1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25}, // Low - {-1, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49}, // Medium - {-1, 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25, 27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68}, // Quartile - {-1, 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81}, // High -}; - - -data_too_long::data_too_long(const std::string &msg) : - std::length_error(msg) {} - - - -/*---- Class BitBuffer ----*/ - -BitBuffer::BitBuffer() - : std::vector() {} - - -void BitBuffer::appendBits(std::uint32_t val, int len) { - if (len < 0 || len > 31 || val >> len != 0) - throw std::domain_error("Value out of range"); - for (int i = len - 1; i >= 0; i--) // Append bit by bit - this->push_back(((val >> i) & 1) != 0); -} - -} diff --git a/3rdparty/qrcodegen.hpp b/3rdparty/qrcodegen.hpp deleted file mode 100644 index 9448982..0000000 --- a/3rdparty/qrcodegen.hpp +++ /dev/null @@ -1,549 +0,0 @@ -/* - * QR Code generator library (C++) - * - * Copyright (c) Project Nayuki. (MIT License) - * https://www.nayuki.io/page/qr-code-generator-library - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - The Software is provided "as is", without warranty of any kind, express or - * implied, including but not limited to the warranties of merchantability, - * fitness for a particular purpose and noninfringement. In no event shall the - * authors or copyright holders be liable for any claim, damages or other - * liability, whether in an action of contract, tort or otherwise, arising from, - * out of or in connection with the Software or the use or other dealings in the - * Software. - */ - -#pragma once - -#include -#include -#include -#include -#include - - -namespace qrcodegen { - -/* - * A segment of character/binary/control data in a QR Code symbol. - * Instances of this class are immutable. - * The mid-level way to create a segment is to take the payload data - * and call a static factory function such as QrSegment::makeNumeric(). - * The low-level way to create a segment is to custom-make the bit buffer - * and call the QrSegment() constructor with appropriate values. - * This segment class imposes no length restrictions, but QR Codes have restrictions. - * Even in the most favorable conditions, a QR Code can only hold 7089 characters of data. - * Any segment longer than this is meaningless for the purpose of generating QR Codes. - */ -class QrSegment final { - - /*---- Public helper enumeration ----*/ - - /* - * Describes how a segment's data bits are interpreted. Immutable. - */ - public: class Mode final { - - /*-- Constants --*/ - - public: static const Mode NUMERIC; - public: static const Mode ALPHANUMERIC; - public: static const Mode BYTE; - public: static const Mode KANJI; - public: static const Mode ECI; - - - /*-- Fields --*/ - - // The mode indicator bits, which is a uint4 value (range 0 to 15). - private: int modeBits; - - // Number of character count bits for three different version ranges. - private: int numBitsCharCount[3]; - - - /*-- Constructor --*/ - - private: Mode(int mode, int cc0, int cc1, int cc2); - - - /*-- Methods --*/ - - /* - * (Package-private) Returns the mode indicator bits, which is an unsigned 4-bit value (range 0 to 15). - */ - public: int getModeBits() const; - - /* - * (Package-private) Returns the bit width of the character count field for a segment in - * this mode in a QR Code at the given version number. The result is in the range [0, 16]. - */ - public: int numCharCountBits(int ver) const; - - }; - - - - /*---- Static factory functions (mid level) ----*/ - - /* - * Returns a segment representing the given binary data encoded in - * byte mode. All input byte vectors are acceptable. Any text string - * can be converted to UTF-8 bytes and encoded as a byte mode segment. - */ - public: static QrSegment makeBytes(const std::vector &data); - - - /* - * Returns a segment representing the given string of decimal digits encoded in numeric mode. - */ - public: static QrSegment makeNumeric(const char *digits); - - - /* - * Returns a segment representing the given text string encoded in alphanumeric mode. - * The characters allowed are: 0 to 9, A to Z (uppercase only), space, - * dollar, percent, asterisk, plus, hyphen, period, slash, colon. - */ - public: static QrSegment makeAlphanumeric(const char *text); - - - /* - * Returns a list of zero or more segments to represent the given text string. The result - * may use various segment modes and switch modes to optimize the length of the bit stream. - */ - public: static std::vector makeSegments(const char *text); - - - /* - * Returns a segment representing an Extended Channel Interpretation - * (ECI) designator with the given assignment value. - */ - public: static QrSegment makeEci(long assignVal); - - - /*---- Public static helper functions ----*/ - - /* - * Tests whether the given string can be encoded as a segment in numeric mode. - * A string is encodable iff each character is in the range 0 to 9. - */ - public: static bool isNumeric(const char *text); - - - /* - * Tests whether the given string can be encoded as a segment in alphanumeric mode. - * A string is encodable iff each character is in the following set: 0 to 9, A to Z - * (uppercase only), space, dollar, percent, asterisk, plus, hyphen, period, slash, colon. - */ - public: static bool isAlphanumeric(const char *text); - - - - /*---- Instance fields ----*/ - - /* The mode indicator of this segment. Accessed through getMode(). */ - private: const Mode *mode; - - /* The length of this segment's unencoded data. Measured in characters for - * numeric/alphanumeric/kanji mode, bytes for byte mode, and 0 for ECI mode. - * Always zero or positive. Not the same as the data's bit length. - * Accessed through getNumChars(). */ - private: int numChars; - - /* The data bits of this segment. Accessed through getData(). */ - private: std::vector data; - - - /*---- Constructors (low level) ----*/ - - /* - * Creates a new QR Code segment with the given attributes and data. - * The character count (numCh) must agree with the mode and the bit buffer length, - * but the constraint isn't checked. The given bit buffer is copied and stored. - */ - public: QrSegment(const Mode &md, int numCh, const std::vector &dt); - - - /* - * Creates a new QR Code segment with the given parameters and data. - * The character count (numCh) must agree with the mode and the bit buffer length, - * but the constraint isn't checked. The given bit buffer is moved and stored. - */ - public: QrSegment(const Mode &md, int numCh, std::vector &&dt); - - - /*---- Methods ----*/ - - /* - * Returns the mode field of this segment. - */ - public: const Mode &getMode() const; - - - /* - * Returns the character count field of this segment. - */ - public: int getNumChars() const; - - - /* - * Returns the data bits of this segment. - */ - public: const std::vector &getData() const; - - - // (Package-private) Calculates the number of bits needed to encode the given segments at - // the given version. Returns a non-negative number if successful. Otherwise returns -1 if a - // segment has too many characters to fit its length field, or the total bits exceeds INT_MAX. - public: static int getTotalBits(const std::vector &segs, int version); - - - /*---- Private constant ----*/ - - /* The set of all legal characters in alphanumeric mode, where - * each character value maps to the index in the string. */ - private: static const char *ALPHANUMERIC_CHARSET; - -}; - - - -/* - * A QR Code symbol, which is a type of two-dimension barcode. - * Invented by Denso Wave and described in the ISO/IEC 18004 standard. - * Instances of this class represent an immutable square grid of dark and light cells. - * The class provides static factory functions to create a QR Code from text or binary data. - * The class covers the QR Code Model 2 specification, supporting all versions (sizes) - * from 1 to 40, all 4 error correction levels, and 4 character encoding modes. - * - * Ways to create a QR Code object: - * - High level: Take the payload data and call QrCode::encodeText() or QrCode::encodeBinary(). - * - Mid level: Custom-make the list of segments and call QrCode::encodeSegments(). - * - Low level: Custom-make the array of data codeword bytes (including - * segment headers and final padding, excluding error correction codewords), - * supply the appropriate version number, and call the QrCode() constructor. - * (Note that all ways require supplying the desired error correction level.) - */ -class QrCode final { - - /*---- Public helper enumeration ----*/ - - /* - * The error correction level in a QR Code symbol. - */ - public: enum class Ecc { - LOW = 0 , // The QR Code can tolerate about 7% erroneous codewords - MEDIUM , // The QR Code can tolerate about 15% erroneous codewords - QUARTILE, // The QR Code can tolerate about 25% erroneous codewords - HIGH , // The QR Code can tolerate about 30% erroneous codewords - }; - - - // Returns a value in the range 0 to 3 (unsigned 2-bit integer). - private: static int getFormatBits(Ecc ecl); - - - - /*---- Static factory functions (high level) ----*/ - - /* - * Returns a QR Code representing the given Unicode text string at the given error correction level. - * As a conservative upper bound, this function is guaranteed to succeed for strings that have 2953 or fewer - * UTF-8 code units (not Unicode code points) if the low error correction level is used. The smallest possible - * QR Code version is automatically chosen for the output. The ECC level of the result may be higher than - * the ecl argument if it can be done without increasing the version. - */ - public: static QrCode encodeText(const char *text, Ecc ecl); - - - /* - * Returns a QR Code representing the given binary data at the given error correction level. - * This function always encodes using the binary segment mode, not any text mode. The maximum number of - * bytes allowed is 2953. The smallest possible QR Code version is automatically chosen for the output. - * The ECC level of the result may be higher than the ecl argument if it can be done without increasing the version. - */ - public: static QrCode encodeBinary(const std::vector &data, Ecc ecl); - - - /*---- Static factory functions (mid level) ----*/ - - /* - * Returns a QR Code representing the given segments with the given encoding parameters. - * The smallest possible QR Code version within the given range is automatically - * chosen for the output. Iff boostEcl is true, then the ECC level of the result - * may be higher than the ecl argument if it can be done without increasing the - * version. The mask number is either between 0 to 7 (inclusive) to force that - * mask, or -1 to automatically choose an appropriate mask (which may be slow). - * This function allows the user to create a custom sequence of segments that switches - * between modes (such as alphanumeric and byte) to encode text in less space. - * This is a mid-level API; the high-level API is encodeText() and encodeBinary(). - */ - public: static QrCode encodeSegments(const std::vector &segs, Ecc ecl, - int minVersion=1, int maxVersion=40, int mask=-1, bool boostEcl=true); // All optional parameters - - - - /*---- Instance fields ----*/ - - // Immutable scalar parameters: - - /* The version number of this QR Code, which is between 1 and 40 (inclusive). - * This determines the size of this barcode. */ - private: int version; - - /* The width and height of this QR Code, measured in modules, between - * 21 and 177 (inclusive). This is equal to version * 4 + 17. */ - private: int size; - - /* The error correction level used in this QR Code. */ - private: Ecc errorCorrectionLevel; - - /* The index of the mask pattern used in this QR Code, which is between 0 and 7 (inclusive). - * Even if a QR Code is created with automatic masking requested (mask = -1), - * the resulting object still has a mask value between 0 and 7. */ - private: int mask; - - // Private grids of modules/pixels, with dimensions of size*size: - - // The modules of this QR Code (false = light, true = dark). - // Immutable after constructor finishes. Accessed through getModule(). - private: std::vector > modules; - - // Indicates function modules that are not subjected to masking. Discarded when constructor finishes. - private: std::vector > isFunction; - - - - /*---- Constructor (low level) ----*/ - - /* - * Creates a new QR Code with the given version number, - * error correction level, data codeword bytes, and mask number. - * This is a low-level API that most users should not use directly. - * A mid-level API is the encodeSegments() function. - */ - public: QrCode(int ver, Ecc ecl, const std::vector &dataCodewords, int msk); - - - - /*---- Public instance methods ----*/ - - /* - * Returns this QR Code's version, in the range [1, 40]. - */ - public: int getVersion() const; - - - /* - * Returns this QR Code's size, in the range [21, 177]. - */ - public: int getSize() const; - - - /* - * Returns this QR Code's error correction level. - */ - public: Ecc getErrorCorrectionLevel() const; - - - /* - * Returns this QR Code's mask, in the range [0, 7]. - */ - public: int getMask() const; - - - /* - * Returns the color of the module (pixel) at the given coordinates, which is false - * for light or true for dark. The top left corner has the coordinates (x=0, y=0). - * If the given coordinates are out of bounds, then false (light) is returned. - */ - public: bool getModule(int x, int y) const; - - - - /*---- Private helper methods for constructor: Drawing function modules ----*/ - - // Reads this object's version field, and draws and marks all function modules. - private: void drawFunctionPatterns(); - - - // Draws two copies of the format bits (with its own error correction code) - // based on the given mask and this object's error correction level field. - private: void drawFormatBits(int msk); - - - // Draws two copies of the version bits (with its own error correction code), - // based on this object's version field, iff 7 <= version <= 40. - private: void drawVersion(); - - - // Draws a 9*9 finder pattern including the border separator, - // with the center module at (x, y). Modules can be out of bounds. - private: void drawFinderPattern(int x, int y); - - - // Draws a 5*5 alignment pattern, with the center module - // at (x, y). All modules must be in bounds. - private: void drawAlignmentPattern(int x, int y); - - - // Sets the color of a module and marks it as a function module. - // Only used by the constructor. Coordinates must be in bounds. - private: void setFunctionModule(int x, int y, bool isDark); - - - // Returns the color of the module at the given coordinates, which must be in range. - private: bool module(int x, int y) const; - - - /*---- Private helper methods for constructor: Codewords and masking ----*/ - - // Returns a new byte string representing the given data with the appropriate error correction - // codewords appended to it, based on this object's version and error correction level. - private: std::vector addEccAndInterleave(const std::vector &data) const; - - - // Draws the given sequence of 8-bit codewords (data and error correction) onto the entire - // data area of this QR Code. Function modules need to be marked off before this is called. - private: void drawCodewords(const std::vector &data); - - - // XORs the codeword modules in this QR Code with the given mask pattern. - // The function modules must be marked and the codeword bits must be drawn - // before masking. Due to the arithmetic of XOR, calling applyMask() with - // the same mask value a second time will undo the mask. A final well-formed - // QR Code needs exactly one (not zero, two, etc.) mask applied. - private: void applyMask(int msk); - - - // Calculates and returns the penalty score based on state of this QR Code's current modules. - // This is used by the automatic mask choice algorithm to find the mask pattern that yields the lowest score. - private: long getPenaltyScore() const; - - - - /*---- Private helper functions ----*/ - - // Returns an ascending list of positions of alignment patterns for this version number. - // Each position is in the range [0,177), and are used on both the x and y axes. - // This could be implemented as lookup table of 40 variable-length lists of unsigned bytes. - private: std::vector getAlignmentPatternPositions() const; - - - // Returns the number of data bits that can be stored in a QR Code of the given version number, after - // all function modules are excluded. This includes remainder bits, so it might not be a multiple of 8. - // The result is in the range [208, 29648]. This could be implemented as a 40-entry lookup table. - private: static int getNumRawDataModules(int ver); - - - // Returns the number of 8-bit data (i.e. not error correction) codewords contained in any - // QR Code of the given version number and error correction level, with remainder bits discarded. - // This stateless pure function could be implemented as a (40*4)-cell lookup table. - private: static int getNumDataCodewords(int ver, Ecc ecl); - - - // Returns a Reed-Solomon ECC generator polynomial for the given degree. This could be - // implemented as a lookup table over all possible parameter values, instead of as an algorithm. - private: static std::vector reedSolomonComputeDivisor(int degree); - - - // Returns the Reed-Solomon error correction codeword for the given data and divisor polynomials. - private: static std::vector reedSolomonComputeRemainder(const std::vector &data, const std::vector &divisor); - - - // Returns the product of the two given field elements modulo GF(2^8/0x11D). - // All inputs are valid. This could be implemented as a 256*256 lookup table. - private: static std::uint8_t reedSolomonMultiply(std::uint8_t x, std::uint8_t y); - - - // Can only be called immediately after a light run is added, and - // returns either 0, 1, or 2. A helper function for getPenaltyScore(). - private: int finderPenaltyCountPatterns(const std::array &runHistory) const; - - - // Must be called at the end of a line (row or column) of modules. A helper function for getPenaltyScore(). - private: int finderPenaltyTerminateAndCount(bool currentRunColor, int currentRunLength, std::array &runHistory) const; - - - // Pushes the given value to the front and drops the last value. A helper function for getPenaltyScore(). - private: void finderPenaltyAddHistory(int currentRunLength, std::array &runHistory) const; - - - // Returns true iff the i'th bit of x is set to 1. - private: static bool getBit(long x, int i); - - - /*---- Constants and tables ----*/ - - // The minimum version number supported in the QR Code Model 2 standard. - public: static constexpr int MIN_VERSION = 1; - - // The maximum version number supported in the QR Code Model 2 standard. - public: static constexpr int MAX_VERSION = 40; - - - // For use in getPenaltyScore(), when evaluating which mask is best. - private: static const int PENALTY_N1; - private: static const int PENALTY_N2; - private: static const int PENALTY_N3; - private: static const int PENALTY_N4; - - - private: static const std::int8_t ECC_CODEWORDS_PER_BLOCK[4][41]; - private: static const std::int8_t NUM_ERROR_CORRECTION_BLOCKS[4][41]; - -}; - - - -/*---- Public exception class ----*/ - -/* - * Thrown when the supplied data does not fit any QR Code version. Ways to handle this exception include: - * - Decrease the error correction level if it was greater than Ecc::LOW. - * - If the encodeSegments() function was called with a maxVersion argument, then increase - * it if it was less than QrCode::MAX_VERSION. (This advice does not apply to the other - * factory functions because they search all versions up to QrCode::MAX_VERSION.) - * - Split the text data into better or optimal segments in order to reduce the number of bits required. - * - Change the text or binary data to be shorter. - * - Change the text to fit the character set of a particular segment mode (e.g. alphanumeric). - * - Propagate the error upward to the caller/user. - */ -class data_too_long : public std::length_error { - - public: explicit data_too_long(const std::string &msg); - -}; - - - -/* - * An appendable sequence of bits (0s and 1s). Mainly used by QrSegment. - */ -class BitBuffer final : public std::vector { - - /*---- Constructor ----*/ - - // Creates an empty bit buffer (length 0). - public: BitBuffer(); - - - - /*---- Method ----*/ - - // Appends the given number of low-order bits of the given value - // to this buffer. Requires 0 <= len <= 31 and val < 2^len. - public: void appendBits(std::uint32_t val, int len); - -}; - -} diff --git a/3rdparty/qscopeguard.h b/3rdparty/qscopeguard.h deleted file mode 100644 index 31100fc..0000000 --- a/3rdparty/qscopeguard.h +++ /dev/null @@ -1,96 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Sérgio Martins -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCOPEGUARD_H -#define QSCOPEGUARD_H - -#include - - -QT_BEGIN_NAMESPACE - - -template class QScopeGuard; -template QScopeGuard qScopeGuard(F f); - -template -class QScopeGuard -{ -public: - QScopeGuard(QScopeGuard &&other) Q_DECL_NOEXCEPT - : m_func(std::move(other.m_func)) - , m_invoke(other.m_invoke) - { - other.dismiss(); - } - - ~QScopeGuard() - { - if (m_invoke) - m_func(); - } - - void dismiss() Q_DECL_NOEXCEPT - { - m_invoke = false; - } - -private: - explicit QScopeGuard(F f) Q_DECL_NOEXCEPT - : m_func(std::move(f)) - { - } - - Q_DISABLE_COPY(QScopeGuard) - - F m_func; - bool m_invoke = true; - friend QScopeGuard qScopeGuard(F); -}; - - -template -QScopeGuard qScopeGuard(F f) -{ - return QScopeGuard(std::move(f)); -} - -QT_END_NAMESPACE - -#endif // QSCOPEGUARD_H diff --git a/3rdparty/qv2ray/v2/components/proxy/QvProxyConfigurator.cpp b/3rdparty/qv2ray/v2/components/proxy/QvProxyConfigurator.cpp deleted file mode 100644 index f3a283d..0000000 --- a/3rdparty/qv2ray/v2/components/proxy/QvProxyConfigurator.cpp +++ /dev/null @@ -1,440 +0,0 @@ -#include "QvProxyConfigurator.hpp" - -#ifdef Q_OS_WIN -// -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#include -// -#include -#include -#include -#include -#endif - -#include -#include - -#include "3rdparty/fix_old_qt.h" -#include "3rdparty/qv2ray/wrapper.hpp" -#include "fmt/Preset.hpp" -#include "main/NekoGui.hpp" - -#define QV_MODULE_NAME "SystemProxy" - -#define QSTRN(num) QString::number(num) - -namespace Qv2ray::components::proxy { - - using ProcessArgument = QPair; -#ifdef Q_OS_MACOS - QStringList macOSgetNetworkServices() { - QProcess p; - p.setProgram("/usr/sbin/networksetup"); - p.setArguments(QStringList{"-listallnetworkservices"}); - p.start(); - p.waitForStarted(); - p.waitForFinished(); - LOG(p.errorString()); - auto str = p.readAllStandardOutput(); - auto lines = SplitLines(str); - QStringList result; - - // Start from 1 since first line is unneeded. - for (auto i = 1; i < lines.count(); i++) { - // * means disabled. - if (!lines[i].contains("*")) { - result << lines[i]; - } - } - - LOG("Found " + QSTRN(result.size()) + " network services: " + result.join(";")); - return result; - } -#endif -#ifdef Q_OS_WIN -#define NO_CONST(expr) const_cast(expr) - // static auto DEFAULT_CONNECTION_NAME = - // NO_CONST(L"DefaultConnectionSettings"); - /// - /// INTERNAL FUNCTION - bool __QueryProxyOptions() { - INTERNET_PER_CONN_OPTION_LIST List; - INTERNET_PER_CONN_OPTION Option[5]; - // - unsigned long nSize = sizeof(INTERNET_PER_CONN_OPTION_LIST); - Option[0].dwOption = INTERNET_PER_CONN_AUTOCONFIG_URL; - Option[1].dwOption = INTERNET_PER_CONN_AUTODISCOVERY_FLAGS; - Option[2].dwOption = INTERNET_PER_CONN_FLAGS; - Option[3].dwOption = INTERNET_PER_CONN_PROXY_BYPASS; - Option[4].dwOption = INTERNET_PER_CONN_PROXY_SERVER; - // - List.dwSize = sizeof(INTERNET_PER_CONN_OPTION_LIST); - List.pszConnection = nullptr; // NO_CONST(DEFAULT_CONNECTION_NAME); - List.dwOptionCount = 5; - List.dwOptionError = 0; - List.pOptions = Option; - - if (!InternetQueryOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &List, &nSize)) { - LOG("InternetQueryOption failed, GLE=" + QSTRN(GetLastError())); - } - - LOG("System default proxy info:"); - - if (Option[0].Value.pszValue != nullptr) { - LOG(QString::fromWCharArray(Option[0].Value.pszValue)); - } - - if ((Option[2].Value.dwValue & PROXY_TYPE_AUTO_PROXY_URL) == PROXY_TYPE_AUTO_PROXY_URL) { - LOG("PROXY_TYPE_AUTO_PROXY_URL"); - } - - if ((Option[2].Value.dwValue & PROXY_TYPE_AUTO_DETECT) == PROXY_TYPE_AUTO_DETECT) { - LOG("PROXY_TYPE_AUTO_DETECT"); - } - - if ((Option[2].Value.dwValue & PROXY_TYPE_DIRECT) == PROXY_TYPE_DIRECT) { - LOG("PROXY_TYPE_DIRECT"); - } - - if ((Option[2].Value.dwValue & PROXY_TYPE_PROXY) == PROXY_TYPE_PROXY) { - LOG("PROXY_TYPE_PROXY"); - } - - if (!InternetQueryOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &List, &nSize)) { - LOG("InternetQueryOption failed,GLE=" + QSTRN(GetLastError())); - } - - if (Option[4].Value.pszValue != nullptr) { - LOG(QString::fromStdWString(Option[4].Value.pszValue)); - } - - INTERNET_VERSION_INFO Version; - nSize = sizeof(INTERNET_VERSION_INFO); - InternetQueryOption(nullptr, INTERNET_OPTION_VERSION, &Version, &nSize); - - if (Option[0].Value.pszValue != nullptr) { - GlobalFree(Option[0].Value.pszValue); - } - - if (Option[3].Value.pszValue != nullptr) { - GlobalFree(Option[3].Value.pszValue); - } - - if (Option[4].Value.pszValue != nullptr) { - GlobalFree(Option[4].Value.pszValue); - } - - return false; - } - bool __SetProxyOptions(LPWSTR proxy_full_addr, bool isPAC) { - INTERNET_PER_CONN_OPTION_LIST list; - DWORD dwBufSize = sizeof(list); - // Fill the list structure. - list.dwSize = sizeof(list); - // NULL == LAN, otherwise connectoid name. - list.pszConnection = nullptr; - - if (nullptr == proxy_full_addr) { - LOG("Clearing system proxy"); - // - list.dwOptionCount = 1; - list.pOptions = new INTERNET_PER_CONN_OPTION[1]; - - // Ensure that the memory was allocated. - if (nullptr == list.pOptions) { - // Return if the memory wasn't allocated. - return false; - } - - // Set flags. - list.pOptions[0].dwOption = INTERNET_PER_CONN_FLAGS; - list.pOptions[0].Value.dwValue = PROXY_TYPE_DIRECT; - } else if (isPAC) { - LOG("Setting system proxy for PAC"); - // - list.dwOptionCount = 2; - list.pOptions = new INTERNET_PER_CONN_OPTION[2]; - - if (nullptr == list.pOptions) { - return false; - } - - // Set flags. - list.pOptions[0].dwOption = INTERNET_PER_CONN_FLAGS; - list.pOptions[0].Value.dwValue = PROXY_TYPE_DIRECT | PROXY_TYPE_AUTO_PROXY_URL; - // Set proxy name. - list.pOptions[1].dwOption = INTERNET_PER_CONN_AUTOCONFIG_URL; - list.pOptions[1].Value.pszValue = proxy_full_addr; - } else { - LOG("Setting system proxy for Global Proxy"); - // - list.dwOptionCount = 2; - list.pOptions = new INTERNET_PER_CONN_OPTION[2]; - - if (nullptr == list.pOptions) { - return false; - } - - // Set flags. - list.pOptions[0].dwOption = INTERNET_PER_CONN_FLAGS; - list.pOptions[0].Value.dwValue = PROXY_TYPE_DIRECT | PROXY_TYPE_PROXY; - // Set proxy name. - list.pOptions[1].dwOption = INTERNET_PER_CONN_PROXY_SERVER; - list.pOptions[1].Value.pszValue = proxy_full_addr; - // Set proxy override. - // list.pOptions[2].dwOption = INTERNET_PER_CONN_PROXY_BYPASS; - // auto localhost = L"localhost"; - // list.pOptions[2].Value.pszValue = NO_CONST(localhost); - } - - // Set proxy for LAN. - if (!InternetSetOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &list, dwBufSize)) { - LOG("InternetSetOption failed for LAN, GLE=" + QSTRN(GetLastError())); - } - - RASENTRYNAME entry; - entry.dwSize = sizeof(entry); - std::vector entries; - DWORD size = sizeof(entry), count; - LPRASENTRYNAME entryAddr = &entry; - auto ret = RasEnumEntries(nullptr, nullptr, entryAddr, &size, &count); - if (ERROR_BUFFER_TOO_SMALL == ret) { - entries.resize(count); - entries[0].dwSize = sizeof(RASENTRYNAME); - entryAddr = entries.data(); - ret = RasEnumEntries(nullptr, nullptr, entryAddr, &size, &count); - } - if (ERROR_SUCCESS != ret) { - LOG("Failed to list entry names"); - return false; - } - - // Set proxy for each connectoid. - for (DWORD i = 0; i < count; ++i) { - list.pszConnection = entryAddr[i].szEntryName; - if (!InternetSetOption(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION, &list, dwBufSize)) { - LOG("InternetSetOption failed for connectoid " + QString::fromWCharArray(list.pszConnection) + ", GLE=" + QSTRN(GetLastError())); - } - } - - delete[] list.pOptions; - InternetSetOption(nullptr, INTERNET_OPTION_SETTINGS_CHANGED, nullptr, 0); - InternetSetOption(nullptr, INTERNET_OPTION_REFRESH, nullptr, 0); - return true; - } -#endif - - void SetSystemProxy(int httpPort, int socksPort) { - const QString &address = "127.0.0.1"; - bool hasHTTP = (httpPort > 0 && httpPort < 65536); - bool hasSOCKS = (socksPort > 0 && socksPort < 65536); - -#ifdef Q_OS_WIN - if (!hasHTTP) { - LOG("Nothing?"); - return; - } else { - LOG("Qv2ray will set system proxy to use HTTP"); - } -#else - if (!hasHTTP && !hasSOCKS) { - LOG("Nothing?"); - return; - } - - if (hasHTTP) { - LOG("Qv2ray will set system proxy to use HTTP"); - } - - if (hasSOCKS) { - LOG("Qv2ray will set system proxy to use SOCKS"); - } -#endif - -#ifdef Q_OS_WIN - QString str = NekoGui::dataStore->system_proxy_format; - if (str.isEmpty()) str = Preset::Windows::system_proxy_format[0]; - str = str.replace("{ip}", address) - .replace("{http_port}", Int2String(httpPort)) - .replace("{socks_port}", Int2String(socksPort)); - // - LOG("Windows proxy string: " + str); - auto proxyStrW = new WCHAR[str.length() + 1]; - wcscpy(proxyStrW, str.toStdWString().c_str()); - // - __QueryProxyOptions(); - - if (!__SetProxyOptions(proxyStrW, false)) { - LOG("Failed to set proxy."); - } - - __QueryProxyOptions(); -#elif defined(Q_OS_LINUX) - QList actions; - actions << ProcessArgument{"gsettings", {"set", "org.gnome.system.proxy", "mode", "manual"}}; - // - bool isKDE = qEnvironmentVariable("XDG_SESSION_DESKTOP") == "KDE" || - qEnvironmentVariable("XDG_SESSION_DESKTOP") == "plasma"; - const auto configPath = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation); - - // - // Configure HTTP Proxies for HTTP, FTP and HTTPS - if (hasHTTP) { - // iterate over protocols... - for (const auto &protocol: QStringList{"http", "ftp", "https"}) { - // for GNOME: - { - actions << ProcessArgument{"gsettings", - {"set", "org.gnome.system.proxy." + protocol, "host", address}}; - actions << ProcessArgument{"gsettings", - {"set", "org.gnome.system.proxy." + protocol, "port", QSTRN(httpPort)}}; - } - - // for KDE: - if (isKDE) { - actions << ProcessArgument{"kwriteconfig5", - {"--file", configPath + "/kioslaverc", // - "--group", "Proxy Settings", // - "--key", protocol + "Proxy", // - "http://" + address + " " + QSTRN(httpPort)}}; - } - } - } - - // Configure SOCKS5 Proxies - if (hasSOCKS) { - // for GNOME: - { - actions << ProcessArgument{"gsettings", {"set", "org.gnome.system.proxy.socks", "host", address}}; - actions << ProcessArgument{"gsettings", - {"set", "org.gnome.system.proxy.socks", "port", QSTRN(socksPort)}}; - - // for KDE: - if (isKDE) { - actions << ProcessArgument{"kwriteconfig5", - {"--file", configPath + "/kioslaverc", // - "--group", "Proxy Settings", // - "--key", "socksProxy", // - "socks://" + address + " " + QSTRN(socksPort)}}; - } - } - } - // Setting Proxy Mode to Manual - { - // for GNOME: - { - actions << ProcessArgument{"gsettings", {"set", "org.gnome.system.proxy", "mode", "manual"}}; - } - - // for KDE: - if (isKDE) { - actions << ProcessArgument{"kwriteconfig5", - {"--file", configPath + "/kioslaverc", // - "--group", "Proxy Settings", // - "--key", "ProxyType", "1"}}; - } - } - - // Notify kioslaves to reload system proxy configuration. - if (isKDE) { - actions << ProcessArgument{"dbus-send", - {"--type=signal", "/KIO/Scheduler", // - "org.kde.KIO.Scheduler.reparseSlaveConfiguration", // - "string:''"}}; - } - // Execute them all! - // - // note: do not use std::all_of / any_of / none_of, - // because those are short-circuit and cannot guarantee atomicity. - QList results; - for (const auto &action: actions) { - // execute and get the code - const auto returnCode = QProcess::execute(action.first, action.second); - // print out the commands and result codes - DEBUG(QStringLiteral("[%1] Program: %2, Args: %3").arg(returnCode).arg(action.first).arg(action.second.join(";"))); - // give the code back - results << (returnCode == QProcess::NormalExit); - } - - if (results.count(true) != actions.size()) { - LOG("Something wrong when setting proxies."); - } -#else - - for (const auto &service: macOSgetNetworkServices()) { - LOG("Setting proxy for interface: " + service); - if (hasHTTP) { - QProcess::execute("/usr/sbin/networksetup", {"-setwebproxystate", service, "on"}); - QProcess::execute("/usr/sbin/networksetup", {"-setsecurewebproxystate", service, "on"}); - QProcess::execute("/usr/sbin/networksetup", {"-setwebproxy", service, address, QSTRN(httpPort)}); - QProcess::execute("/usr/sbin/networksetup", {"-setsecurewebproxy", service, address, QSTRN(httpPort)}); - } - - if (hasSOCKS) { - QProcess::execute("/usr/sbin/networksetup", {"-setsocksfirewallproxystate", service, "on"}); - QProcess::execute("/usr/sbin/networksetup", {"-setsocksfirewallproxy", service, address, QSTRN(socksPort)}); - } - } - -#endif - } - - void ClearSystemProxy() { - LOG("Clearing System Proxy"); - -#ifdef Q_OS_WIN - if (!__SetProxyOptions(nullptr, false)) { - LOG("Failed to clear proxy."); - } -#elif defined(Q_OS_LINUX) - QList actions; - const bool isKDE = qEnvironmentVariable("XDG_SESSION_DESKTOP") == "KDE" || - qEnvironmentVariable("XDG_SESSION_DESKTOP") == "plasma"; - const auto configRoot = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation); - - // Setting System Proxy Mode to: None - { - // for GNOME: - { - actions << ProcessArgument{"gsettings", {"set", "org.gnome.system.proxy", "mode", "none"}}; - } - - // for KDE: - if (isKDE) { - actions << ProcessArgument{"kwriteconfig5", - {"--file", configRoot + "/kioslaverc", // - "--group", "Proxy Settings", // - "--key", "ProxyType", "0"}}; - } - } - - // Notify kioslaves to reload system proxy configuration. - if (isKDE) { - actions << ProcessArgument{"dbus-send", - {"--type=signal", "/KIO/Scheduler", // - "org.kde.KIO.Scheduler.reparseSlaveConfiguration", // - "string:''"}}; - } - - // Execute the Actions - for (const auto &action: actions) { - // execute and get the code - const auto returnCode = QProcess::execute(action.first, action.second); - // print out the commands and result codes - DEBUG(QStringLiteral("[%1] Program: %2, Args: %3").arg(returnCode).arg(action.first).arg(action.second.join(";"))); - } - -#else - for (const auto &service: macOSgetNetworkServices()) { - LOG("Clearing proxy for interface: " + service); - QProcess::execute("/usr/sbin/networksetup", {"-setautoproxystate", service, "off"}); - QProcess::execute("/usr/sbin/networksetup", {"-setwebproxystate", service, "off"}); - QProcess::execute("/usr/sbin/networksetup", {"-setsecurewebproxystate", service, "off"}); - QProcess::execute("/usr/sbin/networksetup", {"-setsocksfirewallproxystate", service, "off"}); - } - -#endif - } -} // namespace Qv2ray::components::proxy diff --git a/3rdparty/qv2ray/v2/components/proxy/QvProxyConfigurator.hpp b/3rdparty/qv2ray/v2/components/proxy/QvProxyConfigurator.hpp deleted file mode 100644 index eaa2c0f..0000000 --- a/3rdparty/qv2ray/v2/components/proxy/QvProxyConfigurator.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include -#include -#include -// -namespace Qv2ray::components::proxy { - void ClearSystemProxy(); - void SetSystemProxy(int http_port, int socks_port); -} // namespace Qv2ray::components::proxy - -using namespace Qv2ray::components; -using namespace Qv2ray::components::proxy; diff --git a/3rdparty/qv2ray/v2/ui/QvAutoCompleteTextEdit.cpp b/3rdparty/qv2ray/v2/ui/QvAutoCompleteTextEdit.cpp deleted file mode 100644 index e4edd82..0000000 --- a/3rdparty/qv2ray/v2/ui/QvAutoCompleteTextEdit.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "QvAutoCompleteTextEdit.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Qv2ray::ui::widgets { - AutoCompleteTextEdit::AutoCompleteTextEdit(const QString &prefix, const QStringList &sourceStrings, QWidget *parent) : QPlainTextEdit(parent) { - this->prefix = prefix; - this->setLineWrapMode(QPlainTextEdit::NoWrap); - c = new QCompleter(this); - c->setModel(new QStringListModel(sourceStrings, c)); - c->setWidget(this); - c->setCompletionMode(QCompleter::PopupCompletion); - c->setCaseSensitivity(Qt::CaseInsensitive); - QObject::connect(c, static_cast(&QCompleter::activated), this, &AutoCompleteTextEdit::insertCompletion); - } - - AutoCompleteTextEdit::~AutoCompleteTextEdit() { - } - - void AutoCompleteTextEdit::insertCompletion(const QString &completion) { - QTextCursor tc = textCursor(); - int extra = completion.length() - c->completionPrefix().length(); - tc.movePosition(QTextCursor::Left); - tc.movePosition(QTextCursor::EndOfWord); - tc.insertText(completion.right(extra).toLower()); - setTextCursor(tc); - } - - QString AutoCompleteTextEdit::lineUnderCursor() const { - QTextCursor tc = textCursor(); - tc.select(QTextCursor::LineUnderCursor); - return tc.selectedText(); - } - - QString AutoCompleteTextEdit::wordUnderCursor() const { - QTextCursor tc = textCursor(); - tc.select(QTextCursor::WordUnderCursor); - return tc.selectedText(); - } - - void AutoCompleteTextEdit::focusInEvent(QFocusEvent *e) { - if (c) - c->setWidget(this); - - QPlainTextEdit::focusInEvent(e); - } - - void AutoCompleteTextEdit::keyPressEvent(QKeyEvent *e) { - const bool hasCtrlOrShiftModifier = e->modifiers().testFlag(Qt::ControlModifier) || e->modifiers().testFlag(Qt::ShiftModifier); - const bool hasOtherModifiers = (e->modifiers() != Qt::NoModifier) && !hasCtrlOrShiftModifier; // has other modifiers - // - const bool isSpace = (e->modifiers().testFlag(Qt::ShiftModifier) || e->modifiers().testFlag(Qt::NoModifier)) // - && e->key() == Qt::Key_Space; - const bool isTab = (e->modifiers().testFlag(Qt::NoModifier) && e->key() == Qt::Key_Tab); - const bool isOtherSpace = e->text() == " "; - // - if (isSpace || isTab || isOtherSpace) { - QToolTip::showText(this->mapToGlobal(QPoint(0, 0)), tr("You can not input space characters here."), this, QRect{}, 2000); - return; - } - // - if (c && c->popup()->isVisible()) { - // The following keys are forwarded by the completer to the widget - switch (e->key()) { - case Qt::Key_Enter: - case Qt::Key_Return: - case Qt::Key_Escape: - case Qt::Key_Tab: - case Qt::Key_Backtab: - e->ignore(); - return; // let the completer do default behavior - - default: - break; - } - } - - QPlainTextEdit::keyPressEvent(e); - - if (!c || (hasCtrlOrShiftModifier && e->text().isEmpty())) - return; - - // if we have other modifiers, or the text is empty, or the line does not start with our prefix. - if (hasOtherModifiers || e->text().isEmpty() || !lineUnderCursor().startsWith(prefix)) { - c->popup()->hide(); - return; - } - - if (auto word = wordUnderCursor(); word != c->completionPrefix()) { - c->setCompletionPrefix(word); - c->popup()->setCurrentIndex(c->completionModel()->index(0, 0)); - } - - QRect cr = cursorRect(); - cr.setWidth(c->popup()->sizeHintForColumn(0) + c->popup()->verticalScrollBar()->sizeHint().width()); - c->complete(cr); // popup it up! - } -} // namespace Qv2ray::ui::widgets diff --git a/3rdparty/qv2ray/v2/ui/QvAutoCompleteTextEdit.hpp b/3rdparty/qv2ray/v2/ui/QvAutoCompleteTextEdit.hpp deleted file mode 100644 index b7bf570..0000000 --- a/3rdparty/qv2ray/v2/ui/QvAutoCompleteTextEdit.hpp +++ /dev/null @@ -1,85 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#pragma once -#include -#include -QT_BEGIN_NAMESPACE -class QCompleter; -QT_END_NAMESPACE - -namespace Qv2ray { - namespace ui { - namespace widgets { - class AutoCompleteTextEdit : public QPlainTextEdit { - Q_OBJECT - - public: - AutoCompleteTextEdit(const QString &prefix, const QStringList &sourceStrings, QWidget *parent = nullptr); - ~AutoCompleteTextEdit(); - - protected: - void keyPressEvent(QKeyEvent *e) override; - void focusInEvent(QFocusEvent *e) override; - - private slots: - void insertCompletion(const QString &completion); - - private: - QString lineUnderCursor() const; - QString wordUnderCursor() const; - - QString prefix; - QCompleter *c = nullptr; - }; - } // namespace widgets - } // namespace ui -} // namespace Qv2ray -using namespace Qv2ray::ui::widgets; diff --git a/3rdparty/qv2ray/v2/ui/widgets/common/QJsonModel.cpp b/3rdparty/qv2ray/v2/ui/widgets/common/QJsonModel.cpp deleted file mode 100644 index 54cb9fe..0000000 --- a/3rdparty/qv2ray/v2/ui/widgets/common/QJsonModel.cpp +++ /dev/null @@ -1,336 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2011 SCHUTZ Sacha - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "QJsonModel.hpp" - -#include -#include - -QJsonTreeItem::QJsonTreeItem(QJsonTreeItem *parent) { - mParent = parent; -} - -QJsonTreeItem::~QJsonTreeItem() { - qDeleteAll(mChilds); -} - -void QJsonTreeItem::appendChild(QJsonTreeItem *item) { - mChilds.append(item); -} - -QJsonTreeItem *QJsonTreeItem::child(int row) { - return mChilds.value(row); -} - -QJsonTreeItem *QJsonTreeItem::parent() { - return mParent; -} - -int QJsonTreeItem::childCount() const { - return mChilds.count(); -} - -int QJsonTreeItem::row() const { - if (mParent) - return mParent->mChilds.indexOf(const_cast(this)); - - return 0; -} - -void QJsonTreeItem::setKey(const QString &key) { - mKey = key; -} - -void QJsonTreeItem::setValue(const QString &value) { - mValue = value; -} - -void QJsonTreeItem::setType(const QJsonValue::Type &type) { - mType = type; -} - -QString QJsonTreeItem::key() const { - return mKey; -} - -QString QJsonTreeItem::value() const { - return mValue; -} - -QJsonValue::Type QJsonTreeItem::type() const { - return mType; -} - -QJsonTreeItem *QJsonTreeItem::load(const QJsonValue &value, QJsonTreeItem *parent) { - QJsonTreeItem *rootItem = new QJsonTreeItem(parent); - rootItem->setKey("root"); - - if (value.isObject()) { - // Get all QJsonValue childs - for (QString key: value.toObject().keys()) { - QJsonValue v = value.toObject().value(key); - QJsonTreeItem *child = load(v, rootItem); - child->setKey(key); - child->setType(v.type()); - rootItem->appendChild(child); - } - } else if (value.isArray()) { - // Get all QJsonValue childs - int index = 0; - - for (QJsonValue v: value.toArray()) { - QJsonTreeItem *child = load(v, rootItem); - child->setKey(QString::number(index)); - child->setType(v.type()); - rootItem->appendChild(child); - ++index; - } - } else { - rootItem->setValue(value.toVariant().toString()); - rootItem->setType(value.type()); - } - - return rootItem; -} - -//========================================================================= - -QJsonModel::QJsonModel(QObject *parent) : QAbstractItemModel(parent), mRootItem{new QJsonTreeItem} { - mHeaders.append("key"); - mHeaders.append("value"); -} - -QJsonModel::QJsonModel(const QString &fileName, QObject *parent) : QAbstractItemModel(parent), mRootItem{new QJsonTreeItem} { - mHeaders.append("key"); - mHeaders.append("value"); - load(fileName); -} - -QJsonModel::QJsonModel(QIODevice *device, QObject *parent) : QAbstractItemModel(parent), mRootItem{new QJsonTreeItem} { - mHeaders.append("key"); - mHeaders.append("value"); - load(device); -} - -QJsonModel::QJsonModel(const QByteArray &json, QObject *parent) : QAbstractItemModel(parent), mRootItem{new QJsonTreeItem} { - mHeaders.append("key"); - mHeaders.append("value"); - loadJson(json); -} - -QJsonModel::~QJsonModel() { - delete mRootItem; -} - -bool QJsonModel::load(const QString &fileName) { - QFile file(fileName); - bool success = false; - - if (file.open(QIODevice::ReadOnly)) { - success = load(&file); - file.close(); - } else - success = false; - - return success; -} - -bool QJsonModel::load(QIODevice *device) { - return loadJson(device->readAll()); -} - -bool QJsonModel::loadJson(const QByteArray &json) { - auto const &jdoc = QJsonDocument::fromJson(json); - - if (!jdoc.isNull()) { - beginResetModel(); - delete mRootItem; - - if (jdoc.isArray()) { - mRootItem = QJsonTreeItem::load(QJsonValue(jdoc.array())); - mRootItem->setType(QJsonValue::Array); - } else { - mRootItem = QJsonTreeItem::load(QJsonValue(jdoc.object())); - mRootItem->setType(QJsonValue::Object); - } - - endResetModel(); - return true; - } - - qDebug() << Q_FUNC_INFO << "cannot load json"; - return false; -} - -QVariant QJsonModel::data(const QModelIndex &index, int role) const { - if (!index.isValid()) - return QVariant(); - - QJsonTreeItem *item = static_cast(index.internalPointer()); - - if (role == Qt::DisplayRole) { - if (index.column() == 0) - return QStringLiteral("%1").arg(item->key()); - - if (index.column() == 1) - return QStringLiteral("%1").arg(item->value()); - } else if (Qt::EditRole == role) { - if (index.column() == 1) { - return QStringLiteral("%1").arg(item->value()); - } - } - - return QVariant(); -} - -bool QJsonModel::setData(const QModelIndex &index, const QVariant &value, int role) { - int col = index.column(); - - if (Qt::EditRole == role) { - if (col == 1) { - QJsonTreeItem *item = static_cast(index.internalPointer()); - item->setValue(value.toString()); - emit dataChanged(index, index, {Qt::EditRole}); - return true; - } - } - - return false; -} - -QVariant QJsonModel::headerData(int section, Qt::Orientation orientation, int role) const { - if (role != Qt::DisplayRole) - return QVariant(); - - if (orientation == Qt::Horizontal) { - return mHeaders.value(section); - } else - return QVariant(); -} - -QModelIndex QJsonModel::index(int row, int column, const QModelIndex &parent) const { - if (!hasIndex(row, column, parent)) - return QModelIndex(); - - QJsonTreeItem *parentItem; - - if (!parent.isValid()) - parentItem = mRootItem; - else - parentItem = static_cast(parent.internalPointer()); - - QJsonTreeItem *childItem = parentItem->child(row); - - if (childItem) - return createIndex(row, column, childItem); - else - return QModelIndex(); -} - -QModelIndex QJsonModel::parent(const QModelIndex &index) const { - if (!index.isValid()) - return QModelIndex(); - - QJsonTreeItem *childItem = static_cast(index.internalPointer()); - QJsonTreeItem *parentItem = childItem->parent(); - - if (parentItem == mRootItem) - return QModelIndex(); - - return createIndex(parentItem->row(), 0, parentItem); -} - -int QJsonModel::rowCount(const QModelIndex &parent) const { - QJsonTreeItem *parentItem; - - if (parent.column() > 0) - return 0; - - if (!parent.isValid()) - parentItem = mRootItem; - else - parentItem = static_cast(parent.internalPointer()); - - return parentItem->childCount(); -} - -int QJsonModel::columnCount(const QModelIndex &parent) const { - Q_UNUSED(parent) - return 2; -} - -Qt::ItemFlags QJsonModel::flags(const QModelIndex &index) const { - int col = index.column(); - auto item = static_cast(index.internalPointer()); - auto isArray = QJsonValue::Array == item->type(); - auto isObject = QJsonValue::Object == item->type(); - - if ((col == 1) && !(isArray || isObject)) { - return Qt::ItemIsEditable | QAbstractItemModel::flags(index); - } else { - return QAbstractItemModel::flags(index); - } -} - -QJsonDocument QJsonModel::json() const { - auto v = genJson(mRootItem); - QJsonDocument doc; - - if (v.isObject()) { - doc = QJsonDocument(v.toObject()); - } else { - doc = QJsonDocument(v.toArray()); - } - - return doc; -} - -QJsonValue QJsonModel::genJson(QJsonTreeItem *item) const { - auto type = item->type(); - int nchild = item->childCount(); - - if (QJsonValue::Object == type) { - QJsonObject jo; - - for (int i = 0; i < nchild; ++i) { - auto ch = item->child(i); - auto key = ch->key(); - jo.insert(key, genJson(ch)); - } - - return jo; - } else if (QJsonValue::Array == type) { - QJsonArray arr; - - for (int i = 0; i < nchild; ++i) { - auto ch = item->child(i); - arr.append(genJson(ch)); - } - - return arr; - } else { - QJsonValue va(item->value()); - return va; - } -} diff --git a/3rdparty/qv2ray/v2/ui/widgets/common/QJsonModel.hpp b/3rdparty/qv2ray/v2/ui/widgets/common/QJsonModel.hpp deleted file mode 100644 index d24979a..0000000 --- a/3rdparty/qv2ray/v2/ui/widgets/common/QJsonModel.hpp +++ /dev/null @@ -1,92 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2011 SCHUTZ Sacha - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -class QJsonModel; -class QJsonItem; - -class QJsonTreeItem { -public: - QJsonTreeItem(QJsonTreeItem *parent = nullptr); - ~QJsonTreeItem(); - void appendChild(QJsonTreeItem *item); - QJsonTreeItem *child(int row); - QJsonTreeItem *parent(); - int childCount() const; - int row() const; - void setKey(const QString &key); - void setValue(const QString &value); - void setType(const QJsonValue::Type &type); - QString key() const; - QString value() const; - QJsonValue::Type type() const; - - static QJsonTreeItem *load(const QJsonValue &value, QJsonTreeItem *parent = 0); - -protected: -private: - QString mKey; - QString mValue; - QJsonValue::Type mType; - QList mChilds; - QJsonTreeItem *mParent; -}; - -//--------------------------------------------------- - -class QJsonModel : public QAbstractItemModel { - Q_OBJECT -public: - explicit QJsonModel(QObject *parent = nullptr); - QJsonModel(const QString &fileName, QObject *parent = nullptr); - QJsonModel(QIODevice *device, QObject *parent = nullptr); - QJsonModel(const QByteArray &json, QObject *parent = nullptr); - ~QJsonModel(); - bool load(const QString &fileName); - bool load(QIODevice *device); - bool loadJson(const QByteArray &json); - QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE; - bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) Q_DECL_OVERRIDE; - QVariant headerData(int section, Qt::Orientation orientation, int role) const Q_DECL_OVERRIDE; - QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; - QModelIndex parent(const QModelIndex &index) const Q_DECL_OVERRIDE; - int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; - int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; - Qt::ItemFlags flags(const QModelIndex &index) const Q_DECL_OVERRIDE; - QJsonDocument json() const; - -private: - QJsonValue genJson(QJsonTreeItem *) const; - - QJsonTreeItem *mRootItem; - QStringList mHeaders; -}; diff --git a/3rdparty/qv2ray/v2/ui/widgets/editors/w_JsonEditor.cpp b/3rdparty/qv2ray/v2/ui/widgets/editors/w_JsonEditor.cpp deleted file mode 100644 index 2eb6bdb..0000000 --- a/3rdparty/qv2ray/v2/ui/widgets/editors/w_JsonEditor.cpp +++ /dev/null @@ -1,97 +0,0 @@ -#include "w_JsonEditor.hpp" - -#include "main/NekoGui.hpp" - -JsonEditor::JsonEditor(const QJsonObject& rootObject, QWidget* parent) : QDialog(parent) { - setupUi(this); - // QvMessageBusConnect(JsonEditor); - // - original = rootObject; - final = rootObject; - QString jsonString = JsonToString(rootObject); - - if (VerifyJsonString(jsonString).isEmpty()) { - jsonTree->setModel(&model); - model.loadJson(QJsonDocument(rootObject).toJson()); - } else { - QvMessageBoxWarn(this, tr("Json Contains Syntax Errors"), - tr("Original Json may contain syntax errors. Json tree is disabled.")); - } - - jsonEditor->setText(JsonToString(rootObject)); - jsonTree->expandAll(); - jsonTree->resizeColumnToContents(0); -} - -// QvMessageBusSlotImpl(JsonEditor) -// { -// switch (msg) -// { -// MBShowDefaultImpl; -// MBHideDefaultImpl; -// MBRetranslateDefaultImpl; -// case UPDATE_COLORSCHEME: -// break; -// } -// } - -QJsonObject JsonEditor::OpenEditor() { - int resultCode = this->exec(); - auto string = jsonEditor->toPlainText(); - - while (resultCode == QDialog::Accepted && !VerifyJsonString(string).isEmpty()) { - if (string.isEmpty()) { - resultCode = QDialog::Accepted; - final = {}; - break; - } - QvMessageBoxWarn(this, tr("Json Contains Syntax Errors"), - tr("You must correct these errors before continuing.")); - resultCode = this->exec(); - string = jsonEditor->toPlainText(); - } - - return resultCode == QDialog::Accepted ? final : original; -} - -JsonEditor::~JsonEditor() { -} - -void JsonEditor::on_jsonEditor_textChanged() { - auto string = jsonEditor->toPlainText(); - auto VerifyResult = VerifyJsonString(string); - jsonValidateStatus->setText(VerifyResult); - - if (VerifyResult.isEmpty()) { - BLACK(jsonEditor); - final = JsonFromString(string); - model.loadJson(QJsonDocument(final).toJson()); - jsonTree->expandAll(); - jsonTree->resizeColumnToContents(0); - } else { - RED(jsonEditor); - } -} - -void JsonEditor::on_formatJsonBtn_clicked() { - auto string = jsonEditor->toPlainText(); - auto VerifyResult = VerifyJsonString(string); - jsonValidateStatus->setText(VerifyResult); - - if (VerifyResult.isEmpty()) { - BLACK(jsonEditor); - jsonEditor->setPlainText(JsonToString(JsonFromString(string))); - model.loadJson(QJsonDocument(JsonFromString(string)).toJson()); - jsonTree->setModel(&model); - jsonTree->expandAll(); - jsonTree->resizeColumnToContents(0); - } else { - RED(jsonEditor); - QvMessageBoxWarn(this, tr("Syntax Errors"), - tr("Please fix the JSON errors or remove the comments before continue")); - } -} - -void JsonEditor::on_removeCommentsBtn_clicked() { - jsonEditor->setPlainText(JsonToString(JsonFromString(jsonEditor->toPlainText()))); -} diff --git a/3rdparty/qv2ray/v2/ui/widgets/editors/w_JsonEditor.hpp b/3rdparty/qv2ray/v2/ui/widgets/editors/w_JsonEditor.hpp deleted file mode 100644 index ea08afa..0000000 --- a/3rdparty/qv2ray/v2/ui/widgets/editors/w_JsonEditor.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include "3rdparty/qv2ray/wrapper.hpp" -#include "3rdparty/qv2ray/v2/ui/widgets/common/QJsonModel.hpp" -#include "ui_w_JsonEditor.h" - -#include - -class JsonEditor - : public QDialog, - private Ui::JsonEditor { - Q_OBJECT - -public: - explicit JsonEditor(const QJsonObject& rootObject, QWidget* parent = nullptr); - ~JsonEditor(); - QJsonObject OpenEditor(); - -private slots: - void on_jsonEditor_textChanged(); - - void on_formatJsonBtn_clicked(); - - void on_removeCommentsBtn_clicked(); - -private: - QJsonModel model; - QJsonObject original; - QJsonObject final; -}; diff --git a/3rdparty/qv2ray/v2/ui/widgets/editors/w_JsonEditor.ui b/3rdparty/qv2ray/v2/ui/widgets/editors/w_JsonEditor.ui deleted file mode 100644 index 51dcd76..0000000 --- a/3rdparty/qv2ray/v2/ui/widgets/editors/w_JsonEditor.ui +++ /dev/null @@ -1,172 +0,0 @@ - - - JsonEditor - - - Qt::ApplicationModal - - - - 0 - 0 - 889 - 572 - - - - JSON Editor - - - true - - - - - - Qt::Horizontal - - - false - - - - - - - - Monospace - - - - QTextEdit::NoWrap - - - false - - - - - - - Format JSON - - - - - - - Remove All Comments - - - - - - - Json Editor - - - - - - - - - - - Structure Preview - - - - - - - QAbstractItemView::NoEditTriggers - - - true - - - 15 - - - true - - - true - - - true - - - 132 - - - 152 - - - - - - - - - - - OK - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - jsonEditor - formatJsonBtn - removeCommentsBtn - jsonTree - - - - - buttonBox - accepted() - JsonEditor - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - JsonEditor - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/3rdparty/qv2ray/v3/components/GeositeReader/GeositeReader.cpp b/3rdparty/qv2ray/v3/components/GeositeReader/GeositeReader.cpp deleted file mode 100644 index 562e986..0000000 --- a/3rdparty/qv2ray/v3/components/GeositeReader/GeositeReader.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "GeositeReader.hpp" - -#include "3rdparty/qv2ray/wrapper.hpp" -#include "picoproto.hpp" - -#include -#include - -namespace Qv2ray::components::GeositeReader { - QMap GeositeEntries; - - QStringList ReadGeoSiteFromFile(const QString &filepath, bool allowCache) { - if (GeositeEntries.contains(filepath) && allowCache) - return GeositeEntries.value(filepath); - - QStringList list; - qInfo() << "Reading geosites from:" << filepath; - QFile f(filepath); - bool opened = f.open(QFile::OpenModeFlag::ReadOnly); - - if (!opened) { - qInfo() << "File cannot be opened:" << filepath; - return list; - } - - const auto content = f.readAll(); - f.close(); - { - picoproto::Message root; - root.ParseFromBytes((unsigned char *) content.data(), content.size()); - - list.reserve(root.GetMessageArray(1).size()); - for (const auto &geosite: root.GetMessageArray(1)) - list << QString::fromStdString(geosite->GetString(1)); - } - - qInfo() << "Loaded" << list.count() << "geosite entries from data file."; - list.sort(); - GeositeEntries[filepath] = list; - return list; - } -} // namespace Qv2ray::components::GeositeReader diff --git a/3rdparty/qv2ray/v3/components/GeositeReader/GeositeReader.hpp b/3rdparty/qv2ray/v3/components/GeositeReader/GeositeReader.hpp deleted file mode 100644 index 8bafd6d..0000000 --- a/3rdparty/qv2ray/v3/components/GeositeReader/GeositeReader.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include - -namespace Qv2ray::components::GeositeReader { - QStringList ReadGeoSiteFromFile(const QString &filepath, bool allowCache = true); -} // namespace Qv2ray::components::GeositeReader diff --git a/3rdparty/qv2ray/v3/components/GeositeReader/picoproto.cpp b/3rdparty/qv2ray/v3/components/GeositeReader/picoproto.cpp deleted file mode 100644 index 786c1fd..0000000 --- a/3rdparty/qv2ray/v3/components/GeositeReader/picoproto.cpp +++ /dev/null @@ -1,551 +0,0 @@ -/* Copyright 2016 Pete Warden. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - ==============================================================================*/ - -#include "picoproto.hpp" - -namespace picoproto { - - namespace { - - // To keep the dependencies down, here's a local copy of the widespread bit_cast - // operator. This is necessary because in practice weird things can happen if - // you just try to use reinterpret_cast. - template - inline Dest bit_cast(const Source &source) { - static_assert(sizeof(Dest) == sizeof(Source), "Sizes do not match"); - Dest dest; - memcpy(&dest, &source, sizeof(dest)); - return dest; - } - - // These are defined in: - // https://developers.google.com/protocol-buffers/docs/encoding - enum WireType { - WIRETYPE_VARINT = 0, - WIRETYPE_64BIT = 1, - WIRETYPE_LENGTH_DELIMITED = 2, - WIRETYPE_GROUP_START = 3, - WIRETYPE_GROUP_END = 4, - WIRETYPE_32BIT = 5, - }; - - // Pull bytes from the stream, updating the state. - bool ConsumeBytes(uint8_t **current, size_t how_many, size_t *remaining) { - if (how_many > *remaining) { - PP_LOG(ERROR) << "ReadBytes overrun!"; - return false; - } - *current += how_many; - *remaining -= how_many; - return true; - } - - // Grabs a particular type from the byte stream. - template - T ReadFromBytes(uint8_t **current, size_t *remaining) { - PP_CHECK(ConsumeBytes(current, sizeof(T), remaining)); - const T result = *(bit_cast(*current - sizeof(T))); - return result; - } - - uint64_t ReadVarInt(uint8_t **current, size_t *remaining) { - uint64_t result = 0; - bool keep_going; - int shift = 0; - do { - const uint8_t next_number = ReadFromBytes(current, remaining); - keep_going = (next_number >= 128); - result += (uint64_t) (next_number & 0x7f) << shift; - shift += 7; - } while (keep_going); - return result; - } - - void ReadWireTypeAndFieldNumber(uint8_t **current, size_t *remaining, uint8_t *wire_type, uint32_t *field_number) { - uint64_t wire_type_and_field_number = ReadVarInt(current, remaining); - *wire_type = wire_type_and_field_number & 0x07; - *field_number = wire_type_and_field_number >> 3; - } - - } // namespace - - std::string FieldTypeDebugString(enum FieldType type) { - switch (type) { - case FIELD_UNSET: - return "UNSET"; - break; - case FIELD_UINT32: - return "UINT32"; - break; - case FIELD_UINT64: - return "UINT64"; - break; - case FIELD_BYTES: - return "BYTES"; - break; - default: - return "Unknown field type"; - break; - } - return "Should never get here"; - } - - Field::Field(FieldType type, bool owns_data) : type(type), owns_data(owns_data) { - cached_messages = nullptr; - switch (type) { - case FIELD_UINT32: { - value.v_uint32 = new std::vector(); - } break; - case FIELD_UINT64: { - value.v_uint64 = new std::vector(); - } break; - case FIELD_BYTES: { - value.v_bytes = new std::vector>(); - cached_messages = new std::vector(); - } break; - default: { - PP_LOG(ERROR) << "Bad field type when constructing field: " << type; - } break; - } - } - - Field::Field(const Field &other) : type(other.type), owns_data(other.owns_data) { - switch (type) { - case FIELD_UINT32: { - value.v_uint32 = new std::vector(*other.value.v_uint32); - } break; - case FIELD_UINT64: { - value.v_uint64 = new std::vector(*other.value.v_uint64); - } break; - case FIELD_BYTES: { - if (owns_data) { - value.v_bytes = new std::vector>(); - for (std::pair data_info: *other.value.v_bytes) { - uint8_t *new_data = new uint8_t[data_info.second]; - std::copy_n(data_info.first, data_info.second, new_data); - value.v_bytes->push_back({new_data, data_info.second}); - } - } else { - value.v_bytes = new std::vector>(*other.value.v_bytes); - } - cached_messages = new std::vector(); - cached_messages->reserve(other.cached_messages->size()); - for (Message *other_cached_message: *other.cached_messages) { - Message *cached_message; - if (other_cached_message) { - cached_message = new Message(*other_cached_message); - } else { - cached_message = nullptr; - } - cached_messages->push_back(cached_message); - } - } break; - default: { - PP_LOG(ERROR) << "Bad field type when constructing field: " << type; - } break; - } - } - - Field::~Field() { - switch (type) { - case FIELD_UINT32: - delete value.v_uint32; - break; - case FIELD_UINT64: - delete value.v_uint64; - break; - case FIELD_BYTES: { - if (owns_data) - for (std::pair data_info: *value.v_bytes) - delete[] data_info.first; - delete value.v_bytes; - - for (Message *cached_message: *cached_messages) - if (cached_message) - delete cached_message; - delete cached_messages; - break; - } - default: - PP_LOG(ERROR) << "Bad field type when destroying field: " << type; - break; - } - } - - Message::Message() : Message(true){}; - - Message::Message(bool copy_arrays) : copy_arrays(copy_arrays){}; - - Message::Message(const Message &other) : field_map(other.field_map), fields(other.fields), copy_arrays(other.copy_arrays){}; - - Message::~Message(){}; - - bool Message::ParseFromBytes(uint8_t *bytes, size_t bytes_size) { - uint8_t *current = bytes; - size_t remaining = bytes_size; - while (remaining > 0) { - uint8_t wire_type; - uint32_t field_number; - ReadWireTypeAndFieldNumber(¤t, &remaining, &wire_type, &field_number); - switch (wire_type) { - case WIRETYPE_VARINT: { - Field *field = AddField(field_number, FIELD_UINT64); - const uint64_t varint = ReadVarInt(¤t, &remaining); - field->value.v_uint64->push_back(varint); - break; - } - case WIRETYPE_64BIT: { - Field *field = AddField(field_number, FIELD_UINT64); - const uint64_t value = ReadFromBytes(¤t, &remaining); - field->value.v_uint64->push_back(value); - break; - } - case WIRETYPE_LENGTH_DELIMITED: { - Field *field = AddField(field_number, FIELD_BYTES); - const uint64_t size = ReadVarInt(¤t, &remaining); - uint8_t *data; - if (copy_arrays) { - data = new uint8_t[size]; - std::copy_n(current, size, data); - field->owns_data = true; - } else { - data = current; - field->owns_data = false; - } - field->value.v_bytes->push_back({data, size}); - field->cached_messages->push_back(nullptr); - current += size; - remaining -= size; - break; - } - case WIRETYPE_GROUP_START: { - PP_LOG(INFO) << field_number << ": GROUPSTART" << std::endl; - PP_LOG(ERROR) << "Unhandled wire type encountered"; - break; - } - case WIRETYPE_GROUP_END: { - PP_LOG(INFO) << field_number << ": GROUPEND" << std::endl; - PP_LOG(ERROR) << "Unhandled wire type encountered"; - break; - } - case WIRETYPE_32BIT: { - Field *field = AddField(field_number, FIELD_UINT32); - const uint32_t value = ReadFromBytes(¤t, &remaining); - field->value.v_uint32->push_back(value); - break; - } - default: { - PP_LOG(ERROR) << "Unknown wire type encountered: " << static_cast(wire_type) << " at offset" << (bytes_size - remaining); - return false; - break; - } - } - } - return true; - } - - Field *Message::AddField(int32_t number, enum FieldType type) { - Field *field = GetField(number); - if (!field) { - fields.push_back(Field(type, copy_arrays)); - field = &fields.back(); - field_map.insert({number, fields.size() - 1}); - } - return field; - } - - Field *Message::GetField(int32_t number) { - if (field_map.count(number) == 0) - return nullptr; - return &(fields[field_map[number]]); - } - - Field *Message::GetFieldAndCheckType(int32_t number, enum FieldType type) { - Field *field = GetField(number); - PP_CHECK(field) << "No field for " << number; - PP_CHECK(field->type == type) << "For field " << number << " wanted type " << FieldTypeDebugString(type) << " but found " << FieldTypeDebugString(field->type); - return field; - } - - int32_t Message::GetInt32(int32_t number) { - Field *field = GetFieldAndCheckType(number, FIELD_UINT32); - uint32_t first_value = (*(field->value.v_uint32))[0]; - int32_t zig_zag_decoded = static_cast((first_value >> 1) ^ (-(first_value & 1))); - return zig_zag_decoded; - } - - int64_t Message::GetInt64(int32_t number) { - Field *field = GetFieldAndCheckType(number, FIELD_UINT64); - uint64_t first_value = (*(field->value.v_uint64))[0]; - int64_t zig_zag_decoded = static_cast((first_value >> 1) ^ (-(first_value & 1))); - return zig_zag_decoded; - } - - uint32_t Message::GetUInt32(int32_t number) { - Field *field = GetFieldAndCheckType(number, FIELD_UINT32); - uint32_t first_value = (*(field->value.v_uint32))[0]; - return first_value; - } - - uint64_t Message::GetUInt64(int32_t number) { - Field *field = GetFieldAndCheckType(number, FIELD_UINT64); - uint64_t first_value = (*(field->value.v_uint64))[0]; - return first_value; - } - - int64_t Message::GetInt(int32_t number) { - Field *field = GetField(number); - PP_CHECK(field) << "No field for " << number; - PP_CHECK((field->type == FIELD_UINT32) || (field->type == FIELD_UINT64)) - << "For field " << number << " wanted integer type but found " << FieldTypeDebugString(field->type); - switch (field->type) { - case FIELD_UINT32: - return GetInt32(number); - break; - case FIELD_UINT64: - return GetInt64(number); - break; - default: { - // Should never get here. - } break; - } - // Should never get here. - return 0; - } - - bool Message::GetBool(int32_t number) { - return (GetInt(number) != 0); - } - - float Message::GetFloat(int32_t number) { - uint32_t int_value = GetUInt32(number); - float float_value = *(bit_cast(&int_value)); - return float_value; - } - - double Message::GetDouble(int32_t number) { - uint64_t int_value = GetUInt64(number); - return *(bit_cast(&int_value)); - } - - std::pair Message::GetBytes(int32_t number) { - Field *field = GetFieldAndCheckType(number, FIELD_BYTES); - std::pair first_value = (*(field->value.v_bytes))[0]; - return first_value; - } - - std::string Message::GetString(int32_t number) { - Field *field = GetFieldAndCheckType(number, FIELD_BYTES); - std::pair first_value = (*(field->value.v_bytes))[0]; - std::string result(first_value.first, first_value.first + first_value.second); - return result; - } - - Message *Message::GetMessage(int32_t number) { - Field *field = GetFieldAndCheckType(number, FIELD_BYTES); - Message *cached_message = field->cached_messages->at(0); - if (!cached_message) { - std::pair first_value = (*(field->value.v_bytes))[0]; - cached_message = new Message(copy_arrays); - cached_message->ParseFromBytes(first_value.first, first_value.second); - field->cached_messages->at(0) = cached_message; - } - return cached_message; - } - - std::vector Message::GetInt32Array(int32_t number) { - std::vector raw_array = GetUInt64Array(number); - std::vector result; - result.reserve(raw_array.size()); - for (uint64_t raw_value: raw_array) { - int32_t zig_zag_decoded = static_cast((raw_value >> 1) ^ (-(raw_value & 1))); - result.push_back(zig_zag_decoded); - } - return result; - } - - std::vector Message::GetInt64Array(int32_t number) { - std::vector raw_array = GetUInt64Array(number); - std::vector result; - result.reserve(raw_array.size()); - for (uint64_t raw_value: raw_array) { - int64_t zig_zag_decoded = static_cast((raw_value >> 1) ^ (-(raw_value & 1))); - result.push_back(zig_zag_decoded); - } - return result; - } - - std::vector Message::GetUInt32Array(int32_t number) { - std::vector raw_array = GetUInt64Array(number); - std::vector result; - result.reserve(raw_array.size()); - for (uint64_t raw_value: raw_array) { - result.push_back(static_cast(raw_value)); - } - return result; - } - - std::vector Message::GetUInt64Array(int32_t number) { - std::vector result; - Field *field = GetField(number); - if (!field) { - return result; - } - if (field->type == FIELD_UINT64) { - result.reserve(field->value.v_uint64->size()); - for (uint64_t value: *field->value.v_uint64) { - result.push_back(static_cast(value)); - } - } else if (field->type == FIELD_UINT32) { - result.reserve(field->value.v_uint32->size()); - for (uint32_t value: *field->value.v_uint32) { - result.push_back(static_cast(value)); - } - } else if (field->type == FIELD_BYTES) { - for (std::pair data_info: *field->value.v_bytes) { - uint8_t *current = data_info.first; - size_t remaining = data_info.second; - while (remaining > 0) { - const uint64_t varint = ReadVarInt(¤t, &remaining); - result.push_back(static_cast(varint)); - } - } - } else { - PP_LOG(ERROR) << "Expected field type UINT32, UINT64, or BYTES but got " << FieldTypeDebugString(field->type); - } - return result; - } - - std::vector Message::GetBoolArray(int32_t number) { - std::vector raw_array = GetUInt64Array(number); - std::vector result; - result.reserve(raw_array.size()); - for (uint64_t raw_value: raw_array) { - result.push_back(raw_value != 0); - } - return result; - } - - std::vector Message::GetFloatArray(int32_t number) { - std::vector result; - Field *field = GetField(number); - if (!field) { - return result; - } - if (field->type == FIELD_UINT32) { - result.reserve(field->value.v_uint32->size()); - for (uint32_t value: *field->value.v_uint32) { - result.push_back(bit_cast(value)); - } - } else if (field->type == FIELD_BYTES) { - for (std::pair data_info: *field->value.v_bytes) { - uint8_t *current = data_info.first; - size_t remaining = data_info.second; - while (remaining > 0) { - const uint64_t varint = ReadVarInt(¤t, &remaining); - const uint32_t varint32 = static_cast(varint & 0xffffffff); - result.push_back(bit_cast(varint32)); - } - } - } else { - PP_LOG(ERROR) << "Expected field type UINT32 or BYTES but got " << FieldTypeDebugString(field->type); - } - return result; - } - - std::vector Message::GetDoubleArray(int32_t number) { - std::vector result; - Field *field = GetField(number); - if (!field) { - return result; - } - if (field->type == FIELD_UINT64) { - result.reserve(field->value.v_uint64->size()); - for (uint64_t value: *field->value.v_uint64) { - result.push_back(bit_cast(value)); - } - } else if (field->type == FIELD_BYTES) { - for (std::pair data_info: *field->value.v_bytes) { - uint8_t *current = data_info.first; - size_t remaining = data_info.second; - while (remaining > 0) { - const uint64_t varint = ReadVarInt(¤t, &remaining); - result.push_back(bit_cast(varint)); - } - } - } else { - PP_LOG(ERROR) << "Expected field type UINT64 or BYTES but got " << FieldTypeDebugString(field->type); - } - return result; - } - - std::vector> Message::GetByteArray(int32_t number) { - std::vector> result; - Field *field = GetField(number); - if (!field) { - return result; - } - if (field->type == FIELD_BYTES) { - result.reserve(field->value.v_bytes->size()); - for (std::pair data_info: *field->value.v_bytes) { - result.push_back(data_info); - } - } else { - PP_LOG(ERROR) << "Expected field type BYTES but got " << FieldTypeDebugString(field->type); - } - return result; - } - - std::vector Message::GetStringArray(int32_t number) { - std::vector result; - Field *field = GetField(number); - if (!field) - return result; - if (field->type == FIELD_BYTES) { - result.reserve(field->value.v_bytes->size()); - for (std::pair data_info: *field->value.v_bytes) { - result.push_back(std::string(data_info.first, data_info.first + data_info.second)); - } - } else { - PP_LOG(ERROR) << "Expected field type BYTES but got " << FieldTypeDebugString(field->type); - } - return result; - } - - std::vector Message::GetMessageArray(int32_t number) { - std::vector result; - Field *field = GetField(number); - if (!field) - return result; - - if (field->type == FIELD_BYTES) { - result.reserve(field->value.v_bytes->size()); - for (size_t i = 0; i < field->value.v_bytes->size(); ++i) { - Message *cached_message = field->cached_messages->at(i); - if (!cached_message) { - std::pair value = field->value.v_bytes->at(i); - cached_message = new Message(copy_arrays); - cached_message->ParseFromBytes(value.first, value.second); - field->cached_messages->at(i) = cached_message; - } - result.push_back(cached_message); - } - } else { - PP_LOG(ERROR) << "Expected field type BYTES but got " << FieldTypeDebugString(field->type); - } - return result; - } - -} // namespace picoproto diff --git a/3rdparty/qv2ray/v3/components/GeositeReader/picoproto.hpp b/3rdparty/qv2ray/v3/components/GeositeReader/picoproto.hpp deleted file mode 100644 index 76a1b6e..0000000 --- a/3rdparty/qv2ray/v3/components/GeositeReader/picoproto.hpp +++ /dev/null @@ -1,208 +0,0 @@ -/* Copyright 2016 Pete Warden. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - ==============================================================================*/ - -/* - See the README for full details, but this module lets you read in protobuf - encoded files with a minimal code footprint. - - It doesn't create classes for each kind of message it encounters, it just has a - single Message interface that lets you access the members of the protobuf as a - key/value store. This loses a lot of the convenience of type-checked classes, - but it does mean that very little code is needed to access data from files. - - As a simple example, if you had read a `bytes_size` long file into `bytes` that - contained a TensorFlow GraphDef proto: - - Message graph_def; - graph_def.ParseFromBytes(bytes, bytes_size); - - You can then access the different fields of the GraphDef using the field - numbers assigned in the .proto file: - - std::vector nodes = graph_def.GetMessageArray(1); - - One big difference between this minimal approach and normal protobufs is that - the calling code has to already know the field number and type of any members - it's trying to access. Here I know that the `node` field is number 1, and that - it should contain a repeated list of NodeDefs. Since they are not primitive - types like numbers or strings, they are accessed as an array of Messages. - - Here are the design goals of this module: - - Keep the code size tiny (single-digit kilobytes on most platforms). - - Minimize memory usage (for example allow in-place references to byte data). - - Provide a simple, readable implementation that can be ported easily. - - Deserialize all saved protobuf files into a usable representation. - - No dependencies other than the standard C++ library. - - No build-time support (e.g. protoc) required. - - Here's what it's explicitly not offering: - - Providing a readable and transparent way of accessing serialized data. - - Saving out data to protobuf format. - -*/ - -#ifndef INCLUDE_PICOPROTO_H -#define INCLUDE_PICOPROTO_H - -#include -#include -#include -#include -#include -#include -#include -#include - -// To keep dependencies minimal, some bare-bones macros to make logging easier. -#define PP_LOG(X) PP_LOG_##X -#define PP_LOG_INFO std::cerr << __FILE__ << ":" << __LINE__ << " - INFO: " -#define PP_LOG_WARN std::cerr << __FILE__ << ":" << __LINE__ << " - WARN: " -#define PP_LOG_ERROR std::cerr << __FILE__ << ":" << __LINE__ << " - ERROR: " -#define PP_CHECK(X) \ - if (!(X)) \ - PP_LOG(ERROR) << "PP_CHECK(" << #X << ") failed. " - -namespace picoproto { - - // These roughly correspond to the wire types used to save data in protobuf - // files. The best reference to understand the full format is: - // https://developers.google.com/protocol-buffers/docs/encoding - // Because we don't know the bit-depth of VarInts, they're always stored as - // uint64 values, which is why there's no specific type for them. - enum FieldType { - FIELD_UNSET, - FIELD_UINT32, - FIELD_UINT64, - FIELD_BYTES, - }; - - // Gives a readable name for the field type for logging purposes. - std::string FieldTypeDebugString(enum FieldType type); - - // Forward declare the main message class, since fields can contain them. - class Message; - - // Fields are the building blocks of messages. They contain the values for each - // data member, and handle all the allocation and deallocation of storage. - // It's unlikely you'll want to access this class directly, since you'll - // normally want to use Message below to pull typed values. - class Field { - public: - // You need to specify the type of a Field on creation, so that the right - // storage can be set up for the values. You also need to indicate whether the - // underlying memory will be around for the lifetime of the message (in which - // case no copies are needed) or whether the class should make copies and take - // ownership in case the data goes away. - Field(FieldType type, bool owns_data); - Field(const Field &other); - ~Field(); - - enum FieldType type; - // I know, this isn't very OOP, but the simplicity of keeping track of a type - // and deciding how to initialize and access the data based on that persuaded - // me this was the best approach. The `value` member contains whatever data - // the field should be holding. - union { - std::vector *v_uint32; - std::vector *v_uint64; - std::vector> *v_bytes; - } value; - // One of the drawbacks of not requiring .proto files ahead of time is that I - // don't know if a length-delimited field contains raw bytes, strings, or - // sub-messages. The only time we know that a field should be interpreted as a - // message is when client code requests it in that form. Because parsing can - // be costly, here we cache the results of any such calls for subsequent - // accesses. - std::vector *cached_messages; - // If this is set, then the object will allocate its own storage for - // length-delimited values, and copy from the input stream. If you know the - // underlying data will be around for the lifetime of the message, you can - // save memory and copies by leaving this as false. - bool owns_data; - }; - - // The main interface for loading and accessing serialized protobuf data. - class Message { - public: - // If you're not sure about the lifetime of any binary data you're reading - // from, just call this default constructor. - Message(); - // In the case when you're sure the lifetime of the byte stream you'll be - // decoding is longer than the lifetime of the message, you can set - // copy_arrays to false. This is especially useful if you have a memory - // mapped file to read from containing large binary blobs, since you'll skip - // a lot of copying and extra allocation. - Message(bool copy_arrays); - Message(const Message &other); - ~Message(); - - // Populates fields with all of the data from this stream of bytes. - // You can call this repeatedly with new messages, and the results will be - // merged together. - bool ParseFromBytes(uint8_t *binary, size_t binary_size); - - // These are the accessor functions if you're expecting exactly one value in a - // field. As discussed above, the burden is on the client code to know the - // field number and type of each member it's trying to access, and so pick the - // correct accessor function. - // If the field isn't present, this will raise an error, so if it's optional - // you should use the array accessors below. - int32_t GetInt32(int32_t number); - int64_t GetInt64(int32_t number); - uint32_t GetUInt32(int32_t number); - uint64_t GetUInt64(int32_t number); - int64_t GetInt(int32_t number); - bool GetBool(int32_t number); - float GetFloat(int32_t number); - double GetDouble(int32_t number); - std::pair GetBytes(int32_t number); - std::string GetString(int32_t number); - Message *GetMessage(int32_t number); - - // If you're not sure if a value will be present, or if it is repeated, you - // should call these array functions. If no such field has been seen, then the - // result will be an empty vector, otherwise you'll get back one or more - // entries. - std::vector GetInt32Array(int32_t number); - std::vector GetInt64Array(int32_t number); - std::vector GetUInt32Array(int32_t number); - std::vector GetUInt64Array(int32_t number); - std::vector GetBoolArray(int32_t number); - std::vector GetFloatArray(int32_t number); - std::vector GetDoubleArray(int32_t number); - std::vector> GetByteArray(int32_t number); - std::vector GetStringArray(int32_t number); - std::vector GetMessageArray(int32_t number); - - // It's unlikely you'll want to access fields directly, but here's an escape - // hatch in case you do have to manipulate them more directly. - Field *GetField(int32_t number); - - private: - // Inserts a new field, updating all the internal data structures. - Field *AddField(int32_t number, enum FieldType type); - - Field *GetFieldAndCheckType(int32_t number, enum FieldType type); - - // Maps from a field number to an index in the `fields` vector. - std::map field_map; - // The core list of fields that have been parsed. - std::vector fields; - bool copy_arrays; - }; - -} // namespace picoproto - -#endif // INCLUDE_PICOPROTO_H diff --git a/3rdparty/qv2ray/wrapper.hpp b/3rdparty/qv2ray/wrapper.hpp deleted file mode 100644 index 3a2cc38..0000000 --- a/3rdparty/qv2ray/wrapper.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -// Qv2ray wrapper - -#include -#include - -#define LOG(...) Qv2ray::base::log_internal(__VA_ARGS__) -#define DEBUG(...) Qv2ray::base::log_internal(__VA_ARGS__) -namespace Qv2ray { - namespace base { - template - inline void log_internal(T... v) {} - } // namespace base -} // namespace Qv2ray - -#define JsonToString(a) QJsonObject2QString(a, false) -#define JsonFromString(a) QString2QJsonObject(a) -#define QvMessageBoxWarn(a, b, c) MessageBoxWarning(b, c) - -inline QString VerifyJsonString(const QString &source) { - QJsonParseError error{}; - QJsonDocument doc = QJsonDocument::fromJson(source.toUtf8(), &error); - Q_UNUSED(doc) - - if (error.error == QJsonParseError::NoError) { - return ""; - } else { - // LOG("WARNING: Json parse returns: " + error.errorString()); - return error.errorString(); - } -} - -#define RED(obj) \ - { \ - auto _temp = obj->palette(); \ - _temp.setColor(QPalette::Text, Qt::red); \ - obj->setPalette(_temp); \ - } - -#define BLACK(obj) obj->setPalette(QWidget::palette()); diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index 7321c0f..0000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,302 +0,0 @@ -cmake_minimum_required(VERSION 3.5) - -project(nekobox VERSION 0.1 LANGUAGES CXX) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED ON) - -# WINDOWS PDB FILE -if (WIN32) - if (MSVC) - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi") - set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DEBUG /OPT:REF /OPT:ICF") - endif () -endif () - -# Find Qt -if (NOT QT_VERSION_MAJOR) - set(QT_VERSION_MAJOR 5) -endif () -find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets Network Svg LinguistTools) - -if (NKR_CROSS) - set_property(TARGET Qt5::moc PROPERTY IMPORTED_LOCATION /usr/bin/moc) - set_property(TARGET Qt5::uic PROPERTY IMPORTED_LOCATION /usr/bin/uic) - set_property(TARGET Qt5::rcc PROPERTY IMPORTED_LOCATION /usr/bin/rcc) - set_property(TARGET Qt5::lrelease PROPERTY IMPORTED_LOCATION /usr/bin/lrelease) - set_property(TARGET Qt5::lupdate PROPERTY IMPORTED_LOCATION /usr/bin/lupdate) -endif () - -#### Platform Variables #### -if (WIN32) - include("cmake/windows/windows.cmake") -else () - include("cmake/linux/linux.cmake") -endif () - -#### default prefix path #### - -if (NOT NKR_LIBS) - if (NKR_PACKAGE) - list(APPEND NKR_LIBS ${CMAKE_SOURCE_DIR}/libs/deps/package) - else () - list(APPEND NKR_LIBS ${CMAKE_SOURCE_DIR}/libs/deps/built) - endif () -endif () - -if (NOT NKR_DISABLE_LIBS) - list(APPEND CMAKE_PREFIX_PATH ${NKR_LIBS}) -endif () - -message("[CMAKE_PREFIX_PATH] ${CMAKE_PREFIX_PATH}") - -# for some cross toolchain -list(APPEND CMAKE_FIND_ROOT_PATH ${CMAKE_PREFIX_PATH}) -message("[CMAKE_FIND_ROOT_PATH] ${CMAKE_FIND_ROOT_PATH}") - -#### NKR #### - -include("cmake/print.cmake") -include("cmake/nkr.cmake") - -find_package(Threads) - -#### NKR EXTERNAL #### - -if (NKR_NO_EXTERNAL) - set(NKR_NO_GRPC 1) - set(NKR_NO_YAML 1) - set(NKR_NO_ZXING 1) - set(NKR_NO_QHOTKEY 1) -endif () - -# grpc -if (NKR_NO_GRPC) - nkr_add_compile_definitions(NKR_NO_GRPC) -else () - # My proto - include("cmake/myproto.cmake") - list(APPEND NKR_EXTERNAL_TARGETS myproto) -endif () - -# yaml-cpp -if (NKR_NO_YAML) - nkr_add_compile_definitions(NKR_NO_YAML) -else () - find_package(yaml-cpp CONFIG REQUIRED) # only Release is built - list(APPEND NKR_EXTERNAL_TARGETS yaml-cpp) -endif () - -# zxing-cpp -if (NKR_NO_ZXING) - nkr_add_compile_definitions(NKR_NO_ZXING) -else () - find_package(ZXing CONFIG REQUIRED) - list(APPEND NKR_EXTERNAL_TARGETS ZXing::ZXing) -endif () - -# QHotkey (static submodule) -if (NKR_NO_QHOTKEY) - nkr_add_compile_definitions(NKR_NO_QHOTKEY) -else () - set(QHOTKEY_INSTALL OFF) - set(BUILD_SHARED_LIBS OFF) - add_subdirectory(3rdparty/QHotkey) - list(APPEND NKR_EXTERNAL_TARGETS qhotkey) -endif () - -#### debug print #### - -if (DBG_CMAKE) - print_all_variables() - print_target_properties(myproto) - print_target_properties(yaml-cpp) - print_target_properties(ZXing::ZXing) - set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CMAKE_COMMAND} -E time") - set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK "${CMAKE_COMMAND} -E time") -endif () - -# Sources -set(PROJECT_SOURCES - ${PLATFORM_SOURCES} - - main/main.cpp - main/NekoGui.cpp - main/NekoGui_Utils.cpp - main/HTTPRequestHelper.cpp - - 3rdparty/base64.cpp - 3rdparty/qrcodegen.cpp - 3rdparty/QtExtKeySequenceEdit.cpp - - 3rdparty/qv2ray/v2/ui/QvAutoCompleteTextEdit.cpp - 3rdparty/qv2ray/v2/components/proxy/QvProxyConfigurator.cpp - 3rdparty/qv2ray/v2/ui/widgets/common/QJsonModel.cpp - 3rdparty/qv2ray/v2/ui/widgets/editors/w_JsonEditor.cpp - 3rdparty/qv2ray/v2/ui/widgets/editors/w_JsonEditor.hpp - 3rdparty/qv2ray/v2/ui/widgets/editors/w_JsonEditor.ui - - 3rdparty/qv2ray/v3/components/GeositeReader/GeositeReader.cpp - 3rdparty/qv2ray/v3/components/GeositeReader/picoproto.cpp - - rpc/gRPC.cpp - - db/Database.cpp - db/traffic/TrafficLooper.cpp - db/ProfileFilter.cpp - db/ConfigBuilder.cpp - - fmt/AbstractBean.cpp - fmt/Bean2CoreObj_box.cpp - fmt/Bean2External.cpp - fmt/Bean2Link.cpp - fmt/Link2Bean.cpp - fmt/ChainBean.hpp # translate - - sub/GroupUpdater.cpp - - sys/ExternalProcess.cpp - sys/AutoRun.cpp - - ui/ThemeManager.cpp - ui/Icon.cpp - - ui/mainwindow_grpc.cpp - ui/mainwindow.cpp - ui/mainwindow.h - ui/mainwindow.ui - - ui/edit/dialog_edit_profile.h - ui/edit/dialog_edit_profile.cpp - ui/edit/dialog_edit_profile.ui - ui/edit/dialog_edit_group.h - ui/edit/dialog_edit_group.cpp - ui/edit/dialog_edit_group.ui - - ui/edit/edit_chain.h - ui/edit/edit_chain.cpp - ui/edit/edit_chain.ui - ui/edit/edit_socks_http.h - ui/edit/edit_socks_http.cpp - ui/edit/edit_socks_http.ui - ui/edit/edit_shadowsocks.h - ui/edit/edit_shadowsocks.cpp - ui/edit/edit_shadowsocks.ui - ui/edit/edit_vmess.h - ui/edit/edit_vmess.cpp - ui/edit/edit_vmess.ui - ui/edit/edit_trojan_vless.h - ui/edit/edit_trojan_vless.cpp - ui/edit/edit_trojan_vless.ui - - ui/edit/edit_naive.h - ui/edit/edit_naive.cpp - ui/edit/edit_naive.ui - - ui/edit/edit_quic.h - ui/edit/edit_quic.cpp - ui/edit/edit_quic.ui - - ui/edit/edit_custom.h - ui/edit/edit_custom.cpp - ui/edit/edit_custom.ui - - ui/dialog_basic_settings.cpp - ui/dialog_basic_settings.h - ui/dialog_basic_settings.ui - - ui/dialog_manage_groups.cpp - ui/dialog_manage_groups.h - ui/dialog_manage_groups.ui - - ui/dialog_manage_routes.cpp - ui/dialog_manage_routes.h - ui/dialog_manage_routes.ui - - ui/dialog_vpn_settings.cpp - ui/dialog_vpn_settings.h - ui/dialog_vpn_settings.ui - - ui/dialog_hotkey.cpp - ui/dialog_hotkey.h - ui/dialog_hotkey.ui - - ui/widget/ProxyItem.cpp - ui/widget/ProxyItem.h - ui/widget/ProxyItem.ui - ui/widget/GroupItem.cpp - ui/widget/GroupItem.h - ui/widget/GroupItem.ui - - res/neko.qrc - res/theme/feiyangqingyun/qss.qrc - ${QV2RAY_RC} -) - -# Qt exe -if (${QT_VERSION_MAJOR} GREATER_EQUAL 6) - qt_add_executable(nekobox - MANUAL_FINALIZATION - ${PROJECT_SOURCES} - ) - # Define target properties for Android with Qt 6 as: - # set_property(TARGET nekobox APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR - # ${CMAKE_CURRENT_SOURCE_DIR}/android) - # For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation -else () - if (ANDROID) - add_library(nekobox SHARED - ${PROJECT_SOURCES} - ) - # Define properties for Android with Qt 5 after find_package() calls as: - # set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android") - else () - add_executable(nekobox - ${PROJECT_SOURCES} - ) - endif () -endif () - -# Target - -set_property(TARGET nekobox PROPERTY AUTOUIC ON) -set_property(TARGET nekobox PROPERTY AUTOMOC ON) -set_property(TARGET nekobox PROPERTY AUTORCC ON) - -set_target_properties(nekobox PROPERTIES - WIN32_EXECUTABLE TRUE -) - -# Target Source Translations - -set(TS_FILES - translations/zh_CN.ts - translations/fa_IR.ts - translations/ru_RU.ts -) -set(LUPDATE_OPTIONS - -locations none -no-obsolete -) -if (${QT_VERSION_MAJOR} GREATER_EQUAL 6) - qt_add_lupdate(nekobox TS_FILES ${TS_FILES} OPTIONS ${LUPDATE_OPTIONS}) - qt_add_lrelease(nekobox TS_FILES ${TS_FILES} QM_FILES_OUTPUT_VARIABLE QM_FILES) -else () - qt5_create_translation(QM_FILES ${PROJECT_SOURCES} ${TS_FILES} OPTIONS ${LUPDATE_OPTIONS}) -endif () -configure_file(translations/translations.qrc ${CMAKE_BINARY_DIR} COPYONLY) -target_sources(nekobox PRIVATE ${CMAKE_BINARY_DIR}/translations.qrc) - -# Target Link - -target_link_libraries(nekobox PRIVATE - Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Network Qt${QT_VERSION_MAJOR}::Svg - Threads::Threads - ${NKR_EXTERNAL_TARGETS} - ${PLATFORM_LIBRARIES} -) - -if (QT_VERSION_MAJOR EQUAL 6) - qt_finalize_executable(nekobox) -endif () diff --git a/LICENSE b/LICENSE deleted file mode 100644 index f288702..0000000 --- a/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/README.md b/README.md deleted file mode 100644 index 9cff256..0000000 --- a/README.md +++ /dev/null @@ -1,119 +0,0 @@ -# NekoBox For PC - -Qt based cross-platform GUI proxy configuration manager (backend: sing-box) - -Support Windows / Linux out of the box now. - -基于 Qt 的跨平台代理配置管理器 (后端 sing-box) - -目前支持 Windows / Linux 开箱即用 - -## 下载 / Download - -### GitHub Releases (Portable ZIP) - -便携格式,无安装器。转到 Releases 下载预编译的二进制文件,解压后即可使用。 - -[![GitHub All Releases](https://img.shields.io/github/downloads/Matsuridayo/nekoray/total?label=downloads-total&logo=github&style=flat-square)](https://github.com/Matsuridayo/nekoray/releases) - -[下载 / Download](https://github.com/Matsuridayo/nekoray/releases) - -[安装包的说明,如果你不知道要下载哪一个](https://github.com/MatsuriDayo/nekoray/wiki/Installation-package-description) - -### Package - -#### AUR - -- [nekoray](https://aur.archlinux.org/packages/nekoray) -- [nekoray-git](https://aur.archlinux.org/packages/nekoray-git) - -#### archlinuxcn - -- [nekoray](https://github.com/archlinuxcn/repo/tree/master/archlinuxcn/nekoray) -- [nekoray-git](https://github.com/archlinuxcn/repo/tree/master/archlinuxcn/nekoray-git) - -#### Scoop Extras - -`scoop install nekoray` - -## 更改记录 & 发布频道 / Changelog & Telegram Channel - -https://t.me/Matsuridayo - -## 项目主页 & 文档 / Homepage & Documents - -https://matsuridayo.github.io - -## 代理 / Proxy - -- SOCKS (4/4a/5) -- HTTP(S) -- Shadowsocks -- VMess -- VLESS -- Trojan -- TUIC ( sing-box ) -- NaïveProxy ( Custom Core ) -- Hysteria2 ( Custom Core or sing-box ) -- Custom Outbound -- Custom Config -- Custom Core - -## 订阅 / Subscription - -- Raw: some widely used formats (like Shadowsocks, Clash and v2rayN) -- 原始格式: 一些广泛使用的格式 (如 Shadowsocks、Clash 和 v2rayN) - -## 运行参数 - -[运行参数](docs/RunFlags.md) - -## Windows 运行 - -若提示 DLL 缺失,无法运行,请下载 安装 [微软 C++ 运行库](https://aka.ms/vs/17/release/vc_redist.x64.exe) - -## Linux 运行 - -[Linux 运行教程](docs/Run_Linux.md) - -## 编译教程 / Compile Tutorial - -请看 [技术文档 / Technical documentation](https://github.com/MatsuriDayo/nekoray/tree/main/docs) - -## 捐助 / Donate - -如果这个项目对您有帮助,可以通过捐赠的方式帮助我们维持这个项目。 - -捐赠满等额 50 USD 可以在「[捐赠榜](https://mtrdnt.pages.dev/donation_list)」显示头像,如果您未被添加到这里,欢迎联系我们补充。 - -Donations of 50 USD or more can display your avatar on the [Donation List](https://mtrdnt.pages.dev/donation_list). If you are not added here, please contact us to add it. - -USDT TRC20 - -`TRhnA7SXE5Sap5gSG3ijxRmdYFiD4KRhPs` - -XMR - -`49bwESYQjoRL3xmvTcjZKHEKaiGywjLYVQJMUv79bXonGiyDCs8AzE3KiGW2ytTybBCpWJUvov8SjZZEGg66a4e59GXa6k5` - -## Credits - -Core: - -- [v2fly/v2ray-core](https://github.com/v2fly/v2ray-core) ( < 3.10 ) -- [MatsuriDayo/Matsuri](https://github.com/MatsuriDayo/Matsuri) ( < 3.10 ) -- [MatsuriDayo/v2ray-core](https://github.com/MatsuriDayo/v2ray-core) ( < 3.10 ) -- [XTLS/Xray-core](https://github.com/XTLS/Xray-core) ( 3.10 <= Version <= 3.26 ) -- [MatsuriDayo/Xray-core](https://github.com/MatsuriDayo/Xray-core) ( 3.10 <= Version <= 3.26 ) -- [SagerNet/sing-box](https://github.com/SagerNet/sing-box) -- [Matsuridayo/sing-box-extra](https://github.com/MatsuriDayo/sing-box-extra) - -Gui: - -- [Qv2ray](https://github.com/Qv2ray/Qv2ray) -- [Qt](https://www.qt.io/) -- [protobuf](https://github.com/protocolbuffers/protobuf) -- [yaml-cpp](https://github.com/jbeder/yaml-cpp) -- [zxing-cpp](https://github.com/nu-book/zxing-cpp) -- [QHotkey](https://github.com/Skycoder42/QHotkey) -- [AppImageKit](https://github.com/AppImage/AppImageKit) diff --git a/cmake/linux/linux.cmake b/cmake/linux/linux.cmake deleted file mode 100644 index f9458e0..0000000 --- a/cmake/linux/linux.cmake +++ /dev/null @@ -1,2 +0,0 @@ -set(PLATFORM_SOURCES sys/linux/LinuxCap.cpp) -set(PLATFORM_LIBRARIES dl) diff --git a/cmake/myproto.cmake b/cmake/myproto.cmake deleted file mode 100644 index 4f387f1..0000000 --- a/cmake/myproto.cmake +++ /dev/null @@ -1,14 +0,0 @@ -find_package(Protobuf CONFIG REQUIRED) - -set(PROTO_FILES - go/grpc_server/gen/libcore.proto - ) - -add_library(myproto STATIC ${PROTO_FILES}) -target_link_libraries(myproto - PUBLIC - protobuf::libprotobuf - ) -target_include_directories(myproto PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) - -protobuf_generate(TARGET myproto LANGUAGE cpp) diff --git a/cmake/nkr.cmake b/cmake/nkr.cmake deleted file mode 100644 index ac501ab..0000000 --- a/cmake/nkr.cmake +++ /dev/null @@ -1,12 +0,0 @@ -# Release -file(STRINGS nekoray_version.txt NKR_VERSION) -add_compile_definitions(NKR_VERSION=\"${NKR_VERSION}\") - -# Debug -set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DNKR_CPP_DEBUG") - -# Func -function(nkr_add_compile_definitions arg) - message("[add_compile_definitions] ${ARGV}") - add_compile_definitions(${ARGV}) -endfunction() diff --git a/cmake/print.cmake b/cmake/print.cmake deleted file mode 100644 index 89705d2..0000000 --- a/cmake/print.cmake +++ /dev/null @@ -1,43 +0,0 @@ -macro(print_all_variables) - message(STATUS "print_all_variables------------------------------------------{") - get_cmake_property(_variableNames VARIABLES) - foreach (_variableName ${_variableNames}) - message(STATUS "${_variableName}=${${_variableName}}") - endforeach() - message(STATUS "print_all_variables------------------------------------------}") -endmacro() - -# Get all propreties that cmake supports -if(NOT CMAKE_PROPERTY_LIST) - execute_process(COMMAND cmake --help-property-list OUTPUT_VARIABLE CMAKE_PROPERTY_LIST) - - # Convert command output into a CMake list - string(REGEX REPLACE ";" "\\\\;" CMAKE_PROPERTY_LIST "${CMAKE_PROPERTY_LIST}") - string(REGEX REPLACE "\n" ";" CMAKE_PROPERTY_LIST "${CMAKE_PROPERTY_LIST}") -endif() - -function(print_properties) - message("CMAKE_PROPERTY_LIST = ${CMAKE_PROPERTY_LIST}") -endfunction() - -function(print_target_properties target) - if(NOT TARGET ${target}) - message(STATUS "There is no target named '${target}'") - return() - endif() - - foreach(property ${CMAKE_PROPERTY_LIST}) - string(REPLACE "" "${CMAKE_BUILD_TYPE}" property ${property}) - - # Fix https://stackoverflow.com/questions/32197663/how-can-i-remove-the-the-location-property-may-not-be-read-from-target-error-i - if(property STREQUAL "LOCATION" OR property MATCHES "^LOCATION_" OR property MATCHES "_LOCATION$") - continue() - endif() - - get_property(was_set TARGET ${target} PROPERTY ${property} SET) - if(was_set) - get_target_property(value ${target} ${property}) - message("${target} ${property} = ${value}") - endif() - endforeach() -endfunction() diff --git a/cmake/windows/VersionInfo.in b/cmake/windows/VersionInfo.in deleted file mode 100644 index 89625c1..0000000 --- a/cmake/windows/VersionInfo.in +++ /dev/null @@ -1,82 +0,0 @@ -#pragma once - -#ifndef PRODUCT_VERSION_MAJOR - #define PRODUCT_VERSION_MAJOR @PRODUCT_VERSION_MAJOR@ -#endif - -#ifndef PRODUCT_VERSION_MINOR - #define PRODUCT_VERSION_MINOR @PRODUCT_VERSION_MINOR@ -#endif - -#ifndef PRODUCT_VERSION_PATCH - #define PRODUCT_VERSION_PATCH @PRODUCT_VERSION_PATCH@ -#endif - -#ifndef PRODUCT_VERSION_BUILD - #define PRODUCT_VERSION_BUILD @PRODUCT_VERSION_REVISION@ -#endif - -#ifndef FILE_VERSION_MAJOR - #define FILE_VERSION_MAJOR @PRODUCT_VERSION_MAJOR@ -#endif - -#ifndef FILE_VERSION_MINOR - #define FILE_VERSION_MINOR @PRODUCT_VERSION_MINOR@ -#endif - -#ifndef FILE_VERSION_PATCH - #define FILE_VERSION_PATCH @PRODUCT_VERSION_PATCH@ -#endif - -#ifndef FILE_VERSION_BUILD - #define FILE_VERSION_BUILD @PRODUCT_VERSION_REVISION@ -#endif - -#ifndef __TO_STRING - #define __TO_STRING_IMPL(x) #x - #define __TO_STRING(x) __TO_STRING_IMPL(x) -#endif - -#define PRODUCT_VERSION_MAJOR_MINOR_STR __TO_STRING(PRODUCT_VERSION_MAJOR) "." __TO_STRING(PRODUCT_VERSION_MINOR) -#define PRODUCT_VERSION_MAJOR_MINOR_PATCH_STR PRODUCT_VERSION_MAJOR_MINOR_STR "." __TO_STRING(PRODUCT_VERSION_PATCH) -#define PRODUCT_VERSION_FULL_STR PRODUCT_VERSION_MAJOR_MINOR_PATCH_STR "." __TO_STRING(PRODUCT_VERSION_BUILD) -#define PRODUCT_VERSION_RESOURCE PRODUCT_VERSION_MAJOR,PRODUCT_VERSION_MINOR,PRODUCT_VERSION_PATCH,PRODUCT_VERSION_BUILD -#define PRODUCT_VERSION_RESOURCE_STR PRODUCT_VERSION_FULL_STR "\0" - -#define FILE_VERSION_MAJOR_MINOR_STR __TO_STRING(FILE_VERSION_MAJOR) "." __TO_STRING(FILE_VERSION_MINOR) -#define FILE_VERSION_MAJOR_MINOR_PATCH_STR FILE_VERSION_MAJOR_MINOR_STR "." __TO_STRING(FILE_VERSION_PATCH) -#define FILE_VERSION_FULL_STR FILE_VERSION_MAJOR_MINOR_PATCH_STR "." __TO_STRING(FILE_VERSION_BUILD) -#define FILE_VERSION_RESOURCE FILE_VERSION_MAJOR,FILE_VERSION_MINOR,FILE_VERSION_PATCH,FILE_VERSION_BUILD -#define FILE_VERSION_RESOURCE_STR FILE_VERSION_FULL_STR "\0" - -#ifndef PRODUCT_ICON - #define PRODUCT_ICON "@PRODUCT_ICON@" -#endif - -#ifndef PRODUCT_COMMENTS - #define PRODUCT_COMMENTS "@PRODUCT_COMMENTS@\0" -#endif - -#ifndef PRODUCT_COMPANY_NAME - #define PRODUCT_COMPANY_NAME "@PRODUCT_COMPANY_NAME@\0" -#endif - -#ifndef PRODUCT_COMPANY_COPYRIGHT - #define PRODUCT_COMPANY_COPYRIGHT "@PRODUCT_COMPANY_COPYRIGHT@\0" -#endif - -#ifndef PRODUCT_FILE_DESCRIPTION - #define PRODUCT_FILE_DESCRIPTION "@PRODUCT_FILE_DESCRIPTION@\0" -#endif - -#ifndef PRODUCT_INTERNAL_NAME - #define PRODUCT_INTERNAL_NAME "@PRODUCT_NAME@\0" -#endif - -#ifndef PRODUCT_ORIGINAL_FILENAME - #define PRODUCT_ORIGINAL_FILENAME "@PRODUCT_ORIGINAL_FILENAME@\0" -#endif - -#ifndef PRODUCT_BUNDLE - #define PRODUCT_BUNDLE "@PRODUCT_BUNDLE@\0" -#endif diff --git a/cmake/windows/VersionResource.rc b/cmake/windows/VersionResource.rc deleted file mode 100644 index b5462ac..0000000 --- a/cmake/windows/VersionResource.rc +++ /dev/null @@ -1,52 +0,0 @@ -#include "VersionInfo.h" - -#if defined(__MINGW64__) || defined(__MINGW32__) - // MinGW-w64, MinGW - #if defined(__has_include) && __has_include() - #include - #else - #include - #include - #endif -#else - // MSVC, Windows SDK - #include -#endif - -IDI_ICON1 ICON PRODUCT_ICON - -LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT - -VS_VERSION_INFO VERSIONINFO - FILEVERSION FILE_VERSION_RESOURCE - PRODUCTVERSION PRODUCT_VERSION_RESOURCE - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x4L - FILETYPE 0x1L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "000904b0" - BEGIN - VALUE "Comments", PRODUCT_COMMENTS - VALUE "CompanyName", PRODUCT_COMPANY_NAME - VALUE "FileDescription", PRODUCT_FILE_DESCRIPTION - VALUE "FileVersion", FILE_VERSION_RESOURCE_STR - VALUE "InternalName", PRODUCT_INTERNAL_NAME - VALUE "LegalCopyright", PRODUCT_COMPANY_COPYRIGHT - VALUE "OriginalFilename", PRODUCT_ORIGINAL_FILENAME - VALUE "ProductName", PRODUCT_BUNDLE - VALUE "ProductVersion", PRODUCT_VERSION_RESOURCE_STR - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x9, 1200 - END -END diff --git a/cmake/windows/generate_product_version.cmake b/cmake/windows/generate_product_version.cmake deleted file mode 100644 index bc395d4..0000000 --- a/cmake/windows/generate_product_version.cmake +++ /dev/null @@ -1,107 +0,0 @@ -include (CMakeParseArguments) - -set (GenerateProductVersionCurrentDir ${CMAKE_CURRENT_LIST_DIR}) - -# generate_product_version() function -# -# This function uses VersionInfo.in template file and VersionResource.rc file -# to generate WIN32 resource with version information and general resource strings. -# -# Usage: -# generate_product_version( -# SomeOutputResourceVariable -# NAME MyGreatProject -# ICON ${PATH_TO_APP_ICON} -# VERSION_MAJOR 2 -# VERSION_MINOR 3 -# VERSION_PATCH ${BUILD_COUNTER} -# VERSION_REVISION ${BUILD_REVISION} -# ) -# where BUILD_COUNTER and BUILD_REVISION could be values from your CI server. -# -# You can use generated resource for your executable targets: -# add_executable(target-name ${target-files} ${SomeOutputResourceVariable}) -# -# You can specify resource strings in arguments: -# NAME - name of executable (no defaults, ex: Microsoft Word) -# BUNDLE - bundle (${NAME} is default, ex: Microsoft Office) -# ICON - path to application icon (${CMAKE_SOURCE_DIR}/product.ico by default) -# VERSION_MAJOR - 1 is default -# VERSION_MINOR - 0 is default -# VERSION_PATCH - 0 is default -# VERSION_REVISION - 0 is default -# COMPANY_NAME - your company name (no defaults) -# COMPANY_COPYRIGHT - ${COMPANY_NAME} (C) Copyright ${CURRENT_YEAR} is default -# COMMENTS - ${NAME} v${VERSION_MAJOR}.${VERSION_MINOR} is default -# ORIGINAL_FILENAME - ${NAME} is default -# INTERNAL_NAME - ${NAME} is default -# FILE_DESCRIPTION - ${NAME} is default -function(generate_product_version outfiles) - set (options) - set (oneValueArgs - NAME - BUNDLE - ICON - VERSION_MAJOR - VERSION_MINOR - VERSION_PATCH - VERSION_REVISION - COMPANY_NAME - COMPANY_COPYRIGHT - COMMENTS - ORIGINAL_FILENAME - INTERNAL_NAME - FILE_DESCRIPTION) - set (multiValueArgs) - cmake_parse_arguments(PRODUCT "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) - - if (NOT PRODUCT_BUNDLE OR "${PRODUCT_BUNDLE}" STREQUAL "") - set(PRODUCT_BUNDLE "${PRODUCT_NAME}") - endif() - if (NOT PRODUCT_ICON OR "${PRODUCT_ICON}" STREQUAL "") - set(PRODUCT_ICON "${CMAKE_SOURCE_DIR}/product.ico") - endif() - - if (NOT PRODUCT_VERSION_MAJOR EQUAL 0 AND (NOT PRODUCT_VERSION_MAJOR OR "${PRODUCT_VERSION_MAJOR}" STREQUAL "")) - set(PRODUCT_VERSION_MAJOR 1) - endif() - if (NOT PRODUCT_VERSION_MINOR EQUAL 0 AND (NOT PRODUCT_VERSION_MINOR OR "${PRODUCT_VERSION_MINOR}" STREQUAL "")) - set(PRODUCT_VERSION_MINOR 0) - endif() - if (NOT PRODUCT_VERSION_PATCH EQUAL 0 AND (NOT PRODUCT_VERSION_PATCH OR "${PRODUCT_VERSION_PATCH}" STREQUAL "")) - set(PRODUCT_VERSION_PATCH 0) - endif() - if (NOT PRODUCT_VERSION_REVISION EQUAL 0 AND (NOT PRODUCT_VERSION_REVISION OR "${PRODUCT_VERSION_REVISION}" STREQUAL "")) - set(PRODUCT_VERSION_REVISION 0) - endif() - - if (NOT PRODUCT_COMPANY_COPYRIGHT OR "${PRODUCT_COMPANY_COPYRIGHT}" STREQUAL "") - string(TIMESTAMP PRODUCT_CURRENT_YEAR "%Y") - set(PRODUCT_COMPANY_COPYRIGHT "${PRODUCT_COMPANY_NAME} (C) Copyright ${PRODUCT_CURRENT_YEAR}") - endif() - if (NOT PRODUCT_COMMENTS OR "${PRODUCT_COMMENTS}" STREQUAL "") - set(PRODUCT_COMMENTS "${PRODUCT_NAME} v${PRODUCT_VERSION_MAJOR}.${PRODUCT_VERSION_MINOR}") - endif() - if (NOT PRODUCT_ORIGINAL_FILENAME OR "${PRODUCT_ORIGINAL_FILENAME}" STREQUAL "") - set(PRODUCT_ORIGINAL_FILENAME "${PRODUCT_NAME}") - endif() - if (NOT PRODUCT_INTERNAL_NAME OR "${PRODUCT_INTERNAL_NAME}" STREQUAL "") - set(PRODUCT_INTERNAL_NAME "${PRODUCT_NAME}") - endif() - if (NOT PRODUCT_FILE_DESCRIPTION OR "${PRODUCT_FILE_DESCRIPTION}" STREQUAL "") - set(PRODUCT_FILE_DESCRIPTION "${PRODUCT_NAME}") - endif() - - set (_VersionInfoFile ${CMAKE_CURRENT_BINARY_DIR}/VersionInfo.h) - set (_VersionResourceFile ${CMAKE_CURRENT_BINARY_DIR}/VersionResource.rc) - configure_file( - ${GenerateProductVersionCurrentDir}/VersionInfo.in - ${_VersionInfoFile} - @ONLY) - configure_file( - ${GenerateProductVersionCurrentDir}/VersionResource.rc - ${_VersionResourceFile} - COPYONLY) - list(APPEND ${outfiles} ${_VersionInfoFile} ${_VersionResourceFile}) - set (${outfiles} ${${outfiles}} PARENT_SCOPE) -endfunction() diff --git a/cmake/windows/windows.cmake b/cmake/windows/windows.cmake deleted file mode 100644 index 5859588..0000000 --- a/cmake/windows/windows.cmake +++ /dev/null @@ -1,24 +0,0 @@ -set(PLATFORM_SOURCES 3rdparty/WinCommander.cpp sys/windows/guihelper.cpp sys/windows/MiniDump.cpp) -set(PLATFORM_LIBRARIES wininet wsock32 ws2_32 user32 rasapi32 iphlpapi) - -include(cmake/windows/generate_product_version.cmake) -generate_product_version( - QV2RAY_RC - ICON "${CMAKE_SOURCE_DIR}/res/nekobox.ico" - NAME "nekobox" - BUNDLE "nekobox" - COMPANY_NAME "nekobox" - COMPANY_COPYRIGHT "nekobox" - FILE_DESCRIPTION "nekobox" -) -add_definitions(-DUNICODE -D_UNICODE -DNOMINMAX) -set(GUI_TYPE WIN32) -if (MINGW) - if (NOT DEFINED MinGW_ROOT) - set(MinGW_ROOT "C:/msys64/mingw64") - endif () -else () - add_compile_options("/utf-8") - add_compile_options("/std:c++17") - add_definitions(-D_WIN32_WINNT=0x600 -D_SCL_SECURE_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS) -endif () diff --git a/db/ConfigBuilder.cpp b/db/ConfigBuilder.cpp deleted file mode 100644 index 379fff7..0000000 --- a/db/ConfigBuilder.cpp +++ /dev/null @@ -1,818 +0,0 @@ -#include "db/ConfigBuilder.hpp" -#include "db/Database.hpp" -#include "fmt/includes.h" -#include "fmt/Preset.hpp" - -#include -#include -#include - -#define BOX_UNDERLYING_DNS dataStore->core_box_underlying_dns.isEmpty() ? "local" : dataStore->core_box_underlying_dns - -namespace NekoGui { - - QStringList getAutoBypassExternalProcessPaths(const std::shared_ptr &result) { - QStringList paths; - for (const auto &extR: result->extRs) { - auto path = extR->program; - if (path.trimmed().isEmpty()) continue; - paths << path.replace("\\", "/"); - } - return paths; - } - - QString genTunName() { - auto tun_name = "neko-tun"; -#ifdef Q_OS_MACOS - tun_name = "utun9"; -#endif - return tun_name; - } - - void MergeJson(QJsonObject &dst, const QJsonObject &src) { - // 合并 - if (src.isEmpty()) return; - for (const auto &key: src.keys()) { - auto v_src = src[key]; - if (dst.contains(key)) { - auto v_dst = dst[key]; - if (v_src.isObject() && v_dst.isObject()) { // isObject 则合并? - auto v_src_obj = v_src.toObject(); - auto v_dst_obj = v_dst.toObject(); - MergeJson(v_dst_obj, v_src_obj); - dst[key] = v_dst_obj; - } else { - dst[key] = v_src; - } - } else if (v_src.isArray()) { - if (key.startsWith("+")) { - auto key2 = SubStrAfter(key, "+"); - auto v_dst = dst[key2]; - auto v_src_arr = v_src.toArray(); - auto v_dst_arr = v_dst.toArray(); - QJSONARRAY_ADD(v_src_arr, v_dst_arr) - dst[key2] = v_src_arr; - } else if (key.endsWith("+")) { - auto key2 = SubStrBefore(key, "+"); - auto v_dst = dst[key2]; - auto v_src_arr = v_src.toArray(); - auto v_dst_arr = v_dst.toArray(); - QJSONARRAY_ADD(v_dst_arr, v_src_arr) - dst[key2] = v_dst_arr; - } else { - dst[key] = v_src; - } - } else { - dst[key] = v_src; - } - } - } - - // Common - - std::shared_ptr BuildConfig(const std::shared_ptr &ent, bool forTest, bool forExport) { - auto result = std::make_shared(); - auto status = std::make_shared(); - status->ent = ent; - status->result = result; - status->forTest = forTest; - status->forExport = forExport; - - auto customBean = dynamic_cast(ent->bean.get()); - if (customBean != nullptr && customBean->core == "internal-full") { - result->coreConfig = QString2QJsonObject(customBean->config_simple); - } else { - BuildConfigSingBox(status); - } - - // apply custom config - MergeJson(result->coreConfig, QString2QJsonObject(ent->bean->custom_config)); - - return result; - } - - QString BuildChain(int chainId, const std::shared_ptr &status) { - auto group = profileManager->GetGroup(status->ent->gid); - if (group == nullptr) { - status->result->error = QStringLiteral("This profile is not in any group, your data may be corrupted."); - return {}; - } - - auto resolveChain = [=](const std::shared_ptr &ent) { - QList> resolved; - if (ent->type == "chain") { - auto list = ent->ChainBean()->list; - std::reverse(std::begin(list), std::end(list)); - for (auto id: list) { - resolved += profileManager->GetProfile(id); - if (resolved.last() == nullptr) { - status->result->error = QStringLiteral("chain missing ent: %1").arg(id); - break; - } - if (resolved.last()->type == "chain") { - status->result->error = QStringLiteral("chain in chain is not allowed: %1").arg(id); - break; - } - } - } else { - resolved += ent; - }; - return resolved; - }; - - // Make list - auto ents = resolveChain(status->ent); - if (!status->result->error.isEmpty()) return {}; - - if (group->front_proxy_id >= 0) { - auto fEnt = profileManager->GetProfile(group->front_proxy_id); - if (fEnt == nullptr) { - status->result->error = QStringLiteral("front proxy ent not found."); - return {}; - } - ents += resolveChain(fEnt); - if (!status->result->error.isEmpty()) return {}; - } - - // BuildChain - QString chainTagOut = BuildChainInternal(0, ents, status); - - // Chain ent traffic stat - if (ents.length() > 1) { - status->ent->traffic_data->id = status->ent->id; - status->ent->traffic_data->tag = chainTagOut.toStdString(); - status->result->outboundStats += status->ent->traffic_data; - } - - return chainTagOut; - } - -#define DOMAIN_USER_RULE \ - for (const auto &line: SplitLinesSkipSharp(dataStore->routing->proxy_domain)) { \ - if (dataStore->routing->dns_routing) status->domainListDNSRemote += line; \ - status->domainListRemote += line; \ - } \ - for (const auto &line: SplitLinesSkipSharp(dataStore->routing->direct_domain)) { \ - if (dataStore->routing->dns_routing) status->domainListDNSDirect += line; \ - status->domainListDirect += line; \ - } \ - for (const auto &line: SplitLinesSkipSharp(dataStore->routing->block_domain)) { \ - status->domainListBlock += line; \ - } - -#define IP_USER_RULE \ - for (const auto &line: SplitLinesSkipSharp(dataStore->routing->block_ip)) { \ - status->ipListBlock += line; \ - } \ - for (const auto &line: SplitLinesSkipSharp(dataStore->routing->proxy_ip)) { \ - status->ipListRemote += line; \ - } \ - for (const auto &line: SplitLinesSkipSharp(dataStore->routing->direct_ip)) { \ - status->ipListDirect += line; \ - } - - QString BuildChainInternal(int chainId, const QList> &ents, - const std::shared_ptr &status) { - QString chainTag = "c-" + Int2String(chainId); - QString chainTagOut; - bool muxApplied = false; - - QString pastTag; - int pastExternalStat = 0; - int index = 0; - - for (const auto &ent: ents) { - // tagOut: v2ray outbound tag for a profile - // profile2 (in) (global) tag g-(id) - // profile1 tag (chainTag)-(id) - // profile0 (out) tag (chainTag)-(id) / single: chainTag=g-(id) - auto tagOut = chainTag + "-" + Int2String(ent->id); - - // needGlobal: can only contain one? - bool needGlobal = false; - - // first profile set as global - auto isFirstProfile = index == ents.length() - 1; - if (isFirstProfile) { - needGlobal = true; - tagOut = "g-" + Int2String(ent->id); - } - - // last profile set as "proxy" - if (chainId == 0 && index == 0) { - needGlobal = false; - tagOut = "proxy"; - } - - // ignoreConnTag - if (index != 0) { - status->result->ignoreConnTag << tagOut; - } - - if (needGlobal) { - if (status->globalProfiles.contains(ent->id)) { - continue; - } - status->globalProfiles += ent->id; - } - - if (index > 0) { - // chain rules: past - if (pastExternalStat == 0) { - auto replaced = status->outbounds.last().toObject(); - replaced["detour"] = tagOut; - status->outbounds.removeLast(); - status->outbounds += replaced; - } else { - status->routingRules += QJsonObject{ - {"inbound", QJsonArray{pastTag + "-mapping"}}, - {"outbound", tagOut}, - }; - } - } else { - // index == 0 means last profile in chain / not chain - chainTagOut = tagOut; - status->result->outboundStat = ent->traffic_data; - } - - // chain rules: this - auto ext_mapping_port = 0; - auto ext_socks_port = 0; - auto thisExternalStat = ent->bean->NeedExternal(isFirstProfile); - if (thisExternalStat < 0) { - status->result->error = "This configuration cannot be set automatically, please try another."; - return {}; - } - - // determine port - if (thisExternalStat > 0) { - if (ent->type == "custom") { - auto bean = ent->CustomBean(); - if (IsValidPort(bean->mapping_port)) { - ext_mapping_port = bean->mapping_port; - } else { - ext_mapping_port = MkPort(); - } - if (IsValidPort(bean->socks_port)) { - ext_socks_port = bean->socks_port; - } else { - ext_socks_port = MkPort(); - } - } else { - ext_mapping_port = MkPort(); - ext_socks_port = MkPort(); - } - } - if (thisExternalStat == 2) dataStore->need_keep_vpn_off = true; - if (thisExternalStat == 1) { - // mapping - status->inbounds += QJsonObject{ - {"type", "direct"}, - {"tag", tagOut + "-mapping"}, - {"listen", "127.0.0.1"}, - {"listen_port", ext_mapping_port}, - {"override_address", ent->bean->serverAddress}, - {"override_port", ent->bean->serverPort}, - }; - // no chain rule and not outbound, so need to set to direct - if (isFirstProfile) { - status->routingRules += QJsonObject{ - {"inbound", QJsonArray{tagOut + "-mapping"}}, - {"outbound", "direct"}, - }; - } - } - - // Outbound - - QJsonObject outbound; - auto stream = GetStreamSettings(ent->bean.get()); - - if (thisExternalStat > 0) { - auto extR = ent->bean->BuildExternal(ext_mapping_port, ext_socks_port, thisExternalStat); - if (extR.program.isEmpty()) { - status->result->error = QObject::tr("Core not found: %1").arg(ent->bean->DisplayCoreType()); - return {}; - } - if (!extR.error.isEmpty()) { // rejected - status->result->error = extR.error; - return {}; - } - extR.tag = ent->bean->DisplayType(); - status->result->extRs.emplace_back(std::make_shared(extR)); - - // SOCKS OUTBOUND - outbound["type"] = "socks"; - outbound["server"] = "127.0.0.1"; - outbound["server_port"] = ext_socks_port; - } else { - const auto coreR = ent->bean->BuildCoreObjSingBox(); - if (coreR.outbound.isEmpty()) { - status->result->error = "unsupported outbound"; - return {}; - } - if (!coreR.error.isEmpty()) { // rejected - status->result->error = coreR.error; - return {}; - } - outbound = coreR.outbound; - } - - // outbound misc - outbound["tag"] = tagOut; - ent->traffic_data->id = ent->id; - ent->traffic_data->tag = tagOut.toStdString(); - status->result->outboundStats += ent->traffic_data; - - // mux common - auto needMux = ent->type == "vmess" || ent->type == "trojan" || ent->type == "vless"; - needMux &= dataStore->mux_concurrency > 0; - - if (stream != nullptr) { - if (stream->network == "grpc" || stream->network == "quic" || (stream->network == "http" && stream->security == "tls")) { - needMux = false; - } - if (stream->multiplex_status == 0) { - if (!dataStore->mux_default_on) needMux = false; - } else if (stream->multiplex_status == 1) { - needMux = true; - } else if (stream->multiplex_status == 2) { - needMux = false; - } - } - if (ent->type == "vless" && outbound["flow"] != "") { - needMux = false; - } - - // common - // apply domain_strategy - outbound["domain_strategy"] = dataStore->routing->outbound_domain_strategy; - // apply mux - if (!muxApplied && needMux) { - auto muxObj = QJsonObject{ - {"enabled", true}, - {"protocol", dataStore->mux_protocol}, - {"padding", dataStore->mux_padding}, - {"max_streams", dataStore->mux_concurrency}, - }; - outbound["multiplex"] = muxObj; - muxApplied = true; - } - - // apply custom outbound settings - MergeJson(outbound, QString2QJsonObject(ent->bean->custom_outbound)); - - // Bypass Lookup for the first profile - auto serverAddress = ent->bean->serverAddress; - - auto customBean = dynamic_cast(ent->bean.get()); - if (customBean != nullptr && customBean->core == "internal") { - auto server = QString2QJsonObject(customBean->config_simple)["server"].toString(); - if (!server.isEmpty()) serverAddress = server; - } - - if (!IsIpAddress(serverAddress)) { - status->domainListDNSDirect += "full:" + serverAddress; - } - - status->outbounds += outbound; - pastTag = tagOut; - pastExternalStat = thisExternalStat; - index++; - } - - return chainTagOut; - } - - // SingBox - - void BuildConfigSingBox(const std::shared_ptr &status) { - // Log - status->result->coreConfig["log"] = QJsonObject{{"level", dataStore->log_level}}; - - // Inbounds - - // mixed-in - if (IsValidPort(dataStore->inbound_socks_port) && !status->forTest) { - QJsonObject inboundObj; - inboundObj["tag"] = "mixed-in"; - inboundObj["type"] = "mixed"; - inboundObj["listen"] = dataStore->inbound_address; - inboundObj["listen_port"] = dataStore->inbound_socks_port; - if (dataStore->routing->sniffing_mode != SniffingMode::DISABLE) { - inboundObj["sniff"] = true; - inboundObj["sniff_override_destination"] = dataStore->routing->sniffing_mode == SniffingMode::FOR_DESTINATION; - } - if (dataStore->inbound_auth->NeedAuth()) { - inboundObj["users"] = QJsonArray{ - QJsonObject{ - {"username", dataStore->inbound_auth->username}, - {"password", dataStore->inbound_auth->password}, - }, - }; - } - inboundObj["domain_strategy"] = dataStore->routing->domain_strategy; - status->inbounds += inboundObj; - } - - // tun-in - if (dataStore->vpn_internal_tun && dataStore->spmode_vpn && !status->forTest) { - QJsonObject inboundObj; - inboundObj["tag"] = "tun-in"; - inboundObj["type"] = "tun"; - inboundObj["interface_name"] = genTunName(); - inboundObj["auto_route"] = true; - inboundObj["endpoint_independent_nat"] = true; - inboundObj["mtu"] = dataStore->vpn_mtu; - inboundObj["stack"] = Preset::SingBox::VpnImplementation.value(dataStore->vpn_implementation); - inboundObj["strict_route"] = dataStore->vpn_strict_route; - inboundObj["inet4_address"] = "172.19.0.1/28"; - if (dataStore->vpn_ipv6) inboundObj["inet6_address"] = "fdfe:dcba:9876::1/126"; - if (dataStore->routing->sniffing_mode != SniffingMode::DISABLE) { - inboundObj["sniff"] = true; - inboundObj["sniff_override_destination"] = dataStore->routing->sniffing_mode == SniffingMode::FOR_DESTINATION; - } - inboundObj["domain_strategy"] = dataStore->routing->domain_strategy; - status->inbounds += inboundObj; - } - - // Outbounds - auto tagProxy = BuildChain(0, status); - if (!status->result->error.isEmpty()) return; - - // direct & bypass & block - status->outbounds += QJsonObject{ - {"type", "direct"}, - {"tag", "direct"}, - }; - status->outbounds += QJsonObject{ - {"type", "direct"}, - {"tag", "bypass"}, - }; - status->outbounds += QJsonObject{ - {"type", "block"}, - {"tag", "block"}, - }; - if (!status->forTest) { - status->outbounds += QJsonObject{ - {"type", "dns"}, - {"tag", "dns-out"}, - }; - } - - // custom inbound - if (!status->forTest) QJSONARRAY_ADD(status->inbounds, QString2QJsonObject(dataStore->custom_inbound)["inbounds"].toArray()) - - status->result->coreConfig.insert("inbounds", status->inbounds); - status->result->coreConfig.insert("outbounds", status->outbounds); - - // user rule - if (!status->forTest) { - DOMAIN_USER_RULE - IP_USER_RULE - } - - // sing-box common rule object - auto make_rule = [&](const QStringList &list, bool isIP = false) { - QJsonObject rule; - // - QJsonArray ip_cidr; - QJsonArray geoip; - // - QJsonArray domain_keyword; - QJsonArray domain_subdomain; - QJsonArray domain_regexp; - QJsonArray domain_full; - QJsonArray geosite; - for (auto item: list) { - if (isIP) { - if (item.startsWith("geoip:")) { - geoip += item.replace("geoip:", ""); - } else { - ip_cidr += item; - } - } else { - // https://www.v2fly.org/config/dns.html#dnsobject - if (item.startsWith("geosite:")) { - geosite += item.replace("geosite:", ""); - } else if (item.startsWith("full:")) { - domain_full += item.replace("full:", "").toLower(); - } else if (item.startsWith("domain:")) { - domain_subdomain += item.replace("domain:", "").toLower(); - } else if (item.startsWith("regexp:")) { - domain_regexp += item.replace("regexp:", "").toLower(); - } else if (item.startsWith("keyword:")) { - domain_keyword += item.replace("keyword:", "").toLower(); - } else { - domain_subdomain += item.toLower(); - } - } - } - if (isIP) { - if (ip_cidr.isEmpty() && geoip.isEmpty()) return rule; - rule["ip_cidr"] = ip_cidr; - rule["geoip"] = geoip; - } else { - if (domain_keyword.isEmpty() && domain_subdomain.isEmpty() && domain_regexp.isEmpty() && domain_full.isEmpty() && geosite.isEmpty()) { - return rule; - } - rule["domain"] = domain_full; - rule["domain_suffix"] = domain_subdomain; // v2ray Subdomain => sing-box suffix - rule["domain_keyword"] = domain_keyword; - rule["domain_regex"] = domain_regexp; - rule["geosite"] = geosite; - } - return rule; - }; - - // final add DNS - QJsonObject dns; - QJsonArray dnsServers; - QJsonArray dnsRules; - - // Remote - if (!status->forTest) - dnsServers += QJsonObject{ - {"tag", "dns-remote"}, - {"address_resolver", "dns-local"}, - {"strategy", dataStore->routing->remote_dns_strategy}, - {"address", dataStore->routing->remote_dns}, - {"detour", tagProxy}, - }; - - // Direct - QJsonObject directObj{ - {"tag", "dns-direct"}, - {"address_resolver", "dns-local"}, - {"strategy", dataStore->routing->direct_dns_strategy}, - {"address", dataStore->routing->direct_dns}, - {"detour", "direct"}, - }; - if (dataStore->routing->dns_final_out == "bypass") { - dnsServers.prepend(directObj); - } else { - dnsServers.append(directObj); - } - dnsRules.append(QJsonObject{ - {"outbound", "any"}, - {"server", "dns-direct"}, - }); - - // block - if (!status->forTest) - dnsServers += QJsonObject{ - {"tag", "dns-block"}, - {"address", "rcode://success"}, - }; - - // Fakedns - if (dataStore->fake_dns && dataStore->vpn_internal_tun && dataStore->spmode_vpn && !status->forTest) { - dnsServers += QJsonObject{ - {"tag", "dns-fake"}, - {"address", "fakeip"}, - }; - dns["fakeip"] = QJsonObject{ - {"enabled", true}, - {"inet4_range", "198.18.0.0/15"}, - {"inet6_range", "fc00::/18"}, - }; - } - - // Underlying 100% Working DNS ? - dnsServers += QJsonObject{ - {"tag", "dns-local"}, - {"address", BOX_UNDERLYING_DNS}, - {"detour", "direct"}, - }; - - // sing-box dns rule object - auto add_rule_dns = [&](const QStringList &list, const QString &server) { - auto rule = make_rule(list, false); - if (rule.isEmpty()) return; - rule["server"] = server; - dnsRules += rule; - }; - add_rule_dns(status->domainListDNSRemote, "dns-remote"); - add_rule_dns(status->domainListDNSDirect, "dns-direct"); - - // built-in rules - if (!status->forTest) { - dnsRules += QJsonObject{ - {"query_type", QJsonArray{32, 33}}, - {"server", "dns-block"}, - }; - dnsRules += QJsonObject{ - {"domain_suffix", ".lan"}, - {"server", "dns-block"}, - }; - } - - // fakedns rule - if (dataStore->fake_dns && dataStore->vpn_internal_tun && dataStore->spmode_vpn && !status->forTest) { - dnsRules += QJsonObject{ - {"inbound", "tun-in"}, - {"server", "dns-fake"}, - }; - } - - dns["servers"] = dnsServers; - dns["rules"] = dnsRules; - dns["independent_cache"] = true; - - if (dataStore->routing->use_dns_object) { - dns = QString2QJsonObject(dataStore->routing->dns_object); - } - status->result->coreConfig.insert("dns", dns); - - // Routing - - // dns hijack - if (!status->forTest) { - status->routingRules += QJsonObject{ - {"protocol", "dns"}, - {"outbound", "dns-out"}, - }; - } - - // sing-box routing rule object - auto add_rule_route = [&](const QStringList &list, bool isIP, const QString &out) { - auto rule = make_rule(list, isIP); - if (rule.isEmpty()) return; - rule["outbound"] = out; - status->routingRules += rule; - }; - - // final add user rule - add_rule_route(status->domainListBlock, false, "block"); - add_rule_route(status->domainListRemote, false, tagProxy); - add_rule_route(status->domainListDirect, false, "bypass"); - add_rule_route(status->ipListBlock, true, "block"); - add_rule_route(status->ipListRemote, true, tagProxy); - add_rule_route(status->ipListDirect, true, "bypass"); - - // built-in rules - status->routingRules += QJsonObject{ - {"network", "udp"}, - {"port", QJsonArray{135, 137, 138, 139, 5353}}, - {"outbound", "block"}, - }; - status->routingRules += QJsonObject{ - {"ip_cidr", QJsonArray{"224.0.0.0/3", "ff00::/8"}}, - {"outbound", "block"}, - }; - status->routingRules += QJsonObject{ - {"source_ip_cidr", QJsonArray{"224.0.0.0/3", "ff00::/8"}}, - {"outbound", "block"}, - }; - - // tun user rule - if (dataStore->vpn_internal_tun && dataStore->spmode_vpn && !status->forTest) { - auto match_out = dataStore->vpn_rule_white ? "proxy" : "bypass"; - - QString process_name_rule = dataStore->vpn_rule_process.trimmed(); - if (!process_name_rule.isEmpty()) { - auto arr = SplitLinesSkipSharp(process_name_rule); - QJsonObject rule{{"outbound", match_out}, - {"process_name", QList2QJsonArray(arr)}}; - status->routingRules += rule; - } - - QString cidr_rule = dataStore->vpn_rule_cidr.trimmed(); - if (!cidr_rule.isEmpty()) { - auto arr = SplitLinesSkipSharp(cidr_rule); - QJsonObject rule{{"outbound", match_out}, - {"ip_cidr", QList2QJsonArray(arr)}}; - status->routingRules += rule; - } - - auto autoBypassExternalProcessPaths = getAutoBypassExternalProcessPaths(status->result); - if (!autoBypassExternalProcessPaths.isEmpty()) { - QJsonObject rule{{"outbound", "bypass"}, - {"process_name", QList2QJsonArray(autoBypassExternalProcessPaths)}}; - status->routingRules += rule; - } - } - - // geopath - auto geoip = FindCoreAsset("geoip.db"); - auto geosite = FindCoreAsset("geosite.db"); - if (geoip.isEmpty()) status->result->error = +"geoip.db not found"; - if (geosite.isEmpty()) status->result->error = +"geosite.db not found"; - - // final add routing rule - auto routingRules = QString2QJsonObject(dataStore->routing->custom)["rules"].toArray(); - if (status->forTest) routingRules = {}; - if (!status->forTest) QJSONARRAY_ADD(routingRules, QString2QJsonObject(dataStore->custom_route_global)["rules"].toArray()) - QJSONARRAY_ADD(routingRules, status->routingRules) - auto routeObj = QJsonObject{ - {"rules", routingRules}, - {"auto_detect_interface", dataStore->spmode_vpn}, // TODO force enable? - { - "geoip", - QJsonObject{ - {"path", geoip}, - }, - }, - { - "geosite", - QJsonObject{ - {"path", geosite}, - }, - }}; - if (!status->forTest) routeObj["final"] = dataStore->routing->def_outbound; - if (status->forExport) { - routeObj.remove("geoip"); - routeObj.remove("geosite"); - routeObj.remove("auto_detect_interface"); - } - status->result->coreConfig.insert("route", routeObj); - - // experimental - QJsonObject experimentalObj; - - if (!status->forTest && dataStore->core_box_clash_api > 0) { - QJsonObject clash_api = { - {"external_controller", "127.0.0.1:" + Int2String(dataStore->core_box_clash_api)}, - {"secret", dataStore->core_box_clash_api_secret}, - {"external_ui", "dashboard"}, - }; - experimentalObj["clash_api"] = clash_api; - } - - if (!experimentalObj.isEmpty()) status->result->coreConfig.insert("experimental", experimentalObj); - } - - QString WriteVPNSingBoxConfig() { - // tun user rule - auto match_out = dataStore->vpn_rule_white ? "neko-socks" : "direct"; - auto no_match_out = dataStore->vpn_rule_white ? "direct" : "neko-socks"; - - QString process_name_rule = dataStore->vpn_rule_process.trimmed(); - if (!process_name_rule.isEmpty()) { - auto arr = SplitLinesSkipSharp(process_name_rule); - QJsonObject rule{{"outbound", match_out}, - {"process_name", QList2QJsonArray(arr)}}; - process_name_rule = "," + QJsonObject2QString(rule, false); - } - - QString cidr_rule = dataStore->vpn_rule_cidr.trimmed(); - if (!cidr_rule.isEmpty()) { - auto arr = SplitLinesSkipSharp(cidr_rule); - QJsonObject rule{{"outbound", match_out}, - {"ip_cidr", QList2QJsonArray(arr)}}; - cidr_rule = "," + QJsonObject2QString(rule, false); - } - - // TODO bypass ext core process path? - - // auth - QString socks_user_pass; - if (dataStore->inbound_auth->NeedAuth()) { - socks_user_pass = R"( "username": "%1", "password": "%2", )"; - socks_user_pass = socks_user_pass.arg(dataStore->inbound_auth->username, dataStore->inbound_auth->password); - } - // gen config - auto configFn = ":/neko/vpn/sing-box-vpn.json"; - if (QFile::exists("vpn/sing-box-vpn.json")) configFn = "vpn/sing-box-vpn.json"; - auto config = ReadFileText(configFn) - .replace("//%IPV6_ADDRESS%", dataStore->vpn_ipv6 ? R"("inet6_address": "fdfe:dcba:9876::1/126",)" : "") - .replace("//%SOCKS_USER_PASS%", socks_user_pass) - .replace("//%PROCESS_NAME_RULE%", process_name_rule) - .replace("//%CIDR_RULE%", cidr_rule) - .replace("%MTU%", Int2String(dataStore->vpn_mtu)) - .replace("%STACK%", Preset::SingBox::VpnImplementation.value(dataStore->vpn_implementation)) - .replace("%TUN_NAME%", genTunName()) - .replace("%STRICT_ROUTE%", dataStore->vpn_strict_route ? "true" : "false") - .replace("%FINAL_OUT%", no_match_out) - .replace("%DNS_ADDRESS%", BOX_UNDERLYING_DNS) - .replace("%FAKE_DNS_INBOUND%", dataStore->fake_dns ? "tun-in" : "empty") - .replace("%PORT%", Int2String(dataStore->inbound_socks_port)); - // write config - QFile file; - file.setFileName(QFileInfo(configFn).fileName()); - file.open(QIODevice::ReadWrite | QIODevice::Truncate); - file.write(config.toUtf8()); - file.close(); - return QFileInfo(file).absoluteFilePath(); - } - - QString WriteVPNLinuxScript(const QString &configPath) { -#ifdef Q_OS_WIN - return {}; -#endif - // gen script - auto scriptFn = ":/neko/vpn/vpn-run-root.sh"; - if (QFile::exists("vpn/vpn-run-root.sh")) scriptFn = "vpn/vpn-run-root.sh"; - auto script = ReadFileText(scriptFn) - .replace("./nekobox_core", QApplication::applicationDirPath() + "/nekobox_core") - .replace("$CONFIG_PATH", configPath); - // write script - QFile file2; - file2.setFileName(QFileInfo(scriptFn).fileName()); - file2.open(QIODevice::ReadWrite | QIODevice::Truncate); - file2.write(script.toUtf8()); - file2.close(); - return QFileInfo(file2).absoluteFilePath(); - } - -} // namespace NekoGui diff --git a/db/ConfigBuilder.hpp b/db/ConfigBuilder.hpp deleted file mode 100644 index 3c150c7..0000000 --- a/db/ConfigBuilder.hpp +++ /dev/null @@ -1,59 +0,0 @@ -#pragma once - -#include "ProxyEntity.hpp" -#include "sys/ExternalProcess.hpp" - -namespace NekoGui { - class BuildConfigResult { - public: - QString error; - QJsonObject coreConfig; - - QList> outboundStats; // all, but not including "bypass" "block" - std::shared_ptr outboundStat; // main - QStringList ignoreConnTag; - - std::list> extRs; - }; - - class BuildConfigStatus { - public: - std::shared_ptr result; - std::shared_ptr ent; - bool forTest; - bool forExport; - - // priv - QList globalProfiles; - - // xxList is V2Ray format string list - - QStringList domainListDNSRemote; - QStringList domainListDNSDirect; - QStringList domainListRemote; - QStringList domainListDirect; - QStringList ipListRemote; - QStringList ipListDirect; - QStringList domainListBlock; - QStringList ipListBlock; - - // config format - - QJsonArray routingRules; - QJsonArray inbounds; - QJsonArray outbounds; - }; - - std::shared_ptr BuildConfig(const std::shared_ptr &ent, bool forTest, bool forExport); - - void BuildConfigSingBox(const std::shared_ptr &status); - - QString BuildChain(int chainId, const std::shared_ptr &status); - - QString BuildChainInternal(int chainId, const QList> &ents, - const std::shared_ptr &status); - - QString WriteVPNSingBoxConfig(); - - QString WriteVPNLinuxScript(const QString &configPath); -} // namespace NekoGui diff --git a/db/Database.cpp b/db/Database.cpp deleted file mode 100644 index 5736438..0000000 --- a/db/Database.cpp +++ /dev/null @@ -1,394 +0,0 @@ -#include "Database.hpp" - -#include "fmt/includes.h" - -#include -#include -#include - -namespace NekoGui { - - ProfileManager *profileManager = new ProfileManager(); - - ProfileManager::ProfileManager() : JsonStore("groups/pm.json") { - _add(new configItem("groups", &groupsTabOrder, itemType::integerList)); - } - - QList filterIntJsonFile(const QString &path) { - QList result; - QDir dr(path); - auto entryList = dr.entryList(QDir::Files); - for (auto e: entryList) { - e = e.toLower(); - if (!e.endsWith(".json", Qt::CaseInsensitive)) continue; - e = e.remove(".json", Qt::CaseInsensitive); - bool ok; - auto id = e.toInt(&ok); - if (ok) { - result << id; - } - } - std::sort(result.begin(), result.end()); - return result; - } - - void ProfileManager::LoadManager() { - JsonStore::Load(); - // - profiles = {}; - groups = {}; - profilesIdOrder = filterIntJsonFile("profiles"); - groupsIdOrder = filterIntJsonFile("groups"); - // Load Proxys - QList delProfile; - for (auto id: profilesIdOrder) { - auto ent = LoadProxyEntity(QStringLiteral("profiles/%1.json").arg(id)); - // Corrupted profile? - if (ent == nullptr || ent->bean == nullptr || ent->bean->version == -114514) { - delProfile << id; - continue; - } - profiles[id] = ent; - } - // Clear Corrupted profile - for (auto id: delProfile) { - DeleteProfile(id); - } - // Load Groups - auto loadedOrder = groupsTabOrder; - groupsTabOrder = {}; - for (auto id: groupsIdOrder) { - auto ent = LoadGroup(QStringLiteral("groups/%1.json").arg(id)); - // Corrupted group? - if (ent->id != id) { - continue; - } - // Ensure order contains every group - if (!loadedOrder.contains(id)) { - loadedOrder << id; - } - groups[id] = ent; - } - // Ensure groups contains order - for (auto id: loadedOrder) { - if (groups.count(id)) { - groupsTabOrder << id; - } - } - // First setup - if (groups.empty()) { - auto defaultGroup = NekoGui::ProfileManager::NewGroup(); - defaultGroup->name = QObject::tr("Default"); - NekoGui::profileManager->AddGroup(defaultGroup); - } - // - if (dataStore->flag_reorder) { - { - // remove all (contains orphan) - for (const auto &profile: profiles) { - QFile::remove(profile.second->fn); - } - } - std::map gidOld2New; - { - int i = 0; - int ii = 0; - QList newProfilesIdOrder; - std::map> newProfiles; - for (auto gid: groupsTabOrder) { - auto group = GetGroup(gid); - gidOld2New[gid] = ii++; - for (auto const &profile: group->ProfilesWithOrder()) { - auto oldId = profile->id; - auto newId = i++; - profile->id = newId; - profile->gid = gidOld2New[gid]; - profile->fn = QStringLiteral("profiles/%1.json").arg(newId); - profile->Save(); - newProfiles[newId] = profile; - newProfilesIdOrder << newId; - } - group->order = {}; - group->Save(); - } - profiles = newProfiles; - profilesIdOrder = newProfilesIdOrder; - } - { - QList newGroupsIdOrder; - std::map> newGroups; - for (auto oldGid: groupsTabOrder) { - auto newId = gidOld2New[oldGid]; - auto group = groups[oldGid]; - QFile::remove(group->fn); - group->id = newId; - group->fn = QStringLiteral("groups/%1.json").arg(newId); - group->Save(); - newGroups[newId] = group; - newGroupsIdOrder << newId; - } - groups = newGroups; - groupsIdOrder = newGroupsIdOrder; - groupsTabOrder = newGroupsIdOrder; - } - MessageBoxInfo(software_name, "Profiles and groups reorder complete."); - } - } - - void ProfileManager::SaveManager() { - JsonStore::Save(); - } - - std::shared_ptr ProfileManager::LoadProxyEntity(const QString &jsonPath) { - // Load type - ProxyEntity ent0(nullptr, nullptr); - ent0.fn = jsonPath; - auto validJson = ent0.Load(); - auto type = ent0.type; - - // Load content - std::shared_ptr ent; - bool validType = validJson; - - if (validType) { - ent = NewProxyEntity(type); - validType = ent->bean->version != -114514; - } - - if (validType) { - ent->load_control_must = true; - ent->fn = jsonPath; - ent->Load(); - } - return ent; - } - - // 新建的不给 fn 和 id - - std::shared_ptr ProfileManager::NewProxyEntity(const QString &type) { - NekoGui_fmt::AbstractBean *bean; - - if (type == "socks") { - bean = new NekoGui_fmt::SocksHttpBean(NekoGui_fmt::SocksHttpBean::type_Socks5); - } else if (type == "http") { - bean = new NekoGui_fmt::SocksHttpBean(NekoGui_fmt::SocksHttpBean::type_HTTP); - } else if (type == "shadowsocks") { - bean = new NekoGui_fmt::ShadowSocksBean(); - } else if (type == "chain") { - bean = new NekoGui_fmt::ChainBean(); - } else if (type == "vmess") { - bean = new NekoGui_fmt::VMessBean(); - } else if (type == "trojan") { - bean = new NekoGui_fmt::TrojanVLESSBean(NekoGui_fmt::TrojanVLESSBean::proxy_Trojan); - } else if (type == "vless") { - bean = new NekoGui_fmt::TrojanVLESSBean(NekoGui_fmt::TrojanVLESSBean::proxy_VLESS); - } else if (type == "naive") { - bean = new NekoGui_fmt::NaiveBean(); - } else if (type == "hysteria2") { - bean = new NekoGui_fmt::QUICBean(NekoGui_fmt::QUICBean::proxy_Hysteria2); - } else if (type == "tuic") { - bean = new NekoGui_fmt::QUICBean(NekoGui_fmt::QUICBean::proxy_TUIC); - } else if (type == "custom") { - bean = new NekoGui_fmt::CustomBean(); - } else { - bean = new NekoGui_fmt::AbstractBean(-114514); - } - - auto ent = std::make_shared(bean, type); - return ent; - } - - std::shared_ptr ProfileManager::NewGroup() { - auto ent = std::make_shared(); - return ent; - } - - // ProxyEntity - - ProxyEntity::ProxyEntity(NekoGui_fmt::AbstractBean *bean, const QString &type_) { - if (type_ != nullptr) this->type = type_; - - _add(new configItem("type", &type, itemType::string)); - _add(new configItem("id", &id, itemType::integer)); - _add(new configItem("gid", &gid, itemType::integer)); - _add(new configItem("yc", &latency, itemType::integer)); - _add(new configItem("report", &full_test_report, itemType::string)); - - // 可以不关联 bean,只加载 ProxyEntity 的信息 - if (bean != nullptr) { - this->bean = std::shared_ptr(bean); - // 有虚函数就要在这里 dynamic_cast - _add(new configItem("bean", dynamic_cast(bean), itemType::jsonStore)); - _add(new configItem("traffic", dynamic_cast(traffic_data.get()), itemType::jsonStore)); - } - }; - - QString ProxyEntity::DisplayLatency() const { - if (latency < 0) { - return QObject::tr("Unavailable"); - } else if (latency > 0) { - return UNICODE_LRO + QStringLiteral("%1 ms").arg(latency); - } else { - return ""; - } - } - - QColor ProxyEntity::DisplayLatencyColor() const { - if (latency < 0) { - return Qt::red; - } else if (latency > 0) { - auto greenMs = dataStore->test_latency_url.startsWith("https://") ? 200 : 100; - if (latency < greenMs) { - return Qt::darkGreen; - } else { - return Qt::darkYellow; - } - } else { - return {}; - } - } - - // Profile - - int ProfileManager::NewProfileID() const { - if (profiles.empty()) { - return 0; - } else { - return profilesIdOrder.last() + 1; - } - } - - bool ProfileManager::AddProfile(const std::shared_ptr &ent, int gid) { - if (ent->id >= 0) { - return false; - } - - ent->gid = gid < 0 ? dataStore->current_group : gid; - ent->id = NewProfileID(); - profiles[ent->id] = ent; - profilesIdOrder.push_back(ent->id); - - ent->fn = QStringLiteral("profiles/%1.json").arg(ent->id); - ent->Save(); - return true; - } - - void ProfileManager::DeleteProfile(int id) { - if (id < 0) return; - if (dataStore->started_id == id) return; - profiles.erase(id); - profilesIdOrder.removeAll(id); - QFile(QStringLiteral("profiles/%1.json").arg(id)).remove(); - } - - void ProfileManager::MoveProfile(const std::shared_ptr &ent, int gid) { - if (gid == ent->gid || gid < 0) return; - auto oldGroup = GetGroup(ent->gid); - if (oldGroup != nullptr && !oldGroup->order.isEmpty()) { - oldGroup->order.removeAll(ent->id); - oldGroup->Save(); - } - auto newGroup = GetGroup(gid); - if (newGroup != nullptr && !newGroup->order.isEmpty()) { - newGroup->order.push_back(ent->id); - newGroup->Save(); - } - ent->gid = gid; - ent->Save(); - } - - std::shared_ptr ProfileManager::GetProfile(int id) { - return profiles.count(id) ? profiles[id] : nullptr; - } - - // Group - - Group::Group() { - _add(new configItem("id", &id, itemType::integer)); - _add(new configItem("front_proxy_id", &front_proxy_id, itemType::integer)); - _add(new configItem("archive", &archive, itemType::boolean)); - _add(new configItem("skip_auto_update", &skip_auto_update, itemType::boolean)); - _add(new configItem("name", &name, itemType::string)); - _add(new configItem("order", &order, itemType::integerList)); - _add(new configItem("url", &url, itemType::string)); - _add(new configItem("info", &info, itemType::string)); - _add(new configItem("lastup", &sub_last_update, itemType::integer64)); - _add(new configItem("manually_column_width", &manually_column_width, itemType::boolean)); - _add(new configItem("column_width", &column_width, itemType::integerList)); - } - - std::shared_ptr ProfileManager::LoadGroup(const QString &jsonPath) { - auto ent = std::make_shared(); - ent->fn = jsonPath; - ent->Load(); - return ent; - } - - int ProfileManager::NewGroupID() const { - if (groups.empty()) { - return 0; - } else { - return groupsIdOrder.last() + 1; - } - } - - bool ProfileManager::AddGroup(const std::shared_ptr &ent) { - if (ent->id >= 0) { - return false; - } - - ent->id = NewGroupID(); - groups[ent->id] = ent; - groupsIdOrder.push_back(ent->id); - groupsTabOrder.push_back(ent->id); - - ent->fn = QStringLiteral("groups/%1.json").arg(ent->id); - ent->Save(); - return true; - } - - void ProfileManager::DeleteGroup(int gid) { - if (groups.size() <= 1) return; - QList toDelete; - for (const auto &[id, profile]: profiles) { - if (profile->gid == gid) toDelete += id; // map访问中,不能操作 - } - for (const auto &id: toDelete) { - DeleteProfile(id); - } - groups.erase(gid); - groupsIdOrder.removeAll(gid); - groupsTabOrder.removeAll(gid); - QFile(QStringLiteral("groups/%1.json").arg(gid)).remove(); - } - - std::shared_ptr ProfileManager::GetGroup(int id) { - return groups.count(id) ? groups[id] : nullptr; - } - - std::shared_ptr ProfileManager::CurrentGroup() { - return GetGroup(dataStore->current_group); - } - - QList> Group::Profiles() const { - QList> ret; - for (const auto &[_, profile]: profileManager->profiles) { - if (id == profile->gid) ret += profile; - } - return ret; - } - - QList> Group::ProfilesWithOrder() const { - if (order.isEmpty()) { - return Profiles(); - } else { - QList> ret; - for (auto _id: order) { - auto ent = profileManager->GetProfile(_id); - if (ent != nullptr) ret += ent; - } - return ret; - } - } - -} // namespace NekoGui diff --git a/db/Database.hpp b/db/Database.hpp deleted file mode 100644 index dc7272f..0000000 --- a/db/Database.hpp +++ /dev/null @@ -1,62 +0,0 @@ -#pragma once - -#include "main/NekoGui.hpp" -#include "ProxyEntity.hpp" -#include "Group.hpp" - -namespace NekoGui { - class ProfileManager : private JsonStore { - public: - // JsonStore - - // order -> id - QList groupsTabOrder; - - // Manager - - std::map> profiles; - std::map> groups; - - ProfileManager(); - - // LoadManager Reset and loads profiles & groups - void LoadManager(); - - void SaveManager(); - - [[nodiscard]] static std::shared_ptr NewProxyEntity(const QString &type); - - [[nodiscard]] static std::shared_ptr NewGroup(); - - bool AddProfile(const std::shared_ptr &ent, int gid = -1); - - void DeleteProfile(int id); - - void MoveProfile(const std::shared_ptr &ent, int gid); - - std::shared_ptr GetProfile(int id); - - bool AddGroup(const std::shared_ptr &ent); - - void DeleteGroup(int gid); - - std::shared_ptr GetGroup(int id); - - std::shared_ptr CurrentGroup(); - - private: - // sort by id - QList profilesIdOrder; - QList groupsIdOrder; - - [[nodiscard]] int NewProfileID() const; - - [[nodiscard]] int NewGroupID() const; - - static std::shared_ptr LoadProxyEntity(const QString &jsonPath); - - static std::shared_ptr LoadGroup(const QString &jsonPath); - }; - - extern ProfileManager *profileManager; -} // namespace NekoGui diff --git a/db/Group.hpp b/db/Group.hpp deleted file mode 100644 index e55c680..0000000 --- a/db/Group.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include "main/NekoGui.hpp" -#include "ProxyEntity.hpp" - -namespace NekoGui { - class Group : public JsonStore { - public: - int id = -1; - bool archive = false; - bool skip_auto_update = false; - QString name = ""; - QString url = ""; - QString info = ""; - qint64 sub_last_update = 0; - int front_proxy_id = -1; - - // list ui - bool manually_column_width = false; - QList column_width; - QList order; - - Group(); - - // 按 id 顺序 - [[nodiscard]] QList> Profiles() const; - - // 按 显示 顺序 - [[nodiscard]] QList> ProfilesWithOrder() const; - }; -} // namespace NekoGui diff --git a/db/ProfileFilter.cpp b/db/ProfileFilter.cpp deleted file mode 100644 index ea062d3..0000000 --- a/db/ProfileFilter.cpp +++ /dev/null @@ -1,75 +0,0 @@ -#include "ProfileFilter.hpp" - -namespace NekoGui { - - QString ProfileFilter_ent_key(const std::shared_ptr &ent, bool by_address) { - by_address &= ent->type != "custom"; - return by_address ? (ent->bean->DisplayAddress() + ent->bean->DisplayType()) - : QJsonObject2QString(ent->bean->ToJson({"c_cfg", "c_out"}), true) + ent->bean->DisplayType(); - } - - void ProfileFilter::Uniq(const QList> &in, - QList> &out, - bool by_address, bool keep_last) { - QMap> hashMap; - - for (const auto &ent: in) { - QString key = ProfileFilter_ent_key(ent, by_address); - if (hashMap.contains(key)) { - if (keep_last) { - out.removeAll(hashMap[key]); - hashMap[key] = ent; - out += ent; - } - } else { - hashMap[key] = ent; - out += ent; - } - } - } - - void ProfileFilter::Common(const QList> &src, - const QList> &dst, - QList> &outSrc, - QList> &outDst, - bool by_address) { - QMap> hashMap; - - for (const auto &ent: src) { - QString key = ProfileFilter_ent_key(ent, by_address); - hashMap[key] = ent; - } - for (const auto &ent: dst) { - QString key = ProfileFilter_ent_key(ent, by_address); - if (hashMap.contains(key)) { - outDst += ent; - outSrc += hashMap[key]; - } - } - } - - void ProfileFilter::OnlyInSrc(const QList> &src, - const QList> &dst, - QList> &out, - bool by_address) { - QMap hashMap; - - for (const auto &ent: dst) { - QString key = ProfileFilter_ent_key(ent, by_address); - hashMap[key] = true; - } - for (const auto &ent: src) { - QString key = ProfileFilter_ent_key(ent, by_address); - if (!hashMap.contains(key)) out += ent; - } - } - - void ProfileFilter::OnlyInSrc_ByPointer(const QList> &src, - const QList> &dst, - QList> &out) { - for (const auto &ent: src) { - if (!dst.contains(ent)) out += ent; - } - } - -} // namespace NekoGui \ No newline at end of file diff --git a/db/ProfileFilter.hpp b/db/ProfileFilter.hpp deleted file mode 100644 index b2d35b1..0000000 --- a/db/ProfileFilter.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include "ProxyEntity.hpp" - -namespace NekoGui { - class ProfileFilter { - public: - static void Uniq( - const QList> &in, - QList> &out, - bool by_address = false, // def by bean - bool keep_last = false // def keep first - ); - - static void Common( - const QList> &src, - const QList> &dst, - QList> &outSrc, - QList> &outDst, - bool by_address = false // def by bean - ); - - static void OnlyInSrc( - const QList> &src, - const QList> &dst, - QList> &out, - bool by_address = false // def by bean - ); - - static void OnlyInSrc_ByPointer( - const QList> &src, - const QList> &dst, - QList> &out); - }; -} // namespace NekoGui diff --git a/db/ProxyEntity.hpp b/db/ProxyEntity.hpp deleted file mode 100644 index f0cded9..0000000 --- a/db/ProxyEntity.hpp +++ /dev/null @@ -1,76 +0,0 @@ -#pragma once - -#include "main/NekoGui.hpp" -#include "db/traffic/TrafficData.hpp" -#include "fmt/AbstractBean.hpp" - -namespace NekoGui_fmt { - class SocksHttpBean; - - class ShadowSocksBean; - - class VMessBean; - - class TrojanVLESSBean; - - class NaiveBean; - - class QUICBean; - - class CustomBean; - - class ChainBean; -}; // namespace NekoGui_fmt - -namespace NekoGui { - class ProxyEntity : public JsonStore { - public: - QString type; - - int id = -1; - int gid = 0; - int latency = 0; - std::shared_ptr bean; - std::shared_ptr traffic_data = std::make_shared(""); - - QString full_test_report; - - ProxyEntity(NekoGui_fmt::AbstractBean *bean, const QString &type_); - - [[nodiscard]] QString DisplayLatency() const; - - [[nodiscard]] QColor DisplayLatencyColor() const; - - [[nodiscard]] NekoGui_fmt::ChainBean *ChainBean() const { - return (NekoGui_fmt::ChainBean *) bean.get(); - }; - - [[nodiscard]] NekoGui_fmt::SocksHttpBean *SocksHTTPBean() const { - return (NekoGui_fmt::SocksHttpBean *) bean.get(); - }; - - [[nodiscard]] NekoGui_fmt::ShadowSocksBean *ShadowSocksBean() const { - return (NekoGui_fmt::ShadowSocksBean *) bean.get(); - }; - - [[nodiscard]] NekoGui_fmt::VMessBean *VMessBean() const { - return (NekoGui_fmt::VMessBean *) bean.get(); - }; - - [[nodiscard]] NekoGui_fmt::TrojanVLESSBean *TrojanVLESSBean() const { - return (NekoGui_fmt::TrojanVLESSBean *) bean.get(); - }; - - [[nodiscard]] NekoGui_fmt::NaiveBean *NaiveBean() const { - return (NekoGui_fmt::NaiveBean *) bean.get(); - }; - - [[nodiscard]] NekoGui_fmt::QUICBean *QUICBean() const { - return (NekoGui_fmt::QUICBean *) bean.get(); - }; - - [[nodiscard]] NekoGui_fmt::CustomBean *CustomBean() const { - return (NekoGui_fmt::CustomBean *) bean.get(); - }; - }; -} // namespace NekoGui diff --git a/db/traffic/TrafficData.hpp b/db/traffic/TrafficData.hpp deleted file mode 100644 index 8ac2e09..0000000 --- a/db/traffic/TrafficData.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include "main/NekoGui.hpp" - -namespace NekoGui_traffic { - class TrafficData : public JsonStore { - public: - int id = -1; // ent id - std::string tag; - - long long downlink = 0; - long long uplink = 0; - long long downlink_rate = 0; - long long uplink_rate = 0; - - long long last_update; - - explicit TrafficData(std::string tag) { - this->tag = std::move(tag); - _add(new configItem("dl", &downlink, itemType::integer64)); - _add(new configItem("ul", &uplink, itemType::integer64)); - }; - - void Reset() { - downlink = 0; - uplink = 0; - downlink_rate = 0; - uplink_rate = 0; - } - - [[nodiscard]] QString DisplaySpeed() const { - return UNICODE_LRO + QStringLiteral("%1↑ %2↓").arg(ReadableSize(uplink_rate), ReadableSize(downlink_rate)); - } - - [[nodiscard]] QString DisplayTraffic() const { - if (downlink + uplink == 0) return ""; - return UNICODE_LRO + QStringLiteral("%1↑ %2↓").arg(ReadableSize(uplink), ReadableSize(downlink)); - } - }; -} // namespace NekoGui_traffic diff --git a/db/traffic/TrafficLooper.cpp b/db/traffic/TrafficLooper.cpp deleted file mode 100644 index 04f10cf..0000000 --- a/db/traffic/TrafficLooper.cpp +++ /dev/null @@ -1,135 +0,0 @@ -#include "TrafficLooper.hpp" - -#include "rpc/gRPC.h" -#include "ui/mainwindow_interface.h" - -#include -#include -#include -#include -#include - -namespace NekoGui_traffic { - - TrafficLooper *trafficLooper = new TrafficLooper; - QElapsedTimer elapsedTimer; - - TrafficData *TrafficLooper::update_stats(TrafficData *item) { -#ifndef NKR_NO_GRPC - // last update - auto now = elapsedTimer.elapsed(); - auto interval = now - item->last_update; - item->last_update = now; - if (interval <= 0) return nullptr; - - // query - auto uplink = NekoGui_rpc::defaultClient->QueryStats(item->tag, "uplink"); - auto downlink = NekoGui_rpc::defaultClient->QueryStats(item->tag, "downlink"); - - // add diff - item->downlink += downlink; - item->uplink += uplink; - item->downlink_rate = downlink * 1000 / interval; - item->uplink_rate = uplink * 1000 / interval; - - // return diff - auto ret = new TrafficData(item->tag); - ret->downlink = downlink; - ret->uplink = uplink; - ret->downlink_rate = item->downlink_rate; - ret->uplink_rate = item->uplink_rate; - return ret; -#endif - return nullptr; - } - - QJsonArray TrafficLooper::get_connection_list() { -#ifndef NKR_NO_GRPC - auto str = NekoGui_rpc::defaultClient->ListConnections(); - QJsonDocument jsonDocument = QJsonDocument::fromJson(str.c_str()); - return jsonDocument.array(); -#else - return QJsonArray{}; -#endif - } - - void TrafficLooper::UpdateAll() { - std::map updated; // tag to diff - for (const auto &item: this->items) { - auto data = item.get(); - auto diff = updated[data->tag]; - // 避免重复查询一个 outbound tag - if (diff == nullptr) { - diff = update_stats(data); - updated[data->tag] = diff; - } else { - data->uplink += diff->uplink; - data->downlink += diff->downlink; - data->uplink_rate = diff->uplink_rate; - data->downlink_rate = diff->downlink_rate; - } - } - updated[bypass->tag] = update_stats(bypass); - // - for (const auto &pair: updated) { - delete pair.second; - } - } - - void TrafficLooper::Loop() { - elapsedTimer.start(); - while (true) { - auto sleep_ms = NekoGui::dataStore->traffic_loop_interval; - if (sleep_ms < 500 || sleep_ms > 5000) sleep_ms = 1000; - QThread::msleep(sleep_ms); - if (NekoGui::dataStore->traffic_loop_interval == 0) continue; // user disabled - - // profile start and stop - if (!loop_enabled) { - // 停止 - if (looping) { - looping = false; - runOnUiThread([=] { - auto m = GetMainWindow(); - m->refresh_status("STOP"); - }); - } - continue; - } else { - // 开始 - if (!looping) { - looping = true; - } - } - - // do update - loop_mutex.lock(); - - UpdateAll(); - - // do conn list update - QJsonArray conn_list; - if (NekoGui::dataStore->connection_statistics) { - conn_list = get_connection_list(); - } - - loop_mutex.unlock(); - - // post to UI - runOnUiThread([=] { - auto m = GetMainWindow(); - if (proxy != nullptr) { - m->refresh_status(QObject::tr("Proxy: %1\nDirect: %2").arg(proxy->DisplaySpeed(), bypass->DisplaySpeed())); - } - for (const auto &item: items) { - if (item->id < 0) continue; - m->refresh_proxy_list(item->id); - } - if (NekoGui::dataStore->connection_statistics) { - m->refresh_connection_list(conn_list); - } - }); - } - } - -} // namespace NekoGui_traffic diff --git a/db/traffic/TrafficLooper.hpp b/db/traffic/TrafficLooper.hpp deleted file mode 100644 index f5b64fa..0000000 --- a/db/traffic/TrafficLooper.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "TrafficData.hpp" - -namespace NekoGui_traffic { - class TrafficLooper { - public: - bool loop_enabled = false; - bool looping = false; - QMutex loop_mutex; - - QList> items; - TrafficData *proxy = nullptr; - - void UpdateAll(); - - void Loop(); - - private: - TrafficData *bypass = new TrafficData("bypass"); - - [[nodiscard]] static TrafficData *update_stats(TrafficData *item); - - [[nodiscard]] static QJsonArray get_connection_list(); - }; - - extern TrafficLooper *trafficLooper; -} // namespace NekoGui_traffic diff --git a/docs/Build_Core.md b/docs/Build_Core.md deleted file mode 100644 index 5f1d02c..0000000 --- a/docs/Build_Core.md +++ /dev/null @@ -1,24 +0,0 @@ -## 构建 nekobox_core - -### 目录结构 - -``` - | nekoray - | go/cmd/* - | sing-box-extra - | sing-box - | ...... -``` - -### 常规构建 - -1. `bash libs/get_source.sh` (自动下载目录结构,自动 checkout commit) -2. `GOOS=windows GOARCH=amd64 bash libs/build_go.sh` - -具体支持的 GOOS 和 GOARCH 请看 `libs/build_go.sh` - -非官方构建无需编译 `updater` `launcher` - -### sing-box tags - -具体使用的 tags 请看 `libs/build_go.sh` diff --git a/docs/Build_Linux.md b/docs/Build_Linux.md deleted file mode 100644 index 966cb77..0000000 --- a/docs/Build_Linux.md +++ /dev/null @@ -1,76 +0,0 @@ -在 Linux 下编译 Nekoray - -## git clone 源码 - -``` -git clone https://github.com/MatsuriDayo/nekoray.git --recursive -``` - -## 简单编译法 - -条件: - -1. C++ 依赖:`protobuf yaml-cpp zxing-cpp` 已用包管理器安装,并符合版本要求。 -2. 已安装 `qtbase` `qtsvg` `qttools` `qtx11extras` -3. 已安装 Qt `5.12.x` 或 `5.15.x` -4. 系统为 `x86-64-linux-gnu` - -```shell -mkdir build -cd build -cmake -GNinja .. -ninja -``` - -编译完成后得到 `nekobox` - -解压 Release 的压缩包,替换其中的 `nekobox`,删除 `launcher` 即可使用。 - -## 复杂编译法 - -### CMake 参数 - -| CMake 参数 | 默认值 | 含义 | -|-------------------|-------------------|-----------------------| -| QT_VERSION_MAJOR | 5 | QT版本 | -| NKR_NO_EXTERNAL | | 不包含外部 C/C++ 依赖 (以下所有) | -| NKR_NO_YAML | | 不包含 yaml-cpp | -| NKR_NO_QHOTKEY | | 不包含 qhotkey | -| NKR_NO_ZXING | | 不包含 zxing | -| NKR_NO_GRPC | | 不包含 gRPC | -| NKR_PACKAGE | | 编译 package 版本 (aur) | -| NKR_LIBS | ./libs/deps/built | 依赖搜索目录 | -| NKR_DISABLE_LIBS | | 禁用 NKR_LIBS | - -1. `NKR_LIBS` 的值会被追加到 `CMAKE_PREFIX_PATH` -2. `NKR_PACKAGE` 打开后,`NKR_LIBS` 的默认值为 `./libs/deps/package` ,具体依赖请看 `build_deps_all.sh` -3. `NKR_PACKAGE` 打开后,应用将使用 appdata 目录存放配置,自动更新等功能将被禁用。 - -### C++ 部分 - -当您的发行版没有上面几个 C++ 依赖包,或者版本不符合要求时,可以参考 `build_deps_all.sh` 编译脚本自行编译。 - -条件: 已安装 Qt `5.12.x` 或 `5.15.x` - -#### 编译安装 C/C++ 依赖 - -(这一步可能要挂梯) - -```shell -./libs/build_deps_all.sh -``` - -#### 编译本体 - -```shell -mkdir build -cd build -cmake -GNinja .. -ninja -``` - -编译完成后得到 `nekobox` - -### Go 部分编译 - -请看 [Build_Core.md](./Build_Core.md) diff --git a/docs/Build_Windows.md b/docs/Build_Windows.md deleted file mode 100644 index b8a1469..0000000 --- a/docs/Build_Windows.md +++ /dev/null @@ -1,64 +0,0 @@ -在 Windows 下编译 Nekoray - -### git clone 源码 - -``` -git clone https://github.com/MatsuriDayo/nekoray.git --recursive -``` - -### 安装 Visual Studio - -从微软官网安装,可以使用 2019 和 2022 版本,安装 Win32 C++ 开发环境。 - -安装好后可以在「开始」菜单找到 `x64 Native Tools Command Prompt` - -本文之后的命令均在该 cmd 内执行。`cmake` `ninja` 等工具使用 VS 自带的即可。 - -### 下载 Qt SDK - -目前 Windows Release 使用的版本是 Qt 6.5.x - -下载解压后,将 bin 目录添加到环境变量。 - -#### Release 编译用到的 Qt 包下载 (MSVC2019 x86_64) - -https://github.com/MatsuriDayo/nekoray_qt_runtime/releases/download/20220503/Qt6.5.0-Windows-x86_64-VS2022-17.5.5-20230507.7z - -#### 官方签名版 Qt 5.15.2 (可选,已知有内存泄漏的BUG) - -在此下载 `qtbase` `qtsvg` `qttools` 的包并解压到同一个目录。 - -https://download.qt.io/online/qtsdkrepository/windows_x86/desktop/qt5_5152/qt.qt5.5152.win64_msvc2019_64/ - -### C++ 部分编译 - -#### 编译安装 C/C++ 依赖 - -(这一步可能要挂梯) - -```shell -bash ./libs/build_deps_all.sh -``` - -目前只有 bash 脚本,没有批处理或 powershell,如果 Windows 没有带 bash 建议自行安装。 - -CMake 参数等细节与 Linux 大同小异,有问题可以参照 Build_Linux 文档。 - -#### 编译本体 - -请根据你的 QT Sdk 的位置替换命令 - -```shell -mkdir build -cd build -cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=D:/path/to/qt/5.15.2/msvc2019_64 .. -ninja -``` - -编译完成后得到 `nekobox.exe` - -最后运行 `windeployqt nekobox.exe` 自动复制所需 DLL 等文件到当前目录 - -### Go 部分编译 - -请看 [Build_Core.md](./Build_Core.md) diff --git a/docs/RunFlags.md b/docs/RunFlags.md deleted file mode 100644 index eda46da..0000000 --- a/docs/RunFlags.md +++ /dev/null @@ -1,5 +0,0 @@ -# 运行参数 - -- `-many` 无视同目录正在运行的实例,强行开启新的实例。 -- `-appdata` 开启后配置文件会指定目录,未指定目录则使用共享目录,无法多开和自动升级。 -- `-flag_reorder` 进行重新整理配置文件的顺序,并删除损坏和孤立的配置。 diff --git a/docs/Run_Linux.md b/docs/Run_Linux.md deleted file mode 100644 index ae0aaa1..0000000 --- a/docs/Run_Linux.md +++ /dev/null @@ -1,81 +0,0 @@ -## Linux 安装 - -### Debian 系发行版 - -使用 Debian 系发行版时,推荐使用 .deb 包安装: - -```shell -sudo apt install ./nekoray-*-debian-x64.deb -``` - -安装完成后,桌面快捷方式启动自带参数 `-appdata`,如果想要直接启动并使用之前的配置,注意附带本参数。 - -### Arch 系发行版 - -使用 Arch 系发行版时,推荐从 ```aur``` 或 ```archlinuxcn``` 安装: - -#### AUR -##### 最新稳定版 - -```shell -[yay/paru] -S nekoray -``` - -##### 最新 Git 版 (开发版) - -```shell -[yay/paru] -S nekoray-git -``` - -#### archlinuxcn - -##### 最新稳定版 - -```shell -sudo pacman -S nekoray -``` - -##### 最新 Git 版 (开发版) - -```shell -sudo pacman -S nekoray-git -``` - -### 其他发行版 - -下载 .zip 文件,解压到合适的路径,开箱即用。 - -或下载 .AppImage,并使用 `chmod +x nekoray-*-AppImage-x64.AppImage` 给予可执行权限。 - -具体使用方法见下文。 - -## Linux 运行 - -**使用 Linux 系统相信您已具备基本的排错能力, -本项目不提供特定发行版/架构的支持,预编译文件不能满足您的需求时,请自行编译/适配。** - -已知部分 Linux 发行版无法使用、非 x86_64 暂无适配,可以尝试自行编译。 - -目前 Release 便携包解压后,有两种使用方法: - -1. System: 若要使用系统的 Qt5 运行库,请执行 `./nekoray` -2. Bundle: 若要使用预编译的 Qt 运行库,请执行 `./launcher` - -### Bundle - -要求:已安装主流的发行版和 xcb 桌面环境。 - -运行: `./launcher` 或 部分系统可双击打开 - -launcher 参数 - -* `./launcher -- -appdata` ( `--` 后的参数传递给主程序 ) -* `-debug` Debug mode - -Ubuntu 22.04: `sudo apt install libxcb-xinerama0` - -### System - -要求:已安装主流的发行版和 xcb 桌面环境,已安装 Qt5.12 ~ Qt5.15 环境。 - -运行: `./nekoray` 或 部分系统可双击打开。如果无法运行,建议使用 Bundle 版。 diff --git a/docs/readme.md b/docs/readme.md deleted file mode 100644 index c6c68fe..0000000 --- a/docs/readme.md +++ /dev/null @@ -1,6 +0,0 @@ -# 技术文档 - -# Technical documentation - -1. Build GUI: `Build_*.md` -2. Build Core: `Build_Core.md` diff --git a/fmt/AbstractBean.cpp b/fmt/AbstractBean.cpp deleted file mode 100644 index d030604..0000000 --- a/fmt/AbstractBean.cpp +++ /dev/null @@ -1,79 +0,0 @@ -#include "includes.h" - -#include -#include -#include - -namespace NekoGui_fmt { - AbstractBean::AbstractBean(int version) { - this->version = version; - _add(new configItem("_v", &this->version, itemType::integer)); - _add(new configItem("name", &name, itemType::string)); - _add(new configItem("addr", &serverAddress, itemType::string)); - _add(new configItem("port", &serverPort, itemType::integer)); - _add(new configItem("c_cfg", &custom_config, itemType::string)); - _add(new configItem("c_out", &custom_outbound, itemType::string)); - } - - QString AbstractBean::ToNekorayShareLink(const QString &type) { - auto b = ToJson(); - QUrl url; - url.setScheme("nekoray"); - url.setHost(type); - url.setFragment(QJsonObject2QString(b, true) - .toUtf8() - .toBase64(QByteArray::Base64UrlEncoding)); - return url.toString(); - } - - QString AbstractBean::DisplayAddress() { - return ::DisplayAddress(serverAddress, serverPort); - } - - QString AbstractBean::DisplayName() { - if (name.isEmpty()) { - return DisplayAddress(); - } - return name; - } - - QString AbstractBean::DisplayTypeAndName() { - return QStringLiteral("[%1] %2").arg(DisplayType(), DisplayName()); - } - - void AbstractBean::ResolveDomainToIP(const std::function &onFinished) { - bool noResolve = false; - if (dynamic_cast(this) != nullptr) noResolve = true; - if (dynamic_cast(this) != nullptr) noResolve = true; - if (dynamic_cast(this) != nullptr) noResolve = true; - if (IsIpAddress(serverAddress)) noResolve = true; - if (noResolve) { - onFinished(); - return; - } - -#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0) // TODO older QT - QHostInfo::lookupHost(serverAddress, QApplication::instance(), [=](const QHostInfo &host) { - auto addr = host.addresses(); - if (!addr.isEmpty()) { - auto domain = serverAddress; - auto stream = GetStreamSettings(this); - - // replace serverAddress - serverAddress = addr.first().toString(); - - // replace ws tls - if (stream != nullptr) { - if (stream->security == "tls" && stream->sni.isEmpty()) { - stream->sni = domain; - } - if (stream->network == "ws" && stream->host.isEmpty()) { - stream->host = domain; - } - } - } - onFinished(); - }); -#endif - } -} // namespace NekoGui_fmt diff --git a/fmt/AbstractBean.hpp b/fmt/AbstractBean.hpp deleted file mode 100644 index 0a5c098..0000000 --- a/fmt/AbstractBean.hpp +++ /dev/null @@ -1,69 +0,0 @@ -#pragma once - -#include -#include - -#include "main/NekoGui.hpp" - -namespace NekoGui_fmt { - struct CoreObjOutboundBuildResult { - public: - QJsonObject outbound; - QString error; - }; - - struct ExternalBuildResult { - public: - QString program; - QStringList env; - QStringList arguments; - // - QString tag; - // - QString error; - QString config_export; - }; - - class AbstractBean : public JsonStore { - public: - int version; - - QString name = ""; - QString serverAddress = "127.0.0.1"; - int serverPort = 1080; - - QString custom_config = ""; - QString custom_outbound = ""; - - explicit AbstractBean(int version); - - // - - QString ToNekorayShareLink(const QString &type); - - void ResolveDomainToIP(const std::function &onFinished); - - // - - [[nodiscard]] virtual QString DisplayAddress(); - - [[nodiscard]] virtual QString DisplayName(); - - virtual QString DisplayCoreType() { return software_core_name; }; - - virtual QString DisplayType() { return {}; }; - - virtual QString DisplayTypeAndName(); - - // - - virtual int NeedExternal(bool isFirstProfile) { return 0; }; - - virtual CoreObjOutboundBuildResult BuildCoreObjSingBox() { return {}; }; - - virtual ExternalBuildResult BuildExternal(int mapping_port, int socks_port, int external_stat) { return {}; }; - - virtual QString ToShareLink() { return {}; }; - }; - -} // namespace NekoGui_fmt diff --git a/fmt/Bean2CoreObj_box.cpp b/fmt/Bean2CoreObj_box.cpp deleted file mode 100644 index 72b6e1e..0000000 --- a/fmt/Bean2CoreObj_box.cpp +++ /dev/null @@ -1,237 +0,0 @@ -#include "db/ProxyEntity.hpp" -#include "fmt/includes.h" - -namespace NekoGui_fmt { - void V2rayStreamSettings::BuildStreamSettingsSingBox(QJsonObject *outbound) { - // https://sing-box.sagernet.org/configuration/shared/v2ray-transport - - if (network != "tcp") { - QJsonObject transport{{"type", network}}; - if (network == "ws") { - if (!host.isEmpty()) transport["headers"] = QJsonObject{{"Host", host}}; - // ws path & ed - auto pathWithoutEd = SubStrBefore(path, "?ed="); - if (!pathWithoutEd.isEmpty()) transport["path"] = pathWithoutEd; - if (pathWithoutEd != path) { - auto ed = SubStrAfter(path, "?ed=").toInt(); - if (ed > 0) { - transport["max_early_data"] = ed; - transport["early_data_header_name"] = "Sec-WebSocket-Protocol"; - } - } - if (ws_early_data_length > 0) { - transport["max_early_data"] = ws_early_data_length; - transport["early_data_header_name"] = ws_early_data_name; - } - } else if (network == "http") { - if (!path.isEmpty()) transport["path"] = path; - if (!host.isEmpty()) transport["host"] = QList2QJsonArray(host.split(",")); - } else if (network == "grpc") { - if (!path.isEmpty()) transport["service_name"] = path; - } else if (network == "httpupgrade") { - if (!path.isEmpty()) transport["path"] = path; - if (!host.isEmpty()) transport["host"] = host; - } - outbound->insert("transport", transport); - } else if (header_type == "http") { - // TCP + headerType - QJsonObject transport{ - {"type", "http"}, - {"method", "GET"}, - {"path", path}, - {"headers", QJsonObject{{"Host", QList2QJsonArray(host.split(","))}}}, - }; - outbound->insert("transport", transport); - } - - // 对应字段 tls - if (security == "tls") { - QJsonObject tls{{"enabled", true}}; - if (allow_insecure || NekoGui::dataStore->skip_cert) tls["insecure"] = true; - if (!sni.trimmed().isEmpty()) tls["server_name"] = sni; - if (!certificate.trimmed().isEmpty()) { - tls["certificate"] = certificate.trimmed(); - } - if (!alpn.trimmed().isEmpty()) { - tls["alpn"] = QList2QJsonArray(alpn.split(",")); - } - QString fp = utlsFingerprint; - if (!reality_pbk.trimmed().isEmpty()) { - tls["reality"] = QJsonObject{ - {"enabled", true}, - {"public_key", reality_pbk}, - {"short_id", reality_sid.split(",")[0]}, - }; - if (fp.isEmpty()) fp = "random"; - } - if (!fp.isEmpty()) { - tls["utls"] = QJsonObject{ - {"enabled", true}, - {"fingerprint", fp}, - }; - } - outbound->insert("tls", tls); - } - - if (outbound->value("type").toString() == "vmess" || outbound->value("type").toString() == "vless") { - outbound->insert("packet_encoding", packet_encoding); - } - } - - CoreObjOutboundBuildResult SocksHttpBean::BuildCoreObjSingBox() { - CoreObjOutboundBuildResult result; - - QJsonObject outbound; - outbound["type"] = socks_http_type == type_HTTP ? "http" : "socks"; - if (socks_http_type == type_Socks4) outbound["version"] = "4"; - outbound["server"] = serverAddress; - outbound["server_port"] = serverPort; - - if (!username.isEmpty() && !password.isEmpty()) { - outbound["username"] = username; - outbound["password"] = password; - } - - stream->BuildStreamSettingsSingBox(&outbound); - result.outbound = outbound; - return result; - } - - CoreObjOutboundBuildResult ShadowSocksBean::BuildCoreObjSingBox() { - CoreObjOutboundBuildResult result; - - QJsonObject outbound{{"type", "shadowsocks"}}; - outbound["server"] = serverAddress; - outbound["server_port"] = serverPort; - outbound["method"] = method; - outbound["password"] = password; - - if (uot != 0) { - QJsonObject udp_over_tcp{ - {"enabled", true}, - {"version", uot}, - }; - outbound["udp_over_tcp"] = udp_over_tcp; - } else { - outbound["udp_over_tcp"] = false; - } - - if (!plugin.trimmed().isEmpty()) { - outbound["plugin"] = SubStrBefore(plugin, ";"); - outbound["plugin_opts"] = SubStrAfter(plugin, ";"); - } - - stream->BuildStreamSettingsSingBox(&outbound); - result.outbound = outbound; - return result; - } - - CoreObjOutboundBuildResult VMessBean::BuildCoreObjSingBox() { - CoreObjOutboundBuildResult result; - - QJsonObject outbound{ - {"type", "vmess"}, - {"server", serverAddress}, - {"server_port", serverPort}, - {"uuid", uuid.trimmed()}, - {"alter_id", aid}, - {"security", security}, - }; - - stream->BuildStreamSettingsSingBox(&outbound); - result.outbound = outbound; - return result; - } - - CoreObjOutboundBuildResult TrojanVLESSBean::BuildCoreObjSingBox() { - CoreObjOutboundBuildResult result; - - QJsonObject outbound{ - {"type", proxy_type == proxy_VLESS ? "vless" : "trojan"}, - {"server", serverAddress}, - {"server_port", serverPort}, - }; - - QJsonObject settings; - if (proxy_type == proxy_VLESS) { - if (flow.right(7) == "-udp443") { - // 检查末尾是否包含"-udp443",如果是,则删去 - flow.chop(7); - } else if (flow == "none") { - // 不使用 flow - flow = ""; - } - outbound["uuid"] = password.trimmed(); - outbound["flow"] = flow; - } else { - outbound["password"] = password; - } - - stream->BuildStreamSettingsSingBox(&outbound); - result.outbound = outbound; - return result; - } - - CoreObjOutboundBuildResult QUICBean::BuildCoreObjSingBox() { - CoreObjOutboundBuildResult result; - - QJsonObject coreTlsObj{ - {"enabled", true}, - {"disable_sni", disableSni}, - {"insecure", allowInsecure}, - {"certificate", caText.trimmed()}, - {"server_name", sni}, - }; - if (!alpn.trimmed().isEmpty()) coreTlsObj["alpn"] = QList2QJsonArray(alpn.split(",")); - if (proxy_type == proxy_Hysteria2) coreTlsObj["alpn"] = "h3"; - - QJsonObject outbound{ - {"server", serverAddress}, - {"server_port", serverPort}, - {"tls", coreTlsObj}, - }; - - if (proxy_type == proxy_Hysteria2) { - outbound["type"] = "hysteria2"; - outbound["password"] = password; - outbound["up_mbps"] = uploadMbps; - outbound["down_mbps"] = downloadMbps; - - if (!hopPort.trimmed().isEmpty()) { - outbound["hop_ports"] = hopPort; - outbound["hop_interval"] = hopInterval; - } - if (!obfsPassword.isEmpty()) { - outbound["obfs"] = QJsonObject{ - {"type", "salamander"}, - {"password", obfsPassword}, - }; - } - } else if (proxy_type == proxy_TUIC) { - outbound["type"] = "tuic"; - outbound["uuid"] = uuid; - outbound["password"] = password; - outbound["congestion_control"] = congestionControl; - if (uos) { - outbound["udp_over_stream"] = true; - } else { - outbound["udp_relay_mode"] = udpRelayMode; - } - outbound["zero_rtt_handshake"] = zeroRttHandshake; - if (!heartbeat.trimmed().isEmpty()) outbound["heartbeat"] = heartbeat; - } - - result.outbound = outbound; - return result; - } - - CoreObjOutboundBuildResult CustomBean::BuildCoreObjSingBox() { - CoreObjOutboundBuildResult result; - - if (core == "internal") { - result.outbound = QString2QJsonObject(config_simple); - } - - return result; - } -} // namespace NekoGui_fmt diff --git a/fmt/Bean2External.cpp b/fmt/Bean2External.cpp deleted file mode 100644 index c58a651..0000000 --- a/fmt/Bean2External.cpp +++ /dev/null @@ -1,265 +0,0 @@ -#include "db/ProxyEntity.hpp" -#include "fmt/includes.h" - -#include -#include -#include -#include - -#define WriteTempFile(fn, data) \ - QDir dir; \ - if (!dir.exists("temp")) dir.mkdir("temp"); \ - QFile f(QStringLiteral("temp/") + fn); \ - bool ok = f.open(QIODevice::WriteOnly | QIODevice::Truncate); \ - if (ok) { \ - f.write(data); \ - } else { \ - result.error = f.errorString(); \ - } \ - f.close(); \ - auto TempFile = QFileInfo(f).absoluteFilePath(); - -namespace NekoGui_fmt { - // -1: Cannot use this config - // 0: Internal - // 1: Mapping External - // 2: Direct External - - int NaiveBean::NeedExternal(bool isFirstProfile) { - if (isFirstProfile) { - if (NekoGui::dataStore->spmode_vpn) { - return 1; - } - return 2; - } - return 1; - } - - int QUICBean::NeedExternal(bool isFirstProfile) { - auto extCore = [=] { - if (isFirstProfile) { - if (NekoGui::dataStore->spmode_vpn && hopPort.trimmed().isEmpty()) { - return 1; - } - return 2; - } else { - if (!hopPort.trimmed().isEmpty()) { - return -1; - } - } - return 1; - }; - - if (!forceExternal) { - // sing-box support - return 0; - } else { - // external core support - return extCore(); - } - } - - int CustomBean::NeedExternal(bool isFirstProfile) { - if (core == "internal" || core == "internal-full") return 0; - return 1; - } - - ExternalBuildResult NaiveBean::BuildExternal(int mapping_port, int socks_port, int external_stat) { - ExternalBuildResult result{NekoGui::dataStore->extraCore->Get("naive")}; - - auto is_direct = external_stat == 2; - auto domain_address = sni.isEmpty() ? serverAddress : sni; - auto connect_address = is_direct ? serverAddress : "127.0.0.1"; - auto connect_port = is_direct ? serverPort : mapping_port; - domain_address = WrapIPV6Host(domain_address); - connect_address = WrapIPV6Host(connect_address); - - auto proxy_url = QUrl(); - proxy_url.setScheme(protocol); - proxy_url.setUserName(username); - proxy_url.setPassword(password); - proxy_url.setPort(connect_port); - proxy_url.setHost(domain_address); - - if (!disable_log) result.arguments += "--log"; - result.arguments += "--listen=socks://127.0.0.1:" + Int2String(socks_port); - result.arguments += "--proxy=" + proxy_url.toString(QUrl::FullyEncoded); - if (domain_address != connect_address) - result.arguments += "--host-resolver-rules=MAP " + domain_address + " " + connect_address; - if (insecure_concurrency > 0) result.arguments += "--insecure-concurrency=" + Int2String(insecure_concurrency); - if (!extra_headers.trimmed().isEmpty()) result.arguments += "--extra-headers=" + extra_headers; - if (!certificate.trimmed().isEmpty()) { - WriteTempFile("naive_" + GetRandomString(10) + ".crt", certificate.toUtf8()); - result.env += "SSL_CERT_FILE=" + TempFile; - } - - auto config_export = QStringList{result.program}; - config_export += result.arguments; - result.config_export = QStringList2Command(config_export); - - return result; - } - - ExternalBuildResult QUICBean::BuildExternal(int mapping_port, int socks_port, int external_stat) { - if (proxy_type == proxy_TUIC) { - ExternalBuildResult result{NekoGui::dataStore->extraCore->Get("tuic")}; - - QJsonObject relay; - - relay["uuid"] = uuid; - relay["password"] = password; - relay["udp_relay_mode"] = udpRelayMode; - relay["congestion_control"] = congestionControl; - relay["zero_rtt_handshake"] = zeroRttHandshake; - relay["disable_sni"] = disableSni; - if (!heartbeat.trimmed().isEmpty()) relay["heartbeat"] = heartbeat; - if (!alpn.trimmed().isEmpty()) relay["alpn"] = QList2QJsonArray(alpn.split(",")); - - if (!caText.trimmed().isEmpty()) { - WriteTempFile("tuic_" + GetRandomString(10) + ".crt", caText.toUtf8()); - QJsonArray certificate; - certificate.append(TempFile); - relay["certificates"] = certificate; - } - - // The most confused part of TUIC...... - if (serverAddress == sni) { - relay["server"] = serverAddress + ":" + Int2String(serverPort); - } else { - relay["server"] = sni + ":" + Int2String(serverPort); - relay["ip"] = serverAddress; - } - - QJsonObject local{ - {"server", "127.0.0.1:" + Int2String(socks_port)}, - }; - - QJsonObject config{ - {"relay", relay}, - {"local", local}, - }; - - // - - result.config_export = QJsonObject2QString(config, false); - WriteTempFile("tuic_" + GetRandomString(10) + ".json", result.config_export.toUtf8()); - result.arguments = QStringList{"-c", TempFile}; - - return result; - } else if (proxy_type == proxy_Hysteria2) { - ExternalBuildResult result{NekoGui::dataStore->extraCore->Get("hysteria2")}; - - QJsonObject config; - - auto server = serverAddress; - if (!hopPort.trimmed().isEmpty()) { - server = WrapIPV6Host(server) + ":" + hopPort; - } else { - server = WrapIPV6Host(server) + ":" + Int2String(serverPort); - } - - QJsonObject transport; - transport["type"] = "udp"; - transport["udp"] = QJsonObject{ - {"hopInterval", QString::number(hopInterval) + "s"}, - }; - config["transport"] = transport; - - config["server"] = server; - config["socks5"] = QJsonObject{ - {"listen", "127.0.0.1:" + Int2String(socks_port)}, - {"disableUDP", false}, - }; - config["auth"] = password; - - QJsonObject bandwidth; - if (uploadMbps > 0) bandwidth["up"] = Int2String(uploadMbps) + " mbps"; - if (downloadMbps > 0) bandwidth["down"] = Int2String(downloadMbps) + " mbps"; - config["bandwidth"] = bandwidth; - - QJsonObject quic; - if (streamReceiveWindow > 0) quic["initStreamReceiveWindow"] = streamReceiveWindow; - if (connectionReceiveWindow > 0) quic["initConnReceiveWindow"] = connectionReceiveWindow; - if (disableMtuDiscovery) quic["disablePathMTUDiscovery"] = true; - config["quic"] = quic; - - config["fastOpen"] = true; - config["lazy"] = true; - - if (!obfsPassword.isEmpty()) { - QJsonObject obfs; - obfs["type"] = "salamander"; - obfs["salamander"] = QJsonObject{ - {"password", obfsPassword}, - }; - - config["obfs"] = obfs; - } - - QJsonObject tls; - auto sniGen = sni; - if (sni.isEmpty() && !IsIpAddress(serverAddress)) sniGen = serverAddress; - tls["sni"] = sniGen; - if (allowInsecure) tls["insecure"] = true; - if (!caText.trimmed().isEmpty()) { - WriteTempFile("hysteria2_" + GetRandomString(10) + ".crt", caText.toUtf8()); - QJsonArray certificate; - certificate.append(TempFile); - tls["certificates"] = certificate; - } - config["tls"] = tls; - - result.config_export = QJsonObject2QString(config, false); - WriteTempFile("hysteria2_" + GetRandomString(10) + ".json", result.config_export.toUtf8()); - result.arguments = QStringList{"-c", TempFile}; - - return result; - } - ExternalBuildResult e; - e.error = "unknown type"; - return e; - } - - ExternalBuildResult CustomBean::BuildExternal(int mapping_port, int socks_port, int external_stat) { - ExternalBuildResult result{NekoGui::dataStore->extraCore->Get(core)}; - - result.arguments = command; // TODO split? - - for (int i = 0; i < result.arguments.length(); i++) { - auto arg = result.arguments[i]; - arg = arg.replace("%mapping_port%", Int2String(mapping_port)); - arg = arg.replace("%socks_port%", Int2String(socks_port)); - arg = arg.replace("%server_addr%", serverAddress); - arg = arg.replace("%server_port%", Int2String(serverPort)); - result.arguments[i] = arg; - } - - if (!config_simple.trimmed().isEmpty()) { - auto config = config_simple; - config = config.replace("%mapping_port%", Int2String(mapping_port)); - config = config.replace("%socks_port%", Int2String(socks_port)); - config = config.replace("%server_addr%", serverAddress); - config = config.replace("%server_port%", Int2String(serverPort)); - - // suffix - QString suffix; - if (!config_suffix.isEmpty()) { - suffix = "." + config_suffix; - } else if (!QString2QJsonObject(config).isEmpty()) { - // trojan-go: unsupported config format: xxx.tmp. use .yaml or .json instead. - suffix = ".json"; - } - - // write config - WriteTempFile("custom_" + GetRandomString(10) + suffix, config.toUtf8()); - for (int i = 0; i < result.arguments.count(); i++) { - result.arguments[i] = result.arguments[i].replace("%config%", TempFile); - } - - result.config_export = config; - } - - return result; - } - -} // namespace NekoGui_fmt diff --git a/fmt/Bean2Link.cpp b/fmt/Bean2Link.cpp deleted file mode 100644 index f194259..0000000 --- a/fmt/Bean2Link.cpp +++ /dev/null @@ -1,225 +0,0 @@ -#include "db/ProxyEntity.hpp" -#include "fmt/includes.h" - -#include - -namespace NekoGui_fmt { - QString SocksHttpBean::ToShareLink() { - QUrl url; - if (socks_http_type == type_HTTP) { // http - if (stream->security == "tls") { - url.setScheme("https"); - } else { - url.setScheme("http"); - } - } else { - url.setScheme(QStringLiteral("socks%1").arg(socks_http_type)); - } - if (!name.isEmpty()) url.setFragment(name); - if (!username.isEmpty()) url.setUserName(username); - if (!password.isEmpty()) url.setPassword(password); - url.setHost(serverAddress); - url.setPort(serverPort); - return url.toString(QUrl::FullyEncoded); - } - - QString TrojanVLESSBean::ToShareLink() { - QUrl url; - QUrlQuery query; - url.setScheme(proxy_type == proxy_VLESS ? "vless" : "trojan"); - url.setUserName(password); - url.setHost(serverAddress); - url.setPort(serverPort); - if (!name.isEmpty()) url.setFragment(name); - - // security - auto security = stream->security; - if (security == "tls" && !stream->reality_pbk.trimmed().isEmpty()) security = "reality"; - query.addQueryItem("security", security); - - if (!stream->sni.isEmpty()) query.addQueryItem("sni", stream->sni); - if (!stream->alpn.isEmpty()) query.addQueryItem("alpn", stream->alpn); - if (stream->allow_insecure) query.addQueryItem("allowInsecure", "1"); - if (!stream->utlsFingerprint.isEmpty()) query.addQueryItem("fp", stream->utlsFingerprint); - - if (security == "reality") { - query.addQueryItem("pbk", stream->reality_pbk); - if (!stream->reality_sid.isEmpty()) query.addQueryItem("sid", stream->reality_sid); - if (!stream->reality_spx.isEmpty()) query.addQueryItem("spx", stream->reality_spx); - } - - // type - query.addQueryItem("type", stream->network); - - if (stream->network == "ws" || stream->network == "http" || stream->network == "httpupgrade") { - if (!stream->path.isEmpty()) query.addQueryItem("path", stream->path); - if (!stream->host.isEmpty()) query.addQueryItem("host", stream->host); - } else if (stream->network == "grpc") { - if (!stream->path.isEmpty()) query.addQueryItem("serviceName", stream->path); - } else if (stream->network == "tcp") { - if (stream->header_type == "http") { - if (!stream->path.isEmpty()) query.addQueryItem("path", stream->path); - query.addQueryItem("headerType", "http"); - query.addQueryItem("host", stream->host); - } - } - - // protocol - if (proxy_type == proxy_VLESS) { - if (!flow.isEmpty()) { - query.addQueryItem("flow", flow); - } - query.addQueryItem("encryption", "none"); - } - - url.setQuery(query); - return url.toString(QUrl::FullyEncoded); - } - - const char* fixShadowsocksUserNameEncodeMagic = "fixShadowsocksUserNameEncodeMagic-holder-for-QUrl"; - - QString ShadowSocksBean::ToShareLink() { - QUrl url; - url.setScheme("ss"); - if (method.startsWith("2022-")) { - url.setUserName(fixShadowsocksUserNameEncodeMagic); - } else { - auto method_password = method + ":" + password; - url.setUserName(method_password.toUtf8().toBase64(QByteArray::Base64Option::Base64UrlEncoding)); - } - url.setHost(serverAddress); - url.setPort(serverPort); - if (!name.isEmpty()) url.setFragment(name); - QUrlQuery q; - if (!plugin.isEmpty()) q.addQueryItem("plugin", plugin); - if (!q.isEmpty()) url.setQuery(q); - // - auto link = url.toString(QUrl::FullyEncoded); - link = link.replace(fixShadowsocksUserNameEncodeMagic, method + ":" + QUrl::toPercentEncoding(password)); - return link; - } - - QString VMessBean::ToShareLink() { - if (NekoGui::dataStore->old_share_link_format) { - // v2rayN format - QJsonObject N{ - {"v", "2"}, - {"ps", name}, - {"add", serverAddress}, - {"port", Int2String(serverPort)}, - {"id", uuid}, - {"aid", Int2String(aid)}, - {"net", stream->network}, - {"host", stream->host}, - {"path", stream->path}, - {"type", stream->header_type}, - {"scy", security}, - {"tls", stream->security == "tls" ? "tls" : ""}, - {"sni", stream->sni}, - }; - return "vmess://" + QJsonObject2QString(N, true).toUtf8().toBase64(); - } else { - // ducksoft format - QUrl url; - QUrlQuery query; - url.setScheme("vmess"); - url.setUserName(uuid); - url.setHost(serverAddress); - url.setPort(serverPort); - if (!name.isEmpty()) url.setFragment(name); - - query.addQueryItem("encryption", security); - - // security - auto security = stream->security; - if (security == "tls" && !stream->reality_pbk.trimmed().isEmpty()) security = "reality"; - query.addQueryItem("security", security); - - if (!stream->sni.isEmpty()) query.addQueryItem("sni", stream->sni); - if (stream->allow_insecure) query.addQueryItem("allowInsecure", "1"); - if (stream->utlsFingerprint.isEmpty()) { - query.addQueryItem("fp", NekoGui::dataStore->utlsFingerprint); - } else { - query.addQueryItem("fp", stream->utlsFingerprint); - } - - if (security == "reality") { - query.addQueryItem("pbk", stream->reality_pbk); - if (!stream->reality_sid.isEmpty()) query.addQueryItem("sid", stream->reality_sid); - if (!stream->reality_spx.isEmpty()) query.addQueryItem("spx", stream->reality_spx); - } - - // type - query.addQueryItem("type", stream->network); - - if (stream->network == "ws" || stream->network == "http" || stream->network == "httpupgrade") { - if (!stream->path.isEmpty()) query.addQueryItem("path", stream->path); - if (!stream->host.isEmpty()) query.addQueryItem("host", stream->host); - } else if (stream->network == "grpc") { - if (!stream->path.isEmpty()) query.addQueryItem("serviceName", stream->path); - } else if (stream->network == "tcp") { - if (stream->header_type == "http") { - query.addQueryItem("headerType", "http"); - query.addQueryItem("host", stream->host); - } - } - - url.setQuery(query); - return url.toString(QUrl::FullyEncoded); - } - } - - QString NaiveBean::ToShareLink() { - QUrl url; - url.setScheme("naive+" + protocol); - url.setUserName(username); - url.setPassword(password); - url.setHost(serverAddress); - url.setPort(serverPort); - if (!name.isEmpty()) url.setFragment(name); - return url.toString(QUrl::FullyEncoded); - } - - QString QUICBean::ToShareLink() { - QUrl url; - if (proxy_type == proxy_TUIC) { - url.setScheme("tuic"); - url.setUserName(uuid); - url.setPassword(password); - url.setHost(serverAddress); - url.setPort(serverPort); - - QUrlQuery q; - if (!congestionControl.isEmpty()) q.addQueryItem("congestion_control", congestionControl); - if (!alpn.isEmpty()) q.addQueryItem("alpn", alpn); - if (!sni.isEmpty()) q.addQueryItem("sni", sni); - if (!udpRelayMode.isEmpty()) q.addQueryItem("udp_relay_mode", udpRelayMode); - if (allowInsecure) q.addQueryItem("allow_insecure", "1"); - if (disableSni) q.addQueryItem("disable_sni", "1"); - if (!q.isEmpty()) url.setQuery(q); - if (!name.isEmpty()) url.setFragment(name); - } else if (proxy_type == proxy_Hysteria2) { - url.setScheme("hy2"); - url.setHost(serverAddress); - url.setPort(serverPort); - if (password.contains(":")) { - url.setUserName(SubStrBefore(password, ":")); - url.setPassword(SubStrAfter(password, ":")); - } else { - url.setUserName(password); - } - QUrlQuery q; - if (!obfsPassword.isEmpty()) { - q.addQueryItem("obfs", "salamander"); - q.addQueryItem("obfs-password", obfsPassword); - } - if (!hopPort.trimmed().isEmpty()) q.addQueryItem("mport", hopPort); - if (allowInsecure) q.addQueryItem("insecure", "1"); - if (!sni.isEmpty()) q.addQueryItem("sni", sni); - if (!q.isEmpty()) url.setQuery(q); - if (!name.isEmpty()) url.setFragment(name); - } - return url.toString(QUrl::FullyEncoded); - } - -} // namespace NekoGui_fmt diff --git a/fmt/ChainBean.hpp b/fmt/ChainBean.hpp deleted file mode 100644 index 27f14ab..0000000 --- a/fmt/ChainBean.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include "main/NekoGui.hpp" - -namespace NekoGui_fmt { - class ChainBean : public AbstractBean { - public: - QList list; // in to out - - ChainBean() : AbstractBean(0) { - _add(new configItem("list", &list, itemType::integerList)); - }; - - QString DisplayType() override { return QObject::tr("Chain Proxy"); }; - - QString DisplayAddress() override { return ""; }; - }; -} // namespace NekoGui_fmt diff --git a/fmt/CustomBean.hpp b/fmt/CustomBean.hpp deleted file mode 100644 index 926e50d..0000000 --- a/fmt/CustomBean.hpp +++ /dev/null @@ -1,52 +0,0 @@ -#pragma once - -#include "fmt/AbstractBean.hpp" - -namespace NekoGui_fmt { - class CustomBean : public AbstractBean { - public: - QString core; - QList command; - QString config_suffix; - QString config_simple; - int mapping_port = 0; - int socks_port = 0; - - CustomBean() : AbstractBean(0) { - _add(new configItem("core", &core, itemType::string)); - _add(new configItem("cmd", &command, itemType::stringList)); - _add(new configItem("cs", &config_simple, itemType::string)); - _add(new configItem("cs_suffix", &config_suffix, itemType::string)); - _add(new configItem("mapping_port", &mapping_port, itemType::integer)); - _add(new configItem("socks_port", &socks_port, itemType::integer)); - }; - - QString DisplayType() override { - if (core == "internal") { - auto obj = QString2QJsonObject(config_simple); - return obj["type"].toString(); - } else if (core == "internal-full") { - return software_core_name + " config"; - } - return core; - }; - - QString DisplayCoreType() override { return NeedExternal(true) == 0 ? software_core_name : core; }; - - QString DisplayAddress() override { - if (core == "internal") { - auto obj = QString2QJsonObject(config_simple); - return ::DisplayAddress(obj["server"].toString(), obj["server_port"].toInt()); - } else if (core == "internal-full") { - return {}; - } - return AbstractBean::DisplayAddress(); - }; - - int NeedExternal(bool isFirstProfile) override; - - ExternalBuildResult BuildExternal(int mapping_port, int socks_port, int external_stat) override; - - CoreObjOutboundBuildResult BuildCoreObjSingBox() override; - }; -} // namespace NekoGui_fmt \ No newline at end of file diff --git a/fmt/Link2Bean.cpp b/fmt/Link2Bean.cpp deleted file mode 100644 index f5d9e0d..0000000 --- a/fmt/Link2Bean.cpp +++ /dev/null @@ -1,297 +0,0 @@ -#include "db/ProxyEntity.hpp" -#include "fmt/includes.h" - -#include - -namespace NekoGui_fmt { - -#define DECODE_V2RAY_N_1 \ - QString linkN = DecodeB64IfValid(SubStrBefore(SubStrAfter(link, "://"), "#"), QByteArray::Base64Option::Base64UrlEncoding); \ - if (linkN.isEmpty()) return false; \ - auto hasRemarks = link.contains("#"); \ - if (hasRemarks) linkN += "#" + SubStrAfter(link, "#"); \ - auto url = QUrl("https://" + linkN); - - bool SocksHttpBean::TryParseLink(const QString &link) { - auto url = QUrl(link); - if (!url.isValid()) return false; - auto query = GetQuery(url); - - if (link.startsWith("socks4")) socks_http_type = type_Socks4; - if (link.startsWith("http")) socks_http_type = type_HTTP; - name = url.fragment(QUrl::FullyDecoded); - serverAddress = url.host(); - serverPort = url.port(); - username = url.userName(); - password = url.password(); - if (serverPort == -1) serverPort = socks_http_type == type_HTTP ? 443 : 1080; - - // v2rayN fmt - if (password.isEmpty() && !username.isEmpty()) { - QString n = DecodeB64IfValid(username); - if (!n.isEmpty()) { - username = SubStrBefore(n, ":"); - password = SubStrAfter(n, ":"); - } - } - - stream->security = GetQueryValue(query, "security", ""); - stream->sni = GetQueryValue(query, "sni"); - if (link.startsWith("https")) stream->security = "tls"; - - return !serverAddress.isEmpty(); - } - - bool TrojanVLESSBean::TryParseLink(const QString &link) { - auto url = QUrl(link); - if (!url.isValid()) return false; - auto query = GetQuery(url); - - name = url.fragment(QUrl::FullyDecoded); - serverAddress = url.host(); - serverPort = url.port(); - password = url.userName(); - if (serverPort == -1) serverPort = 443; - - // security - - auto type = GetQueryValue(query, "type", "tcp"); - if (type == "h2") { - type = "http"; - } - stream->network = type; - - if (proxy_type == proxy_Trojan) { - stream->security = GetQueryValue(query, "security", "tls").replace("reality", "tls").replace("none", ""); - } else { - stream->security = GetQueryValue(query, "security", "").replace("reality", "tls").replace("none", ""); - } - auto sni1 = GetQueryValue(query, "sni"); - auto sni2 = GetQueryValue(query, "peer"); - if (!sni1.isEmpty()) stream->sni = sni1; - if (!sni2.isEmpty()) stream->sni = sni2; - stream->alpn = GetQueryValue(query, "alpn"); - if (!query.queryItemValue("allowInsecure").isEmpty()) stream->allow_insecure = true; - stream->reality_pbk = GetQueryValue(query, "pbk", ""); - stream->reality_sid = GetQueryValue(query, "sid", ""); - stream->reality_spx = GetQueryValue(query, "spx", ""); - stream->utlsFingerprint = GetQueryValue(query, "fp", ""); - if (stream->utlsFingerprint.isEmpty()) { - stream->utlsFingerprint = NekoGui::dataStore->utlsFingerprint; - } - - // type - if (stream->network == "ws") { - stream->path = GetQueryValue(query, "path", ""); - stream->host = GetQueryValue(query, "host", ""); - } else if (stream->network == "http") { - stream->path = GetQueryValue(query, "path", ""); - stream->host = GetQueryValue(query, "host", "").replace("|", ","); - } else if (stream->network == "httpupgrade") { - stream->path = GetQueryValue(query, "path", ""); - stream->host = GetQueryValue(query, "host", ""); - } else if (stream->network == "grpc") { - stream->path = GetQueryValue(query, "serviceName", ""); - } else if (stream->network == "tcp") { - if (GetQueryValue(query, "headerType") == "http") { - stream->header_type = "http"; - stream->host = GetQueryValue(query, "host", ""); - stream->path = GetQueryValue(query, "path", ""); - } - } - - // protocol - if (proxy_type == proxy_VLESS) { - flow = GetQueryValue(query, "flow", ""); - } - - return !(password.isEmpty() || serverAddress.isEmpty()); - } - - bool ShadowSocksBean::TryParseLink(const QString &link) { - if (SubStrBefore(link, "#").contains("@")) { - // SS - auto url = QUrl(link); - if (!url.isValid()) return false; - - name = url.fragment(QUrl::FullyDecoded); - serverAddress = url.host(); - serverPort = url.port(); - - if (url.password().isEmpty()) { - // traditional format - auto method_password = DecodeB64IfValid(url.userName(), QByteArray::Base64Option::Base64UrlEncoding); - if (method_password.isEmpty()) return false; - method = SubStrBefore(method_password, ":"); - password = SubStrAfter(method_password, ":"); - } else { - // 2022 format - method = url.userName(); - password = url.password(); - } - - auto query = GetQuery(url); - plugin = query.queryItemValue("plugin").replace("simple-obfs;", "obfs-local;"); - } else { - // v2rayN - DECODE_V2RAY_N_1 - - if (hasRemarks) name = url.fragment(QUrl::FullyDecoded); - serverAddress = url.host(); - serverPort = url.port(); - method = url.userName(); - password = url.password(); - } - return !(serverAddress.isEmpty() || method.isEmpty() || password.isEmpty()); - } - - bool VMessBean::TryParseLink(const QString &link) { - // V2RayN Format - auto linkN = DecodeB64IfValid(SubStrAfter(link, "vmess://")); - if (!linkN.isEmpty()) { - auto objN = QString2QJsonObject(linkN); - if (objN.isEmpty()) return false; - // REQUIRED - uuid = objN["id"].toString(); - serverAddress = objN["add"].toString(); - serverPort = objN["port"].toVariant().toInt(); - // OPTIONAL - name = objN["ps"].toString(); - aid = objN["aid"].toVariant().toInt(); - stream->host = objN["host"].toString(); - stream->path = objN["path"].toString(); - stream->sni = objN["sni"].toString(); - stream->header_type = objN["type"].toString(); - auto net = objN["net"].toString(); - if (!net.isEmpty()) { - if (net == "h2") { - net = "http"; - } - stream->network = net; - } - auto scy = objN["scy"].toString(); - if (!scy.isEmpty()) security = scy; - // TLS (XTLS?) - stream->security = objN["tls"].toString(); - // TODO quic & kcp - return true; - } else { - // https://github.com/XTLS/Xray-core/discussions/716 - auto url = QUrl(link); - if (!url.isValid()) return false; - auto query = GetQuery(url); - - name = url.fragment(QUrl::FullyDecoded); - serverAddress = url.host(); - serverPort = url.port(); - uuid = url.userName(); - if (serverPort == -1) serverPort = 443; - - aid = 0; // “此分享标准仅针对 VMess AEAD 和 VLESS。” - security = GetQueryValue(query, "encryption", "auto"); - - // security - auto type = GetQueryValue(query, "type", "tcp"); - if (type == "h2") { - type = "http"; - } - stream->network = type; - stream->security = GetQueryValue(query, "security", "tls").replace("reality", "tls"); - auto sni1 = GetQueryValue(query, "sni"); - auto sni2 = GetQueryValue(query, "peer"); - if (!sni1.isEmpty()) stream->sni = sni1; - if (!sni2.isEmpty()) stream->sni = sni2; - if (!query.queryItemValue("allowInsecure").isEmpty()) stream->allow_insecure = true; - stream->reality_pbk = GetQueryValue(query, "pbk", ""); - stream->reality_sid = GetQueryValue(query, "sid", ""); - stream->reality_spx = GetQueryValue(query, "spx", ""); - stream->utlsFingerprint = GetQueryValue(query, "fp", ""); - if (stream->utlsFingerprint.isEmpty()) { - stream->utlsFingerprint = NekoGui::dataStore->utlsFingerprint; - } - - // type - if (stream->network == "ws") { - stream->path = GetQueryValue(query, "path", ""); - stream->host = GetQueryValue(query, "host", ""); - } else if (stream->network == "http") { - stream->path = GetQueryValue(query, "path", ""); - stream->host = GetQueryValue(query, "host", "").replace("|", ","); - } else if (stream->network == "httpupgrade") { - stream->path = GetQueryValue(query, "path", ""); - stream->host = GetQueryValue(query, "host", ""); - } else if (stream->network == "grpc") { - stream->path = GetQueryValue(query, "serviceName", ""); - } else if (stream->network == "tcp") { - if (GetQueryValue(query, "headerType") == "http") { - stream->header_type = "http"; - stream->path = GetQueryValue(query, "path", ""); - stream->host = GetQueryValue(query, "host", ""); - } - } - return !(uuid.isEmpty() || serverAddress.isEmpty()); - } - - return false; - } - - bool NaiveBean::TryParseLink(const QString &link) { - auto url = QUrl(link); - if (!url.isValid()) return false; - - protocol = url.scheme().replace("naive+", ""); - if (protocol != "https" && protocol != "quic") return false; - - name = url.fragment(QUrl::FullyDecoded); - serverAddress = url.host(); - serverPort = url.port(); - username = url.userName(); - password = url.password(); - - return !(username.isEmpty() || password.isEmpty() || serverAddress.isEmpty()); - } - - bool QUICBean::TryParseLink(const QString &link) { - auto url = QUrl(link); - auto query = QUrlQuery(url.query()); - if (url.host().isEmpty() || url.port() == -1) return false; - - if (url.scheme() == "tuic") { - // by daeuniverse - // https://github.com/daeuniverse/dae/discussions/182 - - name = url.fragment(QUrl::FullyDecoded); - serverAddress = url.host(); - if (serverPort == -1) serverPort = 443; - serverPort = url.port(); - - uuid = url.userName(); - password = url.password(); - - congestionControl = query.queryItemValue("congestion_control"); - alpn = query.queryItemValue("alpn"); - sni = query.queryItemValue("sni"); - udpRelayMode = query.queryItemValue("udp_relay_mode"); - allowInsecure = query.queryItemValue("allow_insecure") == "1"; - disableSni = query.queryItemValue("disable_sni") == "1"; - } else if (QStringList{"hy2", "hysteria2"}.contains(url.scheme())) { - name = url.fragment(QUrl::FullyDecoded); - serverAddress = url.host(); - serverPort = url.port(); - hopPort = query.queryItemValue("mport"); - obfsPassword = query.queryItemValue("obfs-password"); - allowInsecure = QStringList{"1", "true"}.contains(query.queryItemValue("insecure")); - - if (url.password().isEmpty()) { - password = url.userName(); - } else { - password = url.userName() + ":" + url.password(); - } - - sni = query.queryItemValue("sni"); - } - - return true; - } - -} // namespace NekoGui_fmt \ No newline at end of file diff --git a/fmt/NaiveBean.hpp b/fmt/NaiveBean.hpp deleted file mode 100644 index 85e9b35..0000000 --- a/fmt/NaiveBean.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include "fmt/AbstractBean.hpp" - -namespace NekoGui_fmt { - class NaiveBean : public AbstractBean { - public: - QString username = ""; - QString password = ""; - QString protocol = "https"; - QString extra_headers = ""; - QString sni = ""; - QString certificate = ""; - int insecure_concurrency = 0; - - bool disable_log = false; - - NaiveBean() : AbstractBean(0) { - _add(new configItem("username", &username, itemType::string)); - _add(new configItem("password", &password, itemType::string)); - _add(new configItem("protocol", &protocol, itemType::string)); - _add(new configItem("extra_headers", &extra_headers, itemType::string)); - _add(new configItem("sni", &sni, itemType::string)); - _add(new configItem("certificate", &certificate, itemType::string)); - _add(new configItem("insecure_concurrency", &insecure_concurrency, itemType::integer)); - _add(new configItem("disable_log", &disable_log, itemType::boolean)); - }; - - QString DisplayCoreType() override { return "Naive"; }; - - QString DisplayType() override { return "Naive"; }; - - int NeedExternal(bool isFirstProfile) override; - - ExternalBuildResult BuildExternal(int mapping_port, int socks_port, int external_stat) override; - - bool TryParseLink(const QString &link); - - QString ToShareLink() override; - }; -} // namespace NekoGui_fmt \ No newline at end of file diff --git a/fmt/Preset.hpp b/fmt/Preset.hpp deleted file mode 100644 index 050a32e..0000000 --- a/fmt/Preset.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -namespace Preset { - namespace SingBox { - inline QStringList VpnImplementation = {"gvisor", "system", "mixed"}; - inline QStringList DomainStrategy = {"", "ipv4_only", "ipv6_only", "prefer_ipv4", "prefer_ipv6"}; - inline QStringList UtlsFingerPrint = {"", "chrome", "firefox", "edge", "safari", "360", "qq", "ios", "android", "random", "randomized"}; - inline QStringList ShadowsocksMethods = {"2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305", "none", "aes-128-gcm", "aes-192-gcm", "aes-256-gcm", "chacha20-ietf-poly1305", "xchacha20-ietf-poly1305", "aes-128-ctr", "aes-192-ctr", "aes-256-ctr", "aes-128-cfb", "aes-192-cfb", "aes-256-cfb", "rc4-md5", "chacha20-ietf", "xchacha20"}; - inline QStringList Flows = {"xtls-rprx-vision"}; - } // namespace SingBox - - namespace Windows { - inline QStringList system_proxy_format{"{ip}:{http_port}", - "socks={ip}:{socks_port}", - "http={ip}:{http_port};https={ip}:{http_port};ftp={ip}:{http_port};socks={ip}:{socks_port}", - "http=http://{ip}:{http_port};https=http://{ip}:{http_port}"}; - } // namespace Windows -} // namespace Preset diff --git a/fmt/QUICBean.hpp b/fmt/QUICBean.hpp deleted file mode 100644 index 9a18c63..0000000 --- a/fmt/QUICBean.hpp +++ /dev/null @@ -1,113 +0,0 @@ -#pragma once - -#include "fmt/AbstractBean.hpp" - -namespace NekoGui_fmt { - class QUICBean : public AbstractBean { - public: - // static constexpr int proxy_Hysteria = 0; - static constexpr int proxy_TUIC = 1; - static constexpr int proxy_Hysteria2 = 3; - int proxy_type = proxy_Hysteria2; - - bool forceExternal = false; - - // Hysteria 2 - - QString obfsPassword = ""; - - int uploadMbps = 0; - int downloadMbps = 0; - - qint64 streamReceiveWindow = 0; - qint64 connectionReceiveWindow = 0; - bool disableMtuDiscovery = false; - - int hopInterval = 10; - QString hopPort = ""; - - // TUIC - - QString uuid = ""; - QString congestionControl = "bbr"; - QString udpRelayMode = "native"; - bool zeroRttHandshake = false; - QString heartbeat = "10s"; - bool uos = false; - - // HY2&TUIC - - QString password = ""; - - // TLS - - bool allowInsecure = false; - QString sni = ""; - QString alpn = ""; - QString caText = ""; - bool disableSni = false; - - explicit QUICBean(int _proxy_type) : AbstractBean(0) { - proxy_type = _proxy_type; - if (proxy_type == proxy_Hysteria2) { - _add(new configItem("obfsPassword", &obfsPassword, itemType::string)); - _add(new configItem("uploadMbps", &uploadMbps, itemType::integer)); - _add(new configItem("downloadMbps", &downloadMbps, itemType::integer)); - _add(new configItem("streamReceiveWindow", &streamReceiveWindow, itemType::integer64)); - _add(new configItem("connectionReceiveWindow", &connectionReceiveWindow, itemType::integer64)); - _add(new configItem("disableMtuDiscovery", &disableMtuDiscovery, itemType::boolean)); - _add(new configItem("hopInterval", &hopInterval, itemType::integer)); - _add(new configItem("hopPort", &hopPort, itemType::string)); - _add(new configItem("password", &password, itemType::string)); - } else if (proxy_type == proxy_TUIC) { - _add(new configItem("uuid", &uuid, itemType::string)); - _add(new configItem("password", &password, itemType::string)); - _add(new configItem("congestionControl", &congestionControl, itemType::string)); - _add(new configItem("udpRelayMode", &udpRelayMode, itemType::string)); - _add(new configItem("zeroRttHandshake", &zeroRttHandshake, itemType::boolean)); - _add(new configItem("heartbeat", &heartbeat, itemType::string)); - _add(new configItem("uos", &uos, itemType::boolean)); - } - _add(new configItem("forceExternal", &forceExternal, itemType::boolean)); - // TLS - _add(new configItem("allowInsecure", &allowInsecure, itemType::boolean)); - _add(new configItem("sni", &sni, itemType::string)); - _add(new configItem("alpn", &alpn, itemType::string)); - _add(new configItem("caText", &caText, itemType::string)); - _add(new configItem("disableSni", &disableSni, itemType::boolean)); - }; - - QString DisplayAddress() override { - if (!hopPort.trimmed().isEmpty()) return WrapIPV6Host(serverAddress) + ":" + hopPort; - return ::DisplayAddress(serverAddress, serverPort); - } - - QString DisplayCoreType() override { - if (NeedExternal(true) == 0) { - return software_core_name; - } else if (proxy_type == proxy_TUIC) { - return "tuic"; - } else { - return "hysteria2"; - } - } - - QString DisplayType() override { - if (proxy_type == proxy_TUIC) { - return "TUIC"; - } else { - return "Hysteria2"; - } - }; - - int NeedExternal(bool isFirstProfile) override; - - ExternalBuildResult BuildExternal(int mapping_port, int socks_port, int external_stat) override; - - CoreObjOutboundBuildResult BuildCoreObjSingBox() override; - - bool TryParseLink(const QString &link); - - QString ToShareLink() override; - }; -} // namespace NekoGui_fmt \ No newline at end of file diff --git a/fmt/ShadowSocksBean.hpp b/fmt/ShadowSocksBean.hpp deleted file mode 100644 index becb684..0000000 --- a/fmt/ShadowSocksBean.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include "fmt/AbstractBean.hpp" -#include "fmt/V2RayStreamSettings.hpp" - -namespace NekoGui_fmt { - class ShadowSocksBean : public AbstractBean { - public: - QString method = "aes-128-gcm"; - QString password = ""; - QString plugin = ""; - int uot = 0; - - std::shared_ptr stream = std::make_shared(); - - ShadowSocksBean() : AbstractBean(0) { - _add(new configItem("method", &method, itemType::string)); - _add(new configItem("pass", &password, itemType::string)); - _add(new configItem("plugin", &plugin, itemType::string)); - _add(new configItem("uot", &uot, itemType::integer)); - _add(new configItem("stream", dynamic_cast(stream.get()), itemType::jsonStore)); - }; - - QString DisplayType() override { return "Shadowsocks"; }; - - CoreObjOutboundBuildResult BuildCoreObjSingBox() override; - - bool TryParseLink(const QString &link); - - QString ToShareLink() override; - }; -} // namespace NekoGui_fmt diff --git a/fmt/SocksHttpBean.hpp b/fmt/SocksHttpBean.hpp deleted file mode 100644 index 930a5f8..0000000 --- a/fmt/SocksHttpBean.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include "fmt/AbstractBean.hpp" -#include "fmt/V2RayStreamSettings.hpp" - -namespace NekoGui_fmt { - class SocksHttpBean : public AbstractBean { - public: - static constexpr int type_HTTP = -80; - static constexpr int type_Socks4 = 4; - static constexpr int type_Socks5 = 5; - - int socks_http_type = type_Socks5; - QString username = ""; - QString password = ""; - - std::shared_ptr stream = std::make_shared(); - - explicit SocksHttpBean(int _socks_http_type) : AbstractBean(0) { - this->socks_http_type = _socks_http_type; - _add(new configItem("v", &socks_http_type, itemType::integer)); - _add(new configItem("username", &username, itemType::string)); - _add(new configItem("password", &password, itemType::string)); - _add(new configItem("stream", dynamic_cast(stream.get()), itemType::jsonStore)); - }; - - QString DisplayType() override { return socks_http_type == type_HTTP ? "HTTP" : "Socks"; }; - - CoreObjOutboundBuildResult BuildCoreObjSingBox() override; - - bool TryParseLink(const QString &link); - - QString ToShareLink() override; - }; -} // namespace NekoGui_fmt diff --git a/fmt/TrojanVLESSBean.hpp b/fmt/TrojanVLESSBean.hpp deleted file mode 100644 index 77070a6..0000000 --- a/fmt/TrojanVLESSBean.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include "fmt/AbstractBean.hpp" -#include "fmt/V2RayStreamSettings.hpp" - -namespace NekoGui_fmt { - class TrojanVLESSBean : public AbstractBean { - public: - static constexpr int proxy_Trojan = 0; - static constexpr int proxy_VLESS = 1; - int proxy_type = proxy_Trojan; - - QString password = ""; - QString flow = ""; - - std::shared_ptr stream = std::make_shared(); - - explicit TrojanVLESSBean(int _proxy_type) : AbstractBean(0) { - proxy_type = _proxy_type; - _add(new configItem("pass", &password, itemType::string)); - _add(new configItem("flow", &flow, itemType::string)); - _add(new configItem("stream", dynamic_cast(stream.get()), itemType::jsonStore)); - }; - - QString DisplayType() override { return proxy_type == proxy_VLESS ? "VLESS" : "Trojan"; }; - - CoreObjOutboundBuildResult BuildCoreObjSingBox() override; - - bool TryParseLink(const QString &link); - - QString ToShareLink() override; - }; -} // namespace NekoGui_fmt \ No newline at end of file diff --git a/fmt/V2RayStreamSettings.hpp b/fmt/V2RayStreamSettings.hpp deleted file mode 100644 index 9a6de9f..0000000 --- a/fmt/V2RayStreamSettings.hpp +++ /dev/null @@ -1,65 +0,0 @@ -#pragma once - -#include "AbstractBean.hpp" - -namespace NekoGui_fmt { - class V2rayStreamSettings : public JsonStore { - public: - QString network = "tcp"; - QString security = ""; - QString packet_encoding = ""; - // ws/http/grpc/tcp-http/httpupgrade - QString path = ""; - QString host = ""; - // kcp/quic/tcp-http - QString header_type = ""; - // tls - QString sni = ""; - QString alpn = ""; - QString certificate = ""; - QString utlsFingerprint = ""; - bool allow_insecure = false; - // ws early data - QString ws_early_data_name = ""; - int ws_early_data_length = 0; - // reality - QString reality_pbk = ""; - QString reality_sid = ""; - QString reality_spx = ""; - // multiplex - int multiplex_status = 0; - - V2rayStreamSettings() : JsonStore() { - _add(new configItem("net", &network, itemType::string)); - _add(new configItem("sec", &security, itemType::string)); - _add(new configItem("pac_enc", &packet_encoding, itemType::string)); - _add(new configItem("path", &path, itemType::string)); - _add(new configItem("host", &host, itemType::string)); - _add(new configItem("sni", &sni, itemType::string)); - _add(new configItem("alpn", &alpn, itemType::string)); - _add(new configItem("cert", &certificate, itemType::string)); - _add(new configItem("insecure", &allow_insecure, itemType::boolean)); - _add(new configItem("h_type", &header_type, itemType::string)); - _add(new configItem("ed_name", &ws_early_data_name, itemType::string)); - _add(new configItem("ed_len", &ws_early_data_length, itemType::integer)); - _add(new configItem("utls", &utlsFingerprint, itemType::string)); - _add(new configItem("pbk", &reality_pbk, itemType::string)); - _add(new configItem("sid", &reality_sid, itemType::string)); - _add(new configItem("spx", &reality_spx, itemType::string)); - _add(new configItem("mux_s", &multiplex_status, itemType::integer)); - } - - void BuildStreamSettingsSingBox(QJsonObject *outbound); - }; - - inline V2rayStreamSettings *GetStreamSettings(AbstractBean *bean) { - if (bean == nullptr) return nullptr; - auto stream_item = bean->_get("stream"); - if (stream_item != nullptr) { - auto stream_store = (JsonStore *) stream_item->ptr; - auto stream = (NekoGui_fmt::V2rayStreamSettings *) stream_store; - return stream; - } - return nullptr; - } -} // namespace NekoGui_fmt diff --git a/fmt/VMessBean.hpp b/fmt/VMessBean.hpp deleted file mode 100644 index 2bd81a4..0000000 --- a/fmt/VMessBean.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include "fmt/AbstractBean.hpp" -#include "fmt/V2RayStreamSettings.hpp" - -namespace NekoGui_fmt { - class VMessBean : public AbstractBean { - public: - QString uuid = ""; - int aid = 0; - QString security = "auto"; - - std::shared_ptr stream = std::make_shared(); - - VMessBean() : AbstractBean(0) { - _add(new configItem("id", &uuid, itemType::string)); - _add(new configItem("aid", &aid, itemType::integer)); - _add(new configItem("sec", &security, itemType::string)); - _add(new configItem("stream", dynamic_cast(stream.get()), itemType::jsonStore)); - }; - - QString DisplayType() override { return "VMess"; }; - - CoreObjOutboundBuildResult BuildCoreObjSingBox() override; - - bool TryParseLink(const QString &link); - - QString ToShareLink() override; - }; -} // namespace NekoGui_fmt diff --git a/fmt/includes.h b/fmt/includes.h deleted file mode 100644 index cd3fe3d..0000000 --- a/fmt/includes.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include "SocksHttpBean.hpp" -#include "ShadowSocksBean.hpp" -#include "ChainBean.hpp" -#include "VMessBean.hpp" -#include "TrojanVLESSBean.hpp" -#include "NaiveBean.hpp" -#include "QUICBean.hpp" -#include "CustomBean.hpp" diff --git a/go/.gitignore b/go/.gitignore deleted file mode 100644 index 96af7a5..0000000 --- a/go/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -*.log -*.pem -*.json -*.exe -*.dat -/cmd/nekoray_core/nekoray_core -/cmd/nekobox_core/nekobox_core -*.db diff --git a/go/cmd/nekobox_core/core_box.go b/go/cmd/nekobox_core/core_box.go deleted file mode 100644 index 4e5d253..0000000 --- a/go/cmd/nekobox_core/core_box.go +++ /dev/null @@ -1,50 +0,0 @@ -package main - -import ( - "context" - "net" - "net/http" - - "github.com/matsuridayo/libneko/neko_common" - "github.com/matsuridayo/libneko/neko_log" - box "github.com/sagernet/sing-box" - "github.com/sagernet/sing-box/boxapi" - boxmain "github.com/sagernet/sing-box/cmd/sing-box" -) - -var instance *box.Box -var instance_cancel context.CancelFunc - -func setupCore() { - boxmain.SetDisableColor(true) - // - neko_log.SetupLog(50*1024, "./neko.log") - // - neko_common.GetCurrentInstance = func() interface{} { - return instance - } - neko_common.DialContext = func(ctx context.Context, specifiedInstance interface{}, network, addr string) (net.Conn, error) { - if i, ok := specifiedInstance.(*box.Box); ok { - return boxapi.DialContext(ctx, i, network, addr) - } - if instance != nil { - return boxapi.DialContext(ctx, instance, network, addr) - } - return neko_common.DialContextSystem(ctx, network, addr) - } - neko_common.DialUDP = func(ctx context.Context, specifiedInstance interface{}) (net.PacketConn, error) { - if i, ok := specifiedInstance.(*box.Box); ok { - return boxapi.DialUDP(ctx, i) - } - if instance != nil { - return boxapi.DialUDP(ctx, instance) - } - return neko_common.DialUDPSystem(ctx) - } - neko_common.CreateProxyHttpClient = func(specifiedInstance interface{}) *http.Client { - if i, ok := specifiedInstance.(*box.Box); ok { - return boxapi.CreateProxyHttpClient(i) - } - return boxapi.CreateProxyHttpClient(instance) - } -} diff --git a/go/cmd/nekobox_core/go.mod b/go/cmd/nekobox_core/go.mod deleted file mode 100644 index 6af5b62..0000000 --- a/go/cmd/nekobox_core/go.mod +++ /dev/null @@ -1,105 +0,0 @@ -module nekobox_core - -go 1.19 - -require ( - github.com/matsuridayo/libneko v1.0.0 // replaced - github.com/sagernet/sing-box v1.0.0 // replaced - // github.com/sagernet/sing-dns v1.0.0 // indirect; replaced - grpc_server v1.0.0 -) - -require ( - berty.tech/go-libtor v1.0.385 // indirect - cloud.google.com/go/compute/metadata v0.2.3 // indirect - github.com/ajg/form v1.5.1 // indirect - github.com/andybalholm/brotli v1.0.6 // indirect - github.com/caddyserver/certmagic v0.20.0 // indirect - github.com/cloudflare/circl v1.3.7 // indirect - github.com/cretz/bine v0.2.0 // indirect - github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/gaukas/godicttls v0.0.4 // indirect - github.com/go-chi/chi/v5 v5.0.12 // indirect - github.com/go-chi/cors v1.2.1 // indirect - github.com/go-chi/render v1.0.3 // indirect - github.com/go-ole/go-ole v1.3.0 // indirect - github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect - github.com/gobwas/httphead v0.1.0 // indirect - github.com/gobwas/pool v0.2.1 // indirect - github.com/gofrs/uuid/v5 v5.2.0 // indirect - github.com/google/btree v1.1.2 // indirect - github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a // indirect - github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect - github.com/hashicorp/yamux v0.1.1 // indirect - github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2 // indirect - github.com/josharian/native v1.1.0 // indirect - github.com/klauspost/compress v1.17.4 // indirect - github.com/klauspost/cpuid/v2 v2.2.5 // indirect - github.com/libdns/alidns v1.0.3 // indirect - github.com/libdns/cloudflare v0.1.1 // indirect - github.com/libdns/libdns v0.2.2 // indirect - github.com/logrusorgru/aurora v2.0.3+incompatible // indirect - github.com/metacubex/tfo-go v0.0.0-20240821025650-e9be0afd5e7d // indirect - github.com/mholt/acmez v1.2.0 // indirect - github.com/miekg/dns v1.1.59 // indirect - github.com/onsi/ginkgo/v2 v2.9.7 // indirect - github.com/ooni/go-libtor v1.1.8 // indirect - github.com/oschwald/maxminddb-golang v1.12.0 // indirect - github.com/pierrec/lz4/v4 v4.1.14 // indirect - github.com/quic-go/qpack v0.4.0 // indirect - github.com/quic-go/qtls-go1-20 v0.4.1 // indirect - github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a // indirect - github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1 // indirect - github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f // indirect - github.com/sagernet/netlink v0.0.0-20240523065131-45e60152f9ba // indirect - github.com/sagernet/quic-go v0.47.0-beta.2 // indirect - github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 // indirect - github.com/sagernet/sing v0.4.3 // indirect - github.com/sagernet/sing-dns v0.2.3 // indirect - github.com/sagernet/sing-mux v0.2.0 // indirect - github.com/sagernet/sing-quic v0.2.2 // indirect - github.com/sagernet/sing-shadowsocks v0.2.7 // indirect - github.com/sagernet/sing-shadowsocks2 v0.2.0 // indirect - github.com/sagernet/sing-shadowtls v0.1.4 // indirect - github.com/sagernet/sing-tun v0.3.3 // indirect - github.com/sagernet/sing-vmess v0.1.12 // indirect - github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 // indirect - github.com/sagernet/utls v1.5.4 // indirect - github.com/sagernet/wireguard-go v0.0.0-20231215174105-89dec3b2f3e8 // indirect - github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854 // indirect - github.com/spf13/cobra v1.8.0 // indirect - github.com/spf13/pflag v1.0.5 // indirect - github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 // indirect - github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect - github.com/zeebo/blake3 v0.2.3 // indirect - go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.27.0 // indirect - go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect - golang.org/x/crypto v0.23.0 // indirect - golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f // indirect - golang.org/x/mod v0.18.0 // indirect - golang.org/x/net v0.25.0 // indirect - golang.org/x/sync v0.8.0 // indirect - golang.org/x/sys v0.25.0 // indirect - golang.org/x/text v0.18.0 // indirect - golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect - golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/grpc v1.63.2 // indirect - google.golang.org/protobuf v1.33.0 // indirect - lukechampine.com/blake3 v1.3.0 // indirect -) - -replace grpc_server => ../../grpc_server - -replace github.com/matsuridayo/libneko => ../../../../libneko - -replace github.com/sagernet/sing-box => ../../../../sing-box - -replace github.com/sagernet/sing-quic => ../../../../sing-quic - -// replace github.com/sagernet/sing => ../../../../sing - -// replace github.com/sagernet/sing-dns => ../../../../sing-dns diff --git a/go/cmd/nekobox_core/go.sum b/go/cmd/nekobox_core/go.sum deleted file mode 100644 index 4f99f25..0000000 --- a/go/cmd/nekobox_core/go.sum +++ /dev/null @@ -1,298 +0,0 @@ -berty.tech/go-libtor v1.0.385 h1:RWK94C3hZj6Z2GdvePpHJLnWYobFr3bY/OdUJ5aoEXw= -berty.tech/go-libtor v1.0.385/go.mod h1:9swOOQVb+kmvuAlsgWUK/4c52pm69AdbJsxLzk+fJEw= -cloud.google.com/go v0.26.0 h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ= -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go/compute v1.24.0 h1:phWcR2eWzRJaL/kOiJwfFsPs4BaKq1j6vnpZrc1YlVg= -cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= -cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= -github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= -github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI= -github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= -github.com/caddyserver/certmagic v0.20.0 h1:bTw7LcEZAh9ucYCRXyCpIrSAGplplI0vGYJ4BpCQ/Fc= -github.com/caddyserver/certmagic v0.20.0/go.mod h1:N4sXgpICQUskEWpj7zVzvWD41p3NYacrNoZYiRM2jTg= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= -github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/cretz/bine v0.1.0/go.mod h1:6PF6fWAvYtwjRGkAuDEJeWNOv3a2hUouSP/yRYXmvHw= -github.com/cretz/bine v0.2.0 h1:8GiDRGlTgz+o8H9DSnsl+5MeBK4HsExxgl6WgzOCuZo= -github.com/cretz/bine v0.2.0/go.mod h1:WU4o9QR9wWp8AVKtTM1XD5vUHkEqnf2vVSo6dBqbetI= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= -github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/gaukas/godicttls v0.0.4 h1:NlRaXb3J6hAnTmWdsEKb9bcSBD6BvcIjdGdeb0zfXbk= -github.com/gaukas/godicttls v0.0.4/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI= -github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s= -github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= -github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4= -github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58= -github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4= -github.com/go-chi/render v1.0.3/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= -github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= -github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= -github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= -github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= -github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gofrs/uuid/v5 v5.2.0 h1:qw1GMx6/y8vhVsx626ImfKMuS5CvJmhIKKtuyvfajMM= -github.com/gofrs/uuid/v5 v5.2.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= -github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a h1:fEBsGL/sjAuJrgah5XqmmYsTLzJp/TO9Lhy39gkverk= -github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= -github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= -github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= -github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= -github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2 h1:9K06NfxkBh25x56yVhWWlKFE8YpicaSfHwoV8SFbueA= -github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2/go.mod h1:3A9PQ1cunSDF/1rbTq99Ts4pVnycWg+vlPkfeD2NLFI= -github.com/josharian/native v1.0.1-0.20221213033349-c1e37c09b531/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= -github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA= -github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= -github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= -github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= -github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= -github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/libdns/alidns v1.0.3 h1:LFHuGnbseq5+HCeGa1aW8awyX/4M2psB9962fdD2+yQ= -github.com/libdns/alidns v1.0.3/go.mod h1:e18uAG6GanfRhcJj6/tps2rCMzQJaYVcGKT+ELjdjGE= -github.com/libdns/cloudflare v0.1.1 h1:FVPfWwP8zZCqj268LZjmkDleXlHPlFU9KC4OJ3yn054= -github.com/libdns/cloudflare v0.1.1/go.mod h1:9VK91idpOjg6v7/WbjkEW49bSCxj00ALesIFDhJ8PBU= -github.com/libdns/libdns v0.2.0/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40= -github.com/libdns/libdns v0.2.2 h1:O6ws7bAfRPaBsgAYt8MDe2HcNBGC29hkZ9MX2eUSX3s= -github.com/libdns/libdns v0.2.2/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ= -github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8= -github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= -github.com/metacubex/tfo-go v0.0.0-20240821025650-e9be0afd5e7d h1:j9LtzkYstLFoNvXW824QQeN7Y26uPL5249kzWKbzO9U= -github.com/metacubex/tfo-go v0.0.0-20240821025650-e9be0afd5e7d/go.mod h1:c7bVFM9f5+VzeZ/6Kg77T/jrg1Xp8QpqlSHvG/aXVts= -github.com/mholt/acmez v1.2.0 h1:1hhLxSgY5FvH5HCnGUuwbKY2VQVo8IU7rxXKSnZ7F30= -github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE= -github.com/miekg/dns v1.1.59 h1:C9EXc/UToRwKLhK5wKU/I4QVsBUc8kE6MkHBkeypWZs= -github.com/miekg/dns v1.1.59/go.mod h1:nZpewl5p6IvctfgrckopVx2OlSEHPRO/U4SYkRklrEk= -github.com/onsi/ginkgo/v2 v2.9.7 h1:06xGQy5www2oN160RtEZoTvnP2sPhEfePYmCDc2szss= -github.com/onsi/ginkgo/v2 v2.9.7/go.mod h1:cxrmXWykAwTwhQsJOPfdIDiJ+l2RYq7U8hFU+M/1uw0= -github.com/onsi/gomega v1.27.7 h1:fVih9JD6ogIiHUN6ePK7HJidyEDpWGVB5mzM7cWNXoU= -github.com/ooni/go-libtor v1.1.8 h1:Wo3V3DVTxl5vZdxtQakqYP+DAHx7pPtAFSl1bnAa08w= -github.com/ooni/go-libtor v1.1.8/go.mod h1:q1YyLwRD9GeMyeerVvwc0vJ2YgwDLTp2bdVcrh/JXyI= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/oschwald/maxminddb-golang v1.12.0 h1:9FnTOD0YOhP7DGxGsq4glzpGy5+w7pq50AS6wALUMYs= -github.com/oschwald/maxminddb-golang v1.12.0/go.mod h1:q0Nob5lTCqyQ8WT6FYgS1L7PXKVVbgiymefNwIjPzgY= -github.com/pierrec/lz4/v4 v4.1.14 h1:+fL8AQEZtz/ijeNnpduH0bROTu0O3NZAlPjQxGn8LwE= -github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= -github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= -github.com/quic-go/qtls-go1-20 v0.4.1 h1:D33340mCNDAIKBqXuAvexTNMUByrYmFYVfKfDN5nfFs= -github.com/quic-go/qtls-go1-20 v0.4.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a h1:+NkI2670SQpQWvkkD2QgdTuzQG263YZ+2emfpeyGqW0= -github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a/go.mod h1:63s7jpZqcDAIpj8oI/1v4Izok+npJOHACFCU6+huCkM= -github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1 h1:YbmpqPQEMdlk9oFSKYWRqVuu9qzNiOayIonKmv1gCXY= -github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1/go.mod h1:J2yAxTFPDjrDPhuAi9aWFz2L3ox9it4qAluBBbN0H5k= -github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f h1:NkhuupzH5ch7b/Y/6ZHJWrnNLoiNnSJaow6DPb8VW2I= -github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f/go.mod h1:KXmw+ouSJNOsuRpg4wgwwCQuunrGz4yoAqQjsLjc6N0= -github.com/sagernet/netlink v0.0.0-20240523065131-45e60152f9ba h1:EY5AS7CCtfmARNv2zXUOrsEMPFDGYxaw65JzA2p51Vk= -github.com/sagernet/netlink v0.0.0-20240523065131-45e60152f9ba/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM= -github.com/sagernet/quic-go v0.47.0-beta.2 h1:1tCGWFOSaXIeuQaHrwOMJIYvlupjTcaVInGQw5ArULU= -github.com/sagernet/quic-go v0.47.0-beta.2/go.mod h1:bLVKvElSEMNv7pu7SZHscW02TYigzQ5lQu3Nh4wNh8Q= -github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc= -github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU= -github.com/sagernet/sing v0.2.18/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo= -github.com/sagernet/sing v0.4.3 h1:Ty/NAiNnVd6844k7ujlL5lkzydhcTH5Psc432jXA4Y8= -github.com/sagernet/sing v0.4.3/go.mod h1:ieZHA/+Y9YZfXs2I3WtuwgyCZ6GPsIR7HdKb1SdEnls= -github.com/sagernet/sing-dns v0.2.3 h1:YzeBUn2tR38F7HtvGEQ0kLRLmZWMEgi/+7wqa4Twb1k= -github.com/sagernet/sing-dns v0.2.3/go.mod h1:BJpJv6XLnrUbSyIntOT6DG9FW0f4fETmPAHvNjOprLg= -github.com/sagernet/sing-mux v0.2.0 h1:4C+vd8HztJCWNYfufvgL49xaOoOHXty2+EAjnzN3IYo= -github.com/sagernet/sing-mux v0.2.0/go.mod h1:khzr9AOPocLa+g53dBplwNDz4gdsyx/YM3swtAhlkHQ= -github.com/sagernet/sing-shadowsocks v0.2.7 h1:zaopR1tbHEw5Nk6FAkM05wCslV6ahVegEZaKMv9ipx8= -github.com/sagernet/sing-shadowsocks v0.2.7/go.mod h1:0rIKJZBR65Qi0zwdKezt4s57y/Tl1ofkaq6NlkzVuyE= -github.com/sagernet/sing-shadowsocks2 v0.2.0 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wKFHi+8XwgADg= -github.com/sagernet/sing-shadowsocks2 v0.2.0/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ= -github.com/sagernet/sing-shadowtls v0.1.4 h1:aTgBSJEgnumzFenPvc+kbD9/W0PywzWevnVpEx6Tw3k= -github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4= -github.com/sagernet/sing-tun v0.3.3 h1:LZnQNmfGcNG2KPTPkLgc+Lo7k606QJVkPp2DnjriwUk= -github.com/sagernet/sing-tun v0.3.3/go.mod h1:DxLIyhjWU/HwGYoX0vNGg2c5QgTQIakphU1MuERR5tQ= -github.com/sagernet/sing-vmess v0.1.12 h1:2gFD8JJb+eTFMoa8FIVMnknEi+vCSfaiTXTfEYAYAPg= -github.com/sagernet/sing-vmess v0.1.12/go.mod h1:luTSsfyBGAc9VhtCqwjR+dt1QgqBhuYBCONB/POhF8I= -github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ= -github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7/go.mod h1:FP9X2xjT/Az1EsG/orYYoC+5MojWnuI7hrffz8fGwwo= -github.com/sagernet/utls v1.5.4 h1:KmsEGbB2dKUtCNC+44NwAdNAqnqQ6GA4pTO0Yik56co= -github.com/sagernet/utls v1.5.4/go.mod h1:CTGxPWExIloRipK3XFpYv0OVyhO8kk3XCGW/ieyTh1s= -github.com/sagernet/wireguard-go v0.0.0-20231215174105-89dec3b2f3e8 h1:R0OMYAScomNAVpTfbHFpxqJpvwuhxSRi+g6z7gZhABs= -github.com/sagernet/wireguard-go v0.0.0-20231215174105-89dec3b2f3e8/go.mod h1:K4J7/npM+VAMUeUmTa2JaA02JmyheP0GpRBOUvn3ecc= -github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854 h1:6uUiZcDRnZSAegryaUGwPC/Fj13JSHwiTftrXhMmYOc= -github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854/go.mod h1:LtfoSK3+NG57tvnVEHgcuBW9ujgE8enPSgzgwStwCAA= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= -github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 h1:tHNk7XK9GkmKUR6Gh8gVBKXc2MVSZ4G/NnWLtzw4gNA= -github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264= -github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg= -github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY= -github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= -github.com/zeebo/blake3 v0.2.3 h1:TFoLXsjeXqRNFxSbk35Dk4YtszE/MQQGK10BH4ptoTg= -github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvvKCaQ= -github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo= -github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= -go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= -go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= -go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M= -go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= -golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f h1:99ci1mjWVBWwJiEKYY6jWa4d2nTQVIEhZIptnrVb1XY= -golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= -golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= -golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 h1:CawjfCvYQH2OU3/TnxLx97WDSUDRABfT18pCOYwc2GE= -golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6/go.mod h1:3rxYc4HtVcSG9gVaTs2GEBdehh+sYPOwKtyUWEOTb80= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= -google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE= -lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= diff --git a/go/cmd/nekobox_core/grpc_box.go b/go/cmd/nekobox_core/grpc_box.go deleted file mode 100644 index aabc0f5..0000000 --- a/go/cmd/nekobox_core/grpc_box.go +++ /dev/null @@ -1,152 +0,0 @@ -package main - -import ( - "context" - "errors" - "fmt" - - "grpc_server" - "grpc_server/gen" - - "github.com/matsuridayo/libneko/neko_common" - "github.com/matsuridayo/libneko/neko_log" - "github.com/matsuridayo/libneko/speedtest" - box "github.com/sagernet/sing-box" - "github.com/sagernet/sing-box/boxapi" - boxmain "github.com/sagernet/sing-box/cmd/sing-box" - - "log" - - "github.com/sagernet/sing-box/option" -) - -type server struct { - grpc_server.BaseServer -} - -func (s *server) Start(ctx context.Context, in *gen.LoadConfigReq) (out *gen.ErrorResp, _ error) { - var err error - - defer func() { - out = &gen.ErrorResp{} - if err != nil { - out.Error = err.Error() - instance = nil - } - }() - - if neko_common.Debug { - log.Println("Start:", in.CoreConfig) - } - - if instance != nil { - err = errors.New("instance already started") - return - } - - instance, instance_cancel, err = boxmain.Create([]byte(in.CoreConfig)) - - if instance != nil { - // Logger - instance.SetLogWritter(neko_log.LogWriter) - // V2ray Service - if in.StatsOutbounds != nil { - instance.Router().SetV2RayServer(boxapi.NewSbV2rayServer(option.V2RayStatsServiceOptions{ - Enabled: true, - Outbounds: in.StatsOutbounds, - })) - } - } - - return -} - -func (s *server) Stop(ctx context.Context, in *gen.EmptyReq) (out *gen.ErrorResp, _ error) { - var err error - - defer func() { - out = &gen.ErrorResp{} - if err != nil { - out.Error = err.Error() - } - }() - - if instance == nil { - return - } - - instance_cancel() - instance.Close() - - instance = nil - - return -} - -func (s *server) Test(ctx context.Context, in *gen.TestReq) (out *gen.TestResp, _ error) { - var err error - out = &gen.TestResp{Ms: 0} - - defer func() { - if err != nil { - out.Error = err.Error() - } - }() - - if in.Mode == gen.TestMode_UrlTest { - var i *box.Box - var cancel context.CancelFunc - if in.Config != nil { - // Test instance - i, cancel, err = boxmain.Create([]byte(in.Config.CoreConfig)) - if i != nil { - defer i.Close() - defer cancel() - } - if err != nil { - return - } - } else { - // Test running instance - i = instance - if i == nil { - return - } - } - // Latency - out.Ms, err = speedtest.UrlTest(boxapi.CreateProxyHttpClient(i), in.Url, in.Timeout, speedtest.UrlTestStandard_RTT) - } else if in.Mode == gen.TestMode_TcpPing { - out.Ms, err = speedtest.TcpPing(in.Address, in.Timeout) - } else if in.Mode == gen.TestMode_FullTest { - i, cancel, err := boxmain.Create([]byte(in.Config.CoreConfig)) - if i != nil { - defer i.Close() - defer cancel() - } - if err != nil { - return - } - return grpc_server.DoFullTest(ctx, in, i) - } - - return -} - -func (s *server) QueryStats(ctx context.Context, in *gen.QueryStatsReq) (out *gen.QueryStatsResp, _ error) { - out = &gen.QueryStatsResp{} - - if instance != nil { - if ss, ok := instance.Router().V2RayServer().(*boxapi.SbV2rayServer); ok { - out.Traffic = ss.QueryStats(fmt.Sprintf("outbound>>>%s>>>traffic>>>%s", in.Tag, in.Direct)) - } - } - - return -} - -func (s *server) ListConnections(ctx context.Context, in *gen.EmptyReq) (*gen.ListConnectionsResp, error) { - out := &gen.ListConnectionsResp{ - // TODO upstream api - } - return out, nil -} diff --git a/go/cmd/nekobox_core/main.go b/go/cmd/nekobox_core/main.go deleted file mode 100644 index d234952..0000000 --- a/go/cmd/nekobox_core/main.go +++ /dev/null @@ -1,28 +0,0 @@ -package main - -import ( - "fmt" - "os" - _ "unsafe" - - "grpc_server" - - "github.com/matsuridayo/libneko/neko_common" - boxmain "github.com/sagernet/sing-box/cmd/sing-box" - "github.com/sagernet/sing-box/constant" -) - -func main() { - fmt.Println("sing-box:", constant.Version, "NekoBox:", neko_common.Version_neko) - fmt.Println() - - // nekobox_core - if len(os.Args) > 1 && os.Args[1] == "nekobox" { - neko_common.RunMode = neko_common.RunMode_NekoBox_Core - grpc_server.RunCore(setupCore, &server{}) - return - } - - // sing-box - boxmain.Main() -} diff --git a/go/cmd/updater/.gitignore b/go/cmd/updater/.gitignore deleted file mode 100644 index 7b3c510..0000000 --- a/go/cmd/updater/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/updater -/launcher diff --git a/go/cmd/updater/go.mod b/go/cmd/updater/go.mod deleted file mode 100644 index 8a8b280..0000000 --- a/go/cmd/updater/go.mod +++ /dev/null @@ -1,11 +0,0 @@ -module updater - -go 1.18 - -require github.com/codeclysm/extract v2.2.0+incompatible - -require ( - github.com/h2non/filetype v1.1.3 // indirect - github.com/juju/errors v0.0.0-20220331221717-b38fca44723b // indirect - github.com/stretchr/testify v1.7.1 // indirect -) diff --git a/go/cmd/updater/go.sum b/go/cmd/updater/go.sum deleted file mode 100644 index 4949ed5..0000000 --- a/go/cmd/updater/go.sum +++ /dev/null @@ -1,19 +0,0 @@ -github.com/codeclysm/extract v2.2.0+incompatible h1:q3wyckoA30bhUSiwdQezMqVhwd8+WGE64/GL//LtUhI= -github.com/codeclysm/extract v2.2.0+incompatible/go.mod h1:2nhFMPHiU9At61hz+12bfrlpXSUrOnK+wR+KlGO4Uks= -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/h2non/filetype v1.1.3 h1:FKkx9QbD7HR/zjK1Ia5XiBsq9zdLi5Kf3zGyFTAFkGg= -github.com/h2non/filetype v1.1.3/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY= -github.com/juju/errors v0.0.0-20220331221717-b38fca44723b h1:AxFeSQJfcm2O3ov1wqAkTKYFsnMw2g1B4PkYujfAdkY= -github.com/juju/errors v0.0.0-20220331221717-b38fca44723b/go.mod h1:jMGj9DWF/qbo91ODcfJq6z/RYc3FX3taCBZMCcpI4Ls= -github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/go/cmd/updater/launcher.go b/go/cmd/updater/launcher.go deleted file mode 100644 index ed9b0e0..0000000 --- a/go/cmd/updater/launcher.go +++ /dev/null @@ -1,12 +0,0 @@ -//go:build !linux - -package main - -import ( - "log" - "runtime" -) - -func Launcher() { - log.Fatalln("launcher is not for your platform", runtime.GOOS) -} diff --git a/go/cmd/updater/launcher_linux.go b/go/cmd/updater/launcher_linux.go deleted file mode 100644 index 334708e..0000000 --- a/go/cmd/updater/launcher_linux.go +++ /dev/null @@ -1,41 +0,0 @@ -package main - -import ( - "flag" - "log" - "os" - "os/exec" - "path/filepath" -) - -var local_qt_theme bool - -func Launcher() { - log.Println("Running as launcher") - wd, _ := filepath.Abs(".") - - _debug := flag.Bool("debug", false, "Debug mode") - flag.Parse() - - cmd := exec.Command("./nekobox", flag.Args()...) - - ld_env := "LD_LIBRARY_PATH=" + filepath.Join(wd, "./usr/lib") - qt_plugin_env := "QT_PLUGIN_PATH=" + filepath.Join(wd, "./usr/plugins") - - // Qt 5.12 abi is usually compatible with system Qt 5.15 - // But use package Qt 5.12 by default. - cmd.Env = os.Environ() - cmd.Env = append(cmd.Env, "NKR_FROM_LAUNCHER=1") - cmd.Env = append(cmd.Env, ld_env, qt_plugin_env) - log.Println(ld_env, qt_plugin_env, cmd) - - if *_debug { - cmd.Env = append(cmd.Env, "QT_DEBUG_PLUGINS=1") - cmd.Stdin = os.Stdin - cmd.Stderr = os.Stderr - cmd.Stdout = os.Stdout - cmd.Run() - } else { - cmd.Start() - } -} diff --git a/go/cmd/updater/main.go b/go/cmd/updater/main.go deleted file mode 100644 index 1e6ca63..0000000 --- a/go/cmd/updater/main.go +++ /dev/null @@ -1,62 +0,0 @@ -package main - -import ( - "io/ioutil" - "log" - "os" - "os/exec" - "path/filepath" - "runtime" - "strings" - "time" -) - -func main() { - // update & launcher - exe, err := os.Executable() - if err != nil { - panic(err.Error()) - } - - wd := filepath.Dir(exe) - os.Chdir(wd) - exe = filepath.Base(os.Args[0]) - log.Println("exe:", exe, "exe dir:", wd) - - if strings.HasPrefix(strings.ToLower(exe), "updater") { - if runtime.GOOS == "windows" { - if strings.HasPrefix(strings.ToLower(exe), "updater.old") { - // 2. "updater.old" update files - time.Sleep(time.Second) - Updater() - // 3. start - exec.Command("./nekobox.exe").Start() - } else { - // 1. main prog quit and run "updater.exe" - Copy("./updater.exe", "./updater.old") - exec.Command("./updater.old", os.Args[1:]...).Start() - } - } else { - // 1. update files - Updater() - // 2. start - if os.Getenv("NKR_FROM_LAUNCHER") == "1" { - Launcher() - } else { - exec.Command("./nekobox").Start() - } - } - return - } else if strings.HasPrefix(strings.ToLower(exe), "launcher") { - Launcher() - return - } - log.Fatalf("wrong name") -} - -func Copy(src string, dst string) { - // Read all content of src to data - data, _ := ioutil.ReadFile(src) - // Write data to dst - ioutil.WriteFile(dst, data, 0644) -} diff --git a/go/cmd/updater/msgbox.go b/go/cmd/updater/msgbox.go deleted file mode 100644 index f94ba8f..0000000 --- a/go/cmd/updater/msgbox.go +++ /dev/null @@ -1,7 +0,0 @@ -//go:build !windows - -package main - -func MessageBoxPlain(title, caption string) int { - return 0 -} diff --git a/go/cmd/updater/msgbox_windows.go b/go/cmd/updater/msgbox_windows.go deleted file mode 100644 index 216f489..0000000 --- a/go/cmd/updater/msgbox_windows.go +++ /dev/null @@ -1,26 +0,0 @@ -package main - -import ( - "syscall" - "unsafe" -) - -// MessageBoxPlain of Win32 API. -func MessageBoxPlain(title, caption string) int { - const ( - NULL = 0 - MB_OK = 0 - ) - return MessageBox(NULL, caption, title, MB_OK) -} - -// MessageBox of Win32 API. -func MessageBox(hwnd uintptr, caption, title string, flags uint) int { - ret, _, _ := syscall.NewLazyDLL("user32.dll").NewProc("MessageBoxW").Call( - uintptr(hwnd), - uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(caption))), - uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(title))), - uintptr(flags)) - - return int(ret) -} diff --git a/go/cmd/updater/updater.go b/go/cmd/updater/updater.go deleted file mode 100644 index c71c775..0000000 --- a/go/cmd/updater/updater.go +++ /dev/null @@ -1,129 +0,0 @@ -package main - -import ( - "context" - "log" - "os" - "path/filepath" - "runtime" - "strings" - - "github.com/codeclysm/extract" -) - -func Updater() { - pre_cleanup := func() { - if runtime.GOOS == "linux" { - os.RemoveAll("./usr") - } - os.RemoveAll("./nekoray_update") - } - - // find update package - var updatePackagePath string - if len(os.Args) == 2 && Exist(os.Args[1]) { - updatePackagePath = os.Args[1] - } else if Exist("./nekoray.zip") { - updatePackagePath = "./nekoray.zip" - } else if Exist("./nekoray.tar.gz") { - updatePackagePath = "./nekoray.tar.gz" - } else { - log.Fatalln("no update") - } - log.Println("updating from", updatePackagePath) - - // extract update package - if strings.HasSuffix(updatePackagePath, ".zip") { - pre_cleanup() - f, err := os.Open(updatePackagePath) - if err != nil { - log.Fatalln(err.Error()) - } - err = extract.Zip(context.Background(), f, "./nekoray_update", nil) - if err != nil { - log.Fatalln(err.Error()) - } - f.Close() - } else if strings.HasSuffix(updatePackagePath, ".tar.gz") { - pre_cleanup() - f, err := os.Open(updatePackagePath) - if err != nil { - log.Fatalln(err.Error()) - } - err = extract.Gz(context.Background(), f, "./nekoray_update", nil) - if err != nil { - log.Fatalln(err.Error()) - } - f.Close() - } - - // remove old file - removeAll("./*.dll") - removeAll("./*.dmp") - - // update move - err := Mv("./nekoray_update/nekoray", "./") - if err != nil { - MessageBoxPlain("NekoGui Updater", "Update failed. Please close the running instance and run the updater again.\n\n"+err.Error()) - log.Fatalln(err.Error()) - } - - os.RemoveAll("./nekoray_update") - os.RemoveAll("./nekoray.zip") - os.RemoveAll("./nekoray.tar.gz") - - // nekoray -> nekobox - os.Remove("./nekoray.exe") - os.Remove("./nekoray.png") - os.Remove("./nekoray_core.exe") -} - -func Exist(path string) bool { - _, err := os.Stat(path) - return err == nil -} - -func FindExist(paths []string) string { - for _, path := range paths { - if Exist(path) { - return path - } - } - return "" -} - -func Mv(src, dst string) error { - s, err := os.Stat(src) - if err != nil { - return err - } - if s.IsDir() { - es, err := os.ReadDir(src) - if err != nil { - return err - } - for _, e := range es { - err = Mv(filepath.Join(src, e.Name()), filepath.Join(dst, e.Name())) - if err != nil { - return err - } - } - } else { - err = os.MkdirAll(filepath.Dir(dst), 0755) - if err != nil { - return err - } - err = os.Rename(src, dst) - if err != nil { - return err - } - } - return nil -} - -func removeAll(glob string) { - files, _ := filepath.Glob(glob) - for _, f := range files { - os.Remove(f) - } -} diff --git a/go/grpc_server/auth/auth.go b/go/grpc_server/auth/auth.go deleted file mode 100644 index 53f65f8..0000000 --- a/go/grpc_server/auth/auth.go +++ /dev/null @@ -1,54 +0,0 @@ -package auth - -import ( - "context" - - "google.golang.org/grpc/codes" - "google.golang.org/grpc/metadata" - "google.golang.org/grpc/status" -) - -// Authenticator exposes a function for authenticating requests. -type Authenticator struct { - Token string -} - -// Authenticate checks that a token exists and is valid. It stores the user -// metadata in the returned context and removes the token from the context. -func (a Authenticator) Authenticate(ctx context.Context) (newCtx context.Context, err error) { - auth, err := extractHeader(ctx, "nekoray_auth") - if err != nil { - return ctx, err - } - - if auth != a.Token { - return ctx, status.Error(codes.Unauthenticated, "invalid token") - } - - return purgeHeader(ctx, "nekoray_auth"), nil -} - -func extractHeader(ctx context.Context, header string) (string, error) { - md, ok := metadata.FromIncomingContext(ctx) - if !ok { - return "", status.Error(codes.Unauthenticated, "no headers in request") - } - - authHeaders, ok := md[header] - if !ok { - return "", status.Error(codes.Unauthenticated, "no header in request") - } - - if len(authHeaders) != 1 { - return "", status.Error(codes.Unauthenticated, "more than 1 header in request") - } - - return authHeaders[0], nil -} - -func purgeHeader(ctx context.Context, header string) context.Context { - md, _ := metadata.FromIncomingContext(ctx) - mdCopy := md.Copy() - mdCopy[header] = nil - return metadata.NewIncomingContext(ctx, mdCopy) -} diff --git a/go/grpc_server/fulltest.go b/go/grpc_server/fulltest.go deleted file mode 100644 index f888ece..0000000 --- a/go/grpc_server/fulltest.go +++ /dev/null @@ -1,180 +0,0 @@ -package grpc_server - -import ( - "context" - "encoding/hex" - "fmt" - "grpc_server/gen" - "io" - "log" - "math" - "net" - "net/http" - "strings" - "time" - - "github.com/matsuridayo/libneko/neko_common" - "github.com/matsuridayo/libneko/speedtest" -) - -const ( - KiB = 1024 - MiB = 1024 * KiB -) - -func getBetweenStr(str, start, end string) string { - n := strings.Index(str, start) - if n == -1 { - n = 0 - } - str = string([]byte(str)[n:]) - m := strings.Index(str, end) - if m == -1 { - m = len(str) - } - str = string([]byte(str)[:m]) - return str[len(start):] -} - -func DoFullTest(ctx context.Context, in *gen.TestReq, instance interface{}) (out *gen.TestResp, _ error) { - out = &gen.TestResp{} - httpClient := neko_common.CreateProxyHttpClient(instance) - - // Latency - var latency string - if in.FullLatency { - t, _ := speedtest.UrlTest(httpClient, in.Url, in.Timeout, speedtest.UrlTestStandard_RTT) - out.Ms = t - if t > 0 { - latency = fmt.Sprint(t, "ms") - } else { - latency = "Error" - } - } - - // UDP Latency - var udpLatency string - if in.FullUdpLatency { - ctx, cancel := context.WithTimeout(context.Background(), time.Second*3) - result := make(chan string) - - go func() { - var startTime = time.Now() - pc, err := neko_common.DialContext(ctx, instance, "udp", "8.8.8.8:53") - if err == nil { - defer pc.Close() - dnsPacket, _ := hex.DecodeString("0000010000010000000000000377777706676f6f676c6503636f6d0000010001") - _, err = pc.Write(dnsPacket) - if err == nil { - var buf [1400]byte - _, err = pc.Read(buf[:]) - } - } - if err == nil { - var endTime = time.Now() - result <- fmt.Sprint(endTime.Sub(startTime).Abs().Milliseconds(), "ms") - } else { - log.Println("UDP Latency test error:", err) - result <- "Error" - } - close(result) - }() - - select { - case <-ctx.Done(): - udpLatency = "Timeout" - case r := <-result: - udpLatency = r - } - cancel() - } - - // 入口 IP - var in_ip string - if in.FullInOut { - _in_ip, err := net.ResolveIPAddr("ip", in.InAddress) - if err == nil { - in_ip = _in_ip.String() - } else { - in_ip = err.Error() - } - } - - // 出口 IP - var out_ip string - if in.FullInOut { - resp, err := httpClient.Get("https://www.cloudflare.com/cdn-cgi/trace") - if err == nil { - b, _ := io.ReadAll(resp.Body) - out_ip = getBetweenStr(string(b), "ip=", "\n") - resp.Body.Close() - } else { - out_ip = "Error" - } - } - - // 下载 - var speed string - if in.FullSpeed { - if in.FullSpeedTimeout <= 0 { - in.FullSpeedTimeout = 30 - } - - ctx, cancel := context.WithTimeout(context.Background(), time.Second*time.Duration(in.FullSpeedTimeout)) - result := make(chan string) - var bodyClose io.Closer - - go func() { - req, _ := http.NewRequestWithContext(ctx, "GET", in.FullSpeedUrl, nil) - resp, err := httpClient.Do(req) - if err == nil && resp != nil && resp.Body != nil { - bodyClose = resp.Body - defer resp.Body.Close() - - timeStart := time.Now() - n, _ := io.Copy(io.Discard, resp.Body) - timeEnd := time.Now() - - duration := math.Max(timeEnd.Sub(timeStart).Seconds(), 0.000001) - resultSpeed := (float64(n) / duration) / MiB - result <- fmt.Sprintf("%.2fMiB/s", resultSpeed) - } else { - result <- "Error" - } - close(result) - }() - - select { - case <-ctx.Done(): - speed = "Timeout" - case s := <-result: - speed = s - } - - cancel() - if bodyClose != nil { - bodyClose.Close() - } - } - - fr := make([]string, 0) - if latency != "" { - fr = append(fr, fmt.Sprintf("Latency: %s", latency)) - } - if udpLatency != "" { - fr = append(fr, fmt.Sprintf("UDPLatency: %s", udpLatency)) - } - if speed != "" { - fr = append(fr, fmt.Sprintf("Speed: %s", speed)) - } - if in_ip != "" { - fr = append(fr, fmt.Sprintf("In: %s", in_ip)) - } - if out_ip != "" { - fr = append(fr, fmt.Sprintf("Out: %s", out_ip)) - } - - out.FullReport = strings.Join(fr, " / ") - - return -} diff --git a/go/grpc_server/gen/libcore.pb.go b/go/grpc_server/gen/libcore.pb.go deleted file mode 100644 index c9b5282..0000000 --- a/go/grpc_server/gen/libcore.pb.go +++ /dev/null @@ -1,1146 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.28.1 -// protoc v4.23.3 -// source: libcore.proto - -package gen - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type TestMode int32 - -const ( - TestMode_TcpPing TestMode = 0 - TestMode_UrlTest TestMode = 1 - TestMode_FullTest TestMode = 2 -) - -// Enum value maps for TestMode. -var ( - TestMode_name = map[int32]string{ - 0: "TcpPing", - 1: "UrlTest", - 2: "FullTest", - } - TestMode_value = map[string]int32{ - "TcpPing": 0, - "UrlTest": 1, - "FullTest": 2, - } -) - -func (x TestMode) Enum() *TestMode { - p := new(TestMode) - *p = x - return p -} - -func (x TestMode) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (TestMode) Descriptor() protoreflect.EnumDescriptor { - return file_libcore_proto_enumTypes[0].Descriptor() -} - -func (TestMode) Type() protoreflect.EnumType { - return &file_libcore_proto_enumTypes[0] -} - -func (x TestMode) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use TestMode.Descriptor instead. -func (TestMode) EnumDescriptor() ([]byte, []int) { - return file_libcore_proto_rawDescGZIP(), []int{0} -} - -type UpdateAction int32 - -const ( - UpdateAction_Check UpdateAction = 0 - UpdateAction_Download UpdateAction = 1 -) - -// Enum value maps for UpdateAction. -var ( - UpdateAction_name = map[int32]string{ - 0: "Check", - 1: "Download", - } - UpdateAction_value = map[string]int32{ - "Check": 0, - "Download": 1, - } -) - -func (x UpdateAction) Enum() *UpdateAction { - p := new(UpdateAction) - *p = x - return p -} - -func (x UpdateAction) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (UpdateAction) Descriptor() protoreflect.EnumDescriptor { - return file_libcore_proto_enumTypes[1].Descriptor() -} - -func (UpdateAction) Type() protoreflect.EnumType { - return &file_libcore_proto_enumTypes[1] -} - -func (x UpdateAction) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use UpdateAction.Descriptor instead. -func (UpdateAction) EnumDescriptor() ([]byte, []int) { - return file_libcore_proto_rawDescGZIP(), []int{1} -} - -type EmptyReq struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *EmptyReq) Reset() { - *x = EmptyReq{} - if protoimpl.UnsafeEnabled { - mi := &file_libcore_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *EmptyReq) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*EmptyReq) ProtoMessage() {} - -func (x *EmptyReq) ProtoReflect() protoreflect.Message { - mi := &file_libcore_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use EmptyReq.ProtoReflect.Descriptor instead. -func (*EmptyReq) Descriptor() ([]byte, []int) { - return file_libcore_proto_rawDescGZIP(), []int{0} -} - -type EmptyResp struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *EmptyResp) Reset() { - *x = EmptyResp{} - if protoimpl.UnsafeEnabled { - mi := &file_libcore_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *EmptyResp) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*EmptyResp) ProtoMessage() {} - -func (x *EmptyResp) ProtoReflect() protoreflect.Message { - mi := &file_libcore_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use EmptyResp.ProtoReflect.Descriptor instead. -func (*EmptyResp) Descriptor() ([]byte, []int) { - return file_libcore_proto_rawDescGZIP(), []int{1} -} - -type ErrorResp struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Error string `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"` -} - -func (x *ErrorResp) Reset() { - *x = ErrorResp{} - if protoimpl.UnsafeEnabled { - mi := &file_libcore_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ErrorResp) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ErrorResp) ProtoMessage() {} - -func (x *ErrorResp) ProtoReflect() protoreflect.Message { - mi := &file_libcore_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ErrorResp.ProtoReflect.Descriptor instead. -func (*ErrorResp) Descriptor() ([]byte, []int) { - return file_libcore_proto_rawDescGZIP(), []int{2} -} - -func (x *ErrorResp) GetError() string { - if x != nil { - return x.Error - } - return "" -} - -type LoadConfigReq struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - CoreConfig string `protobuf:"bytes,1,opt,name=core_config,json=coreConfig,proto3" json:"core_config,omitempty"` - EnableNekorayConnections bool `protobuf:"varint,2,opt,name=enable_nekoray_connections,json=enableNekorayConnections,proto3" json:"enable_nekoray_connections,omitempty"` - StatsOutbounds []string `protobuf:"bytes,3,rep,name=stats_outbounds,json=statsOutbounds,proto3" json:"stats_outbounds,omitempty"` -} - -func (x *LoadConfigReq) Reset() { - *x = LoadConfigReq{} - if protoimpl.UnsafeEnabled { - mi := &file_libcore_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LoadConfigReq) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LoadConfigReq) ProtoMessage() {} - -func (x *LoadConfigReq) ProtoReflect() protoreflect.Message { - mi := &file_libcore_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use LoadConfigReq.ProtoReflect.Descriptor instead. -func (*LoadConfigReq) Descriptor() ([]byte, []int) { - return file_libcore_proto_rawDescGZIP(), []int{3} -} - -func (x *LoadConfigReq) GetCoreConfig() string { - if x != nil { - return x.CoreConfig - } - return "" -} - -func (x *LoadConfigReq) GetEnableNekorayConnections() bool { - if x != nil { - return x.EnableNekorayConnections - } - return false -} - -func (x *LoadConfigReq) GetStatsOutbounds() []string { - if x != nil { - return x.StatsOutbounds - } - return nil -} - -type TestReq struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Mode TestMode `protobuf:"varint,1,opt,name=mode,proto3,enum=libcore.TestMode" json:"mode,omitempty"` - Timeout int32 `protobuf:"varint,6,opt,name=timeout,proto3" json:"timeout,omitempty"` - // TcpPing - Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` - // UrlTest - Config *LoadConfigReq `protobuf:"bytes,3,opt,name=config,proto3" json:"config,omitempty"` - Inbound string `protobuf:"bytes,4,opt,name=inbound,proto3" json:"inbound,omitempty"` - Url string `protobuf:"bytes,5,opt,name=url,proto3" json:"url,omitempty"` - // FullTest - InAddress string `protobuf:"bytes,7,opt,name=in_address,json=inAddress,proto3" json:"in_address,omitempty"` - FullLatency bool `protobuf:"varint,8,opt,name=full_latency,json=fullLatency,proto3" json:"full_latency,omitempty"` - FullSpeed bool `protobuf:"varint,9,opt,name=full_speed,json=fullSpeed,proto3" json:"full_speed,omitempty"` - FullSpeedUrl string `protobuf:"bytes,13,opt,name=full_speed_url,json=fullSpeedUrl,proto3" json:"full_speed_url,omitempty"` - FullSpeedTimeout int32 `protobuf:"varint,14,opt,name=full_speed_timeout,json=fullSpeedTimeout,proto3" json:"full_speed_timeout,omitempty"` - FullInOut bool `protobuf:"varint,10,opt,name=full_in_out,json=fullInOut,proto3" json:"full_in_out,omitempty"` - FullUdpLatency bool `protobuf:"varint,12,opt,name=full_udp_latency,json=fullUdpLatency,proto3" json:"full_udp_latency,omitempty"` - // Deprecated: Do not use. - FullNat bool `protobuf:"varint,11,opt,name=full_nat,json=fullNat,proto3" json:"full_nat,omitempty"` -} - -func (x *TestReq) Reset() { - *x = TestReq{} - if protoimpl.UnsafeEnabled { - mi := &file_libcore_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TestReq) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TestReq) ProtoMessage() {} - -func (x *TestReq) ProtoReflect() protoreflect.Message { - mi := &file_libcore_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TestReq.ProtoReflect.Descriptor instead. -func (*TestReq) Descriptor() ([]byte, []int) { - return file_libcore_proto_rawDescGZIP(), []int{4} -} - -func (x *TestReq) GetMode() TestMode { - if x != nil { - return x.Mode - } - return TestMode_TcpPing -} - -func (x *TestReq) GetTimeout() int32 { - if x != nil { - return x.Timeout - } - return 0 -} - -func (x *TestReq) GetAddress() string { - if x != nil { - return x.Address - } - return "" -} - -func (x *TestReq) GetConfig() *LoadConfigReq { - if x != nil { - return x.Config - } - return nil -} - -func (x *TestReq) GetInbound() string { - if x != nil { - return x.Inbound - } - return "" -} - -func (x *TestReq) GetUrl() string { - if x != nil { - return x.Url - } - return "" -} - -func (x *TestReq) GetInAddress() string { - if x != nil { - return x.InAddress - } - return "" -} - -func (x *TestReq) GetFullLatency() bool { - if x != nil { - return x.FullLatency - } - return false -} - -func (x *TestReq) GetFullSpeed() bool { - if x != nil { - return x.FullSpeed - } - return false -} - -func (x *TestReq) GetFullSpeedUrl() string { - if x != nil { - return x.FullSpeedUrl - } - return "" -} - -func (x *TestReq) GetFullSpeedTimeout() int32 { - if x != nil { - return x.FullSpeedTimeout - } - return 0 -} - -func (x *TestReq) GetFullInOut() bool { - if x != nil { - return x.FullInOut - } - return false -} - -func (x *TestReq) GetFullUdpLatency() bool { - if x != nil { - return x.FullUdpLatency - } - return false -} - -// Deprecated: Do not use. -func (x *TestReq) GetFullNat() bool { - if x != nil { - return x.FullNat - } - return false -} - -type TestResp struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Error string `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"` - Ms int32 `protobuf:"varint,2,opt,name=ms,proto3" json:"ms,omitempty"` - FullReport string `protobuf:"bytes,3,opt,name=full_report,json=fullReport,proto3" json:"full_report,omitempty"` -} - -func (x *TestResp) Reset() { - *x = TestResp{} - if protoimpl.UnsafeEnabled { - mi := &file_libcore_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TestResp) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TestResp) ProtoMessage() {} - -func (x *TestResp) ProtoReflect() protoreflect.Message { - mi := &file_libcore_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TestResp.ProtoReflect.Descriptor instead. -func (*TestResp) Descriptor() ([]byte, []int) { - return file_libcore_proto_rawDescGZIP(), []int{5} -} - -func (x *TestResp) GetError() string { - if x != nil { - return x.Error - } - return "" -} - -func (x *TestResp) GetMs() int32 { - if x != nil { - return x.Ms - } - return 0 -} - -func (x *TestResp) GetFullReport() string { - if x != nil { - return x.FullReport - } - return "" -} - -type QueryStatsReq struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"` - Direct string `protobuf:"bytes,2,opt,name=direct,proto3" json:"direct,omitempty"` -} - -func (x *QueryStatsReq) Reset() { - *x = QueryStatsReq{} - if protoimpl.UnsafeEnabled { - mi := &file_libcore_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *QueryStatsReq) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*QueryStatsReq) ProtoMessage() {} - -func (x *QueryStatsReq) ProtoReflect() protoreflect.Message { - mi := &file_libcore_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use QueryStatsReq.ProtoReflect.Descriptor instead. -func (*QueryStatsReq) Descriptor() ([]byte, []int) { - return file_libcore_proto_rawDescGZIP(), []int{6} -} - -func (x *QueryStatsReq) GetTag() string { - if x != nil { - return x.Tag - } - return "" -} - -func (x *QueryStatsReq) GetDirect() string { - if x != nil { - return x.Direct - } - return "" -} - -type QueryStatsResp struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Traffic int64 `protobuf:"varint,1,opt,name=traffic,proto3" json:"traffic,omitempty"` -} - -func (x *QueryStatsResp) Reset() { - *x = QueryStatsResp{} - if protoimpl.UnsafeEnabled { - mi := &file_libcore_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *QueryStatsResp) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*QueryStatsResp) ProtoMessage() {} - -func (x *QueryStatsResp) ProtoReflect() protoreflect.Message { - mi := &file_libcore_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use QueryStatsResp.ProtoReflect.Descriptor instead. -func (*QueryStatsResp) Descriptor() ([]byte, []int) { - return file_libcore_proto_rawDescGZIP(), []int{7} -} - -func (x *QueryStatsResp) GetTraffic() int64 { - if x != nil { - return x.Traffic - } - return 0 -} - -type UpdateReq struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Action UpdateAction `protobuf:"varint,1,opt,name=action,proto3,enum=libcore.UpdateAction" json:"action,omitempty"` - CheckPreRelease bool `protobuf:"varint,2,opt,name=check_pre_release,json=checkPreRelease,proto3" json:"check_pre_release,omitempty"` -} - -func (x *UpdateReq) Reset() { - *x = UpdateReq{} - if protoimpl.UnsafeEnabled { - mi := &file_libcore_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *UpdateReq) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*UpdateReq) ProtoMessage() {} - -func (x *UpdateReq) ProtoReflect() protoreflect.Message { - mi := &file_libcore_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use UpdateReq.ProtoReflect.Descriptor instead. -func (*UpdateReq) Descriptor() ([]byte, []int) { - return file_libcore_proto_rawDescGZIP(), []int{8} -} - -func (x *UpdateReq) GetAction() UpdateAction { - if x != nil { - return x.Action - } - return UpdateAction_Check -} - -func (x *UpdateReq) GetCheckPreRelease() bool { - if x != nil { - return x.CheckPreRelease - } - return false -} - -type UpdateResp struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Error string `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"` - AssetsName string `protobuf:"bytes,2,opt,name=assets_name,json=assetsName,proto3" json:"assets_name,omitempty"` - DownloadUrl string `protobuf:"bytes,3,opt,name=download_url,json=downloadUrl,proto3" json:"download_url,omitempty"` - ReleaseUrl string `protobuf:"bytes,4,opt,name=release_url,json=releaseUrl,proto3" json:"release_url,omitempty"` - ReleaseNote string `protobuf:"bytes,5,opt,name=release_note,json=releaseNote,proto3" json:"release_note,omitempty"` - IsPreRelease bool `protobuf:"varint,6,opt,name=is_pre_release,json=isPreRelease,proto3" json:"is_pre_release,omitempty"` -} - -func (x *UpdateResp) Reset() { - *x = UpdateResp{} - if protoimpl.UnsafeEnabled { - mi := &file_libcore_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *UpdateResp) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*UpdateResp) ProtoMessage() {} - -func (x *UpdateResp) ProtoReflect() protoreflect.Message { - mi := &file_libcore_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use UpdateResp.ProtoReflect.Descriptor instead. -func (*UpdateResp) Descriptor() ([]byte, []int) { - return file_libcore_proto_rawDescGZIP(), []int{9} -} - -func (x *UpdateResp) GetError() string { - if x != nil { - return x.Error - } - return "" -} - -func (x *UpdateResp) GetAssetsName() string { - if x != nil { - return x.AssetsName - } - return "" -} - -func (x *UpdateResp) GetDownloadUrl() string { - if x != nil { - return x.DownloadUrl - } - return "" -} - -func (x *UpdateResp) GetReleaseUrl() string { - if x != nil { - return x.ReleaseUrl - } - return "" -} - -func (x *UpdateResp) GetReleaseNote() string { - if x != nil { - return x.ReleaseNote - } - return "" -} - -func (x *UpdateResp) GetIsPreRelease() bool { - if x != nil { - return x.IsPreRelease - } - return false -} - -type ListConnectionsResp struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - NekorayConnectionsJson string `protobuf:"bytes,1,opt,name=nekoray_connections_json,json=nekorayConnectionsJson,proto3" json:"nekoray_connections_json,omitempty"` -} - -func (x *ListConnectionsResp) Reset() { - *x = ListConnectionsResp{} - if protoimpl.UnsafeEnabled { - mi := &file_libcore_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListConnectionsResp) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListConnectionsResp) ProtoMessage() {} - -func (x *ListConnectionsResp) ProtoReflect() protoreflect.Message { - mi := &file_libcore_proto_msgTypes[10] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListConnectionsResp.ProtoReflect.Descriptor instead. -func (*ListConnectionsResp) Descriptor() ([]byte, []int) { - return file_libcore_proto_rawDescGZIP(), []int{10} -} - -func (x *ListConnectionsResp) GetNekorayConnectionsJson() string { - if x != nil { - return x.NekorayConnectionsJson - } - return "" -} - -var File_libcore_proto protoreflect.FileDescriptor - -var file_libcore_proto_rawDesc = []byte{ - 0x0a, 0x0d, 0x6c, 0x69, 0x62, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, - 0x07, 0x6c, 0x69, 0x62, 0x63, 0x6f, 0x72, 0x65, 0x22, 0x0a, 0x0a, 0x08, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x52, 0x65, 0x71, 0x22, 0x0b, 0x0a, 0x09, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x52, 0x65, 0x73, - 0x70, 0x22, 0x21, 0x0a, 0x09, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x12, 0x14, - 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, - 0x72, 0x72, 0x6f, 0x72, 0x22, 0x97, 0x01, 0x0a, 0x0d, 0x4c, 0x6f, 0x61, 0x64, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x72, 0x65, 0x5f, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x72, - 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3c, 0x0a, 0x1a, 0x65, 0x6e, 0x61, 0x62, 0x6c, - 0x65, 0x5f, 0x6e, 0x65, 0x6b, 0x6f, 0x72, 0x61, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x65, 0x6e, 0x61, - 0x62, 0x6c, 0x65, 0x4e, 0x65, 0x6b, 0x6f, 0x72, 0x61, 0x79, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x5f, 0x6f, - 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, - 0x73, 0x74, 0x61, 0x74, 0x73, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x22, 0xde, - 0x03, 0x0a, 0x07, 0x54, 0x65, 0x73, 0x74, 0x52, 0x65, 0x71, 0x12, 0x25, 0x0a, 0x04, 0x6d, 0x6f, - 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x6c, 0x69, 0x62, 0x63, 0x6f, - 0x72, 0x65, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6d, 0x6f, 0x64, - 0x65, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x2e, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6c, 0x69, 0x62, 0x63, 0x6f, 0x72, 0x65, 0x2e, - 0x4c, 0x6f, 0x61, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x52, 0x06, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, - 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, - 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x6e, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x75, 0x6c, 0x6c, 0x5f, 0x6c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x66, 0x75, 0x6c, 0x6c, 0x4c, 0x61, 0x74, 0x65, - 0x6e, 0x63, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x75, 0x6c, 0x6c, 0x5f, 0x73, 0x70, 0x65, 0x65, - 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x66, 0x75, 0x6c, 0x6c, 0x53, 0x70, 0x65, - 0x65, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x66, 0x75, 0x6c, 0x6c, 0x5f, 0x73, 0x70, 0x65, 0x65, 0x64, - 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x66, 0x75, 0x6c, 0x6c, - 0x53, 0x70, 0x65, 0x65, 0x64, 0x55, 0x72, 0x6c, 0x12, 0x2c, 0x0a, 0x12, 0x66, 0x75, 0x6c, 0x6c, - 0x5f, 0x73, 0x70, 0x65, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x0e, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x66, 0x75, 0x6c, 0x6c, 0x53, 0x70, 0x65, 0x65, 0x64, 0x54, - 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x1e, 0x0a, 0x0b, 0x66, 0x75, 0x6c, 0x6c, 0x5f, 0x69, - 0x6e, 0x5f, 0x6f, 0x75, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x66, 0x75, 0x6c, - 0x6c, 0x49, 0x6e, 0x4f, 0x75, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x66, 0x75, 0x6c, 0x6c, 0x5f, 0x75, - 0x64, 0x70, 0x5f, 0x6c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x0e, 0x66, 0x75, 0x6c, 0x6c, 0x55, 0x64, 0x70, 0x4c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, - 0x12, 0x1d, 0x0a, 0x08, 0x66, 0x75, 0x6c, 0x6c, 0x5f, 0x6e, 0x61, 0x74, 0x18, 0x0b, 0x20, 0x01, - 0x28, 0x08, 0x42, 0x02, 0x18, 0x01, 0x52, 0x07, 0x66, 0x75, 0x6c, 0x6c, 0x4e, 0x61, 0x74, 0x22, - 0x51, 0x0a, 0x08, 0x54, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x65, - 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, - 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x6d, - 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x75, 0x6c, 0x6c, 0x5f, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x66, 0x75, 0x6c, 0x6c, 0x52, 0x65, 0x70, 0x6f, - 0x72, 0x74, 0x22, 0x39, 0x0a, 0x0d, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x61, 0x74, 0x73, - 0x52, 0x65, 0x71, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x22, 0x2a, 0x0a, - 0x0e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, - 0x18, 0x0a, 0x07, 0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x07, 0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x22, 0x66, 0x0a, 0x09, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x12, 0x2d, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x6c, 0x69, 0x62, 0x63, 0x6f, 0x72, 0x65, - 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x61, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x11, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x5f, 0x70, - 0x72, 0x65, 0x5f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x0f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x50, 0x72, 0x65, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, - 0x65, 0x22, 0xd0, 0x01, 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x73, 0x73, 0x65, 0x74, 0x73, - 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x73, 0x73, - 0x65, 0x74, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x6f, 0x77, 0x6e, 0x6c, - 0x6f, 0x61, 0x64, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, - 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x72, 0x6c, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0a, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x55, 0x72, 0x6c, 0x12, 0x21, 0x0a, 0x0c, 0x72, - 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x6e, 0x6f, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0b, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4e, 0x6f, 0x74, 0x65, 0x12, 0x24, - 0x0a, 0x0e, 0x69, 0x73, 0x5f, 0x70, 0x72, 0x65, 0x5f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x73, 0x50, 0x72, 0x65, 0x52, 0x65, 0x6c, - 0x65, 0x61, 0x73, 0x65, 0x22, 0x4f, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x38, 0x0a, 0x18, 0x6e, - 0x65, 0x6b, 0x6f, 0x72, 0x61, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x6e, - 0x65, 0x6b, 0x6f, 0x72, 0x61, 0x79, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x4a, 0x73, 0x6f, 0x6e, 0x2a, 0x32, 0x0a, 0x08, 0x54, 0x65, 0x73, 0x74, 0x4d, 0x6f, 0x64, - 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x54, 0x63, 0x70, 0x50, 0x69, 0x6e, 0x67, 0x10, 0x00, 0x12, 0x0b, - 0x0a, 0x07, 0x55, 0x72, 0x6c, 0x54, 0x65, 0x73, 0x74, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x46, - 0x75, 0x6c, 0x6c, 0x54, 0x65, 0x73, 0x74, 0x10, 0x02, 0x2a, 0x27, 0x0a, 0x0c, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x09, 0x0a, 0x05, 0x43, 0x68, 0x65, - 0x63, 0x6b, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, - 0x10, 0x01, 0x32, 0x94, 0x03, 0x0a, 0x0e, 0x4c, 0x69, 0x62, 0x63, 0x6f, 0x72, 0x65, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x2f, 0x0a, 0x04, 0x45, 0x78, 0x69, 0x74, 0x12, 0x11, 0x2e, - 0x6c, 0x69, 0x62, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x52, 0x65, 0x71, - 0x1a, 0x12, 0x2e, 0x6c, 0x69, 0x62, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x33, 0x0a, 0x06, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x12, 0x12, 0x2e, 0x6c, 0x69, 0x62, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x52, 0x65, 0x71, 0x1a, 0x13, 0x2e, 0x6c, 0x69, 0x62, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x35, 0x0a, 0x05, 0x53, - 0x74, 0x61, 0x72, 0x74, 0x12, 0x16, 0x2e, 0x6c, 0x69, 0x62, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, - 0x6f, 0x61, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x1a, 0x12, 0x2e, 0x6c, - 0x69, 0x62, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, - 0x22, 0x00, 0x12, 0x2f, 0x0a, 0x04, 0x53, 0x74, 0x6f, 0x70, 0x12, 0x11, 0x2e, 0x6c, 0x69, 0x62, - 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x52, 0x65, 0x71, 0x1a, 0x12, 0x2e, - 0x6c, 0x69, 0x62, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x73, - 0x70, 0x22, 0x00, 0x12, 0x2d, 0x0a, 0x04, 0x54, 0x65, 0x73, 0x74, 0x12, 0x10, 0x2e, 0x6c, 0x69, - 0x62, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x11, 0x2e, - 0x6c, 0x69, 0x62, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x22, 0x00, 0x12, 0x3f, 0x0a, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x61, 0x74, 0x73, - 0x12, 0x16, 0x2e, 0x6c, 0x69, 0x62, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, - 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x17, 0x2e, 0x6c, 0x69, 0x62, 0x63, 0x6f, - 0x72, 0x65, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x22, 0x00, 0x12, 0x44, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x11, 0x2e, 0x6c, 0x69, 0x62, 0x63, 0x6f, 0x72, 0x65, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x52, 0x65, 0x71, 0x1a, 0x1c, 0x2e, 0x6c, 0x69, 0x62, 0x63, - 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x42, 0x11, 0x5a, 0x0f, 0x67, 0x72, 0x70, - 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x67, 0x65, 0x6e, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_libcore_proto_rawDescOnce sync.Once - file_libcore_proto_rawDescData = file_libcore_proto_rawDesc -) - -func file_libcore_proto_rawDescGZIP() []byte { - file_libcore_proto_rawDescOnce.Do(func() { - file_libcore_proto_rawDescData = protoimpl.X.CompressGZIP(file_libcore_proto_rawDescData) - }) - return file_libcore_proto_rawDescData -} - -var file_libcore_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_libcore_proto_msgTypes = make([]protoimpl.MessageInfo, 11) -var file_libcore_proto_goTypes = []interface{}{ - (TestMode)(0), // 0: libcore.TestMode - (UpdateAction)(0), // 1: libcore.UpdateAction - (*EmptyReq)(nil), // 2: libcore.EmptyReq - (*EmptyResp)(nil), // 3: libcore.EmptyResp - (*ErrorResp)(nil), // 4: libcore.ErrorResp - (*LoadConfigReq)(nil), // 5: libcore.LoadConfigReq - (*TestReq)(nil), // 6: libcore.TestReq - (*TestResp)(nil), // 7: libcore.TestResp - (*QueryStatsReq)(nil), // 8: libcore.QueryStatsReq - (*QueryStatsResp)(nil), // 9: libcore.QueryStatsResp - (*UpdateReq)(nil), // 10: libcore.UpdateReq - (*UpdateResp)(nil), // 11: libcore.UpdateResp - (*ListConnectionsResp)(nil), // 12: libcore.ListConnectionsResp -} -var file_libcore_proto_depIdxs = []int32{ - 0, // 0: libcore.TestReq.mode:type_name -> libcore.TestMode - 5, // 1: libcore.TestReq.config:type_name -> libcore.LoadConfigReq - 1, // 2: libcore.UpdateReq.action:type_name -> libcore.UpdateAction - 2, // 3: libcore.LibcoreService.Exit:input_type -> libcore.EmptyReq - 10, // 4: libcore.LibcoreService.Update:input_type -> libcore.UpdateReq - 5, // 5: libcore.LibcoreService.Start:input_type -> libcore.LoadConfigReq - 2, // 6: libcore.LibcoreService.Stop:input_type -> libcore.EmptyReq - 6, // 7: libcore.LibcoreService.Test:input_type -> libcore.TestReq - 8, // 8: libcore.LibcoreService.QueryStats:input_type -> libcore.QueryStatsReq - 2, // 9: libcore.LibcoreService.ListConnections:input_type -> libcore.EmptyReq - 3, // 10: libcore.LibcoreService.Exit:output_type -> libcore.EmptyResp - 11, // 11: libcore.LibcoreService.Update:output_type -> libcore.UpdateResp - 4, // 12: libcore.LibcoreService.Start:output_type -> libcore.ErrorResp - 4, // 13: libcore.LibcoreService.Stop:output_type -> libcore.ErrorResp - 7, // 14: libcore.LibcoreService.Test:output_type -> libcore.TestResp - 9, // 15: libcore.LibcoreService.QueryStats:output_type -> libcore.QueryStatsResp - 12, // 16: libcore.LibcoreService.ListConnections:output_type -> libcore.ListConnectionsResp - 10, // [10:17] is the sub-list for method output_type - 3, // [3:10] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name -} - -func init() { file_libcore_proto_init() } -func file_libcore_proto_init() { - if File_libcore_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_libcore_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EmptyReq); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_libcore_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EmptyResp); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_libcore_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ErrorResp); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_libcore_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LoadConfigReq); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_libcore_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TestReq); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_libcore_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TestResp); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_libcore_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*QueryStatsReq); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_libcore_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*QueryStatsResp); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_libcore_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UpdateReq); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_libcore_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UpdateResp); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_libcore_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListConnectionsResp); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_libcore_proto_rawDesc, - NumEnums: 2, - NumMessages: 11, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_libcore_proto_goTypes, - DependencyIndexes: file_libcore_proto_depIdxs, - EnumInfos: file_libcore_proto_enumTypes, - MessageInfos: file_libcore_proto_msgTypes, - }.Build() - File_libcore_proto = out.File - file_libcore_proto_rawDesc = nil - file_libcore_proto_goTypes = nil - file_libcore_proto_depIdxs = nil -} diff --git a/go/grpc_server/gen/libcore.proto b/go/grpc_server/gen/libcore.proto deleted file mode 100644 index 23abf1b..0000000 --- a/go/grpc_server/gen/libcore.proto +++ /dev/null @@ -1,94 +0,0 @@ -syntax = "proto3"; - -package libcore; -option go_package = "grpc_server/gen"; - -service LibcoreService { - rpc Exit(EmptyReq) returns (EmptyResp) {} - rpc Update(UpdateReq) returns (UpdateResp) {} - // - rpc Start(LoadConfigReq) returns (ErrorResp) {} - rpc Stop(EmptyReq) returns (ErrorResp) {} - rpc Test(TestReq) returns (TestResp) {} - rpc QueryStats(QueryStatsReq) returns (QueryStatsResp) {} - rpc ListConnections(EmptyReq) returns (ListConnectionsResp) {} -} - -message EmptyReq {} - -message EmptyResp {} - -message ErrorResp { - string error = 1; -} - -message LoadConfigReq { - string core_config = 1; - bool enable_nekoray_connections = 2; - repeated string stats_outbounds = 3; -} - -enum TestMode { - TcpPing = 0; - UrlTest = 1; - FullTest = 2; -} - -message TestReq { - TestMode mode = 1; - int32 timeout = 6; - // TcpPing - string address = 2; - // UrlTest - LoadConfigReq config = 3; - string inbound = 4; - string url = 5; - // FullTest - string in_address = 7; - bool full_latency = 8; - bool full_speed = 9; - string full_speed_url = 13; - int32 full_speed_timeout = 14; - bool full_in_out = 10; - bool full_udp_latency = 12; - // - bool full_nat = 11 [deprecated = true]; -} - -message TestResp { - string error = 1; - int32 ms = 2; - string full_report = 3; -} - -message QueryStatsReq{ - string tag = 1; - string direct = 2; -} - -message QueryStatsResp{ - int64 traffic = 1; -} - -enum UpdateAction { - Check = 0; - Download = 1; -} - -message UpdateReq { - UpdateAction action = 1; - bool check_pre_release = 2; -} - -message UpdateResp { - string error = 1; - string assets_name = 2; - string download_url = 3; - string release_url = 4; - string release_note = 5; - bool is_pre_release = 6; -} - -message ListConnectionsResp { - string nekoray_connections_json = 1; -} diff --git a/go/grpc_server/gen/libcore_grpc.pb.go b/go/grpc_server/gen/libcore_grpc.pb.go deleted file mode 100644 index 663854b..0000000 --- a/go/grpc_server/gen/libcore_grpc.pb.go +++ /dev/null @@ -1,321 +0,0 @@ -// Code generated by protoc-gen-go-grpc. DO NOT EDIT. -// versions: -// - protoc-gen-go-grpc v1.2.0 -// - protoc v4.23.3 -// source: libcore.proto - -package gen - -import ( - context "context" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" -) - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.32.0 or later. -const _ = grpc.SupportPackageIsVersion7 - -// LibcoreServiceClient is the client API for LibcoreService service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. -type LibcoreServiceClient interface { - Exit(ctx context.Context, in *EmptyReq, opts ...grpc.CallOption) (*EmptyResp, error) - Update(ctx context.Context, in *UpdateReq, opts ...grpc.CallOption) (*UpdateResp, error) - Start(ctx context.Context, in *LoadConfigReq, opts ...grpc.CallOption) (*ErrorResp, error) - Stop(ctx context.Context, in *EmptyReq, opts ...grpc.CallOption) (*ErrorResp, error) - Test(ctx context.Context, in *TestReq, opts ...grpc.CallOption) (*TestResp, error) - QueryStats(ctx context.Context, in *QueryStatsReq, opts ...grpc.CallOption) (*QueryStatsResp, error) - ListConnections(ctx context.Context, in *EmptyReq, opts ...grpc.CallOption) (*ListConnectionsResp, error) -} - -type libcoreServiceClient struct { - cc grpc.ClientConnInterface -} - -func NewLibcoreServiceClient(cc grpc.ClientConnInterface) LibcoreServiceClient { - return &libcoreServiceClient{cc} -} - -func (c *libcoreServiceClient) Exit(ctx context.Context, in *EmptyReq, opts ...grpc.CallOption) (*EmptyResp, error) { - out := new(EmptyResp) - err := c.cc.Invoke(ctx, "/libcore.LibcoreService/Exit", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *libcoreServiceClient) Update(ctx context.Context, in *UpdateReq, opts ...grpc.CallOption) (*UpdateResp, error) { - out := new(UpdateResp) - err := c.cc.Invoke(ctx, "/libcore.LibcoreService/Update", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *libcoreServiceClient) Start(ctx context.Context, in *LoadConfigReq, opts ...grpc.CallOption) (*ErrorResp, error) { - out := new(ErrorResp) - err := c.cc.Invoke(ctx, "/libcore.LibcoreService/Start", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *libcoreServiceClient) Stop(ctx context.Context, in *EmptyReq, opts ...grpc.CallOption) (*ErrorResp, error) { - out := new(ErrorResp) - err := c.cc.Invoke(ctx, "/libcore.LibcoreService/Stop", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *libcoreServiceClient) Test(ctx context.Context, in *TestReq, opts ...grpc.CallOption) (*TestResp, error) { - out := new(TestResp) - err := c.cc.Invoke(ctx, "/libcore.LibcoreService/Test", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *libcoreServiceClient) QueryStats(ctx context.Context, in *QueryStatsReq, opts ...grpc.CallOption) (*QueryStatsResp, error) { - out := new(QueryStatsResp) - err := c.cc.Invoke(ctx, "/libcore.LibcoreService/QueryStats", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *libcoreServiceClient) ListConnections(ctx context.Context, in *EmptyReq, opts ...grpc.CallOption) (*ListConnectionsResp, error) { - out := new(ListConnectionsResp) - err := c.cc.Invoke(ctx, "/libcore.LibcoreService/ListConnections", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// LibcoreServiceServer is the server API for LibcoreService service. -// All implementations must embed UnimplementedLibcoreServiceServer -// for forward compatibility -type LibcoreServiceServer interface { - Exit(context.Context, *EmptyReq) (*EmptyResp, error) - Update(context.Context, *UpdateReq) (*UpdateResp, error) - Start(context.Context, *LoadConfigReq) (*ErrorResp, error) - Stop(context.Context, *EmptyReq) (*ErrorResp, error) - Test(context.Context, *TestReq) (*TestResp, error) - QueryStats(context.Context, *QueryStatsReq) (*QueryStatsResp, error) - ListConnections(context.Context, *EmptyReq) (*ListConnectionsResp, error) - mustEmbedUnimplementedLibcoreServiceServer() -} - -// UnimplementedLibcoreServiceServer must be embedded to have forward compatible implementations. -type UnimplementedLibcoreServiceServer struct { -} - -func (UnimplementedLibcoreServiceServer) Exit(context.Context, *EmptyReq) (*EmptyResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method Exit not implemented") -} -func (UnimplementedLibcoreServiceServer) Update(context.Context, *UpdateReq) (*UpdateResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method Update not implemented") -} -func (UnimplementedLibcoreServiceServer) Start(context.Context, *LoadConfigReq) (*ErrorResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method Start not implemented") -} -func (UnimplementedLibcoreServiceServer) Stop(context.Context, *EmptyReq) (*ErrorResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method Stop not implemented") -} -func (UnimplementedLibcoreServiceServer) Test(context.Context, *TestReq) (*TestResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method Test not implemented") -} -func (UnimplementedLibcoreServiceServer) QueryStats(context.Context, *QueryStatsReq) (*QueryStatsResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method QueryStats not implemented") -} -func (UnimplementedLibcoreServiceServer) ListConnections(context.Context, *EmptyReq) (*ListConnectionsResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method ListConnections not implemented") -} -func (UnimplementedLibcoreServiceServer) mustEmbedUnimplementedLibcoreServiceServer() {} - -// UnsafeLibcoreServiceServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to LibcoreServiceServer will -// result in compilation errors. -type UnsafeLibcoreServiceServer interface { - mustEmbedUnimplementedLibcoreServiceServer() -} - -func RegisterLibcoreServiceServer(s grpc.ServiceRegistrar, srv LibcoreServiceServer) { - s.RegisterService(&LibcoreService_ServiceDesc, srv) -} - -func _LibcoreService_Exit_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(EmptyReq) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(LibcoreServiceServer).Exit(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/libcore.LibcoreService/Exit", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(LibcoreServiceServer).Exit(ctx, req.(*EmptyReq)) - } - return interceptor(ctx, in, info, handler) -} - -func _LibcoreService_Update_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(UpdateReq) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(LibcoreServiceServer).Update(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/libcore.LibcoreService/Update", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(LibcoreServiceServer).Update(ctx, req.(*UpdateReq)) - } - return interceptor(ctx, in, info, handler) -} - -func _LibcoreService_Start_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(LoadConfigReq) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(LibcoreServiceServer).Start(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/libcore.LibcoreService/Start", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(LibcoreServiceServer).Start(ctx, req.(*LoadConfigReq)) - } - return interceptor(ctx, in, info, handler) -} - -func _LibcoreService_Stop_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(EmptyReq) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(LibcoreServiceServer).Stop(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/libcore.LibcoreService/Stop", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(LibcoreServiceServer).Stop(ctx, req.(*EmptyReq)) - } - return interceptor(ctx, in, info, handler) -} - -func _LibcoreService_Test_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(TestReq) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(LibcoreServiceServer).Test(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/libcore.LibcoreService/Test", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(LibcoreServiceServer).Test(ctx, req.(*TestReq)) - } - return interceptor(ctx, in, info, handler) -} - -func _LibcoreService_QueryStats_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryStatsReq) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(LibcoreServiceServer).QueryStats(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/libcore.LibcoreService/QueryStats", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(LibcoreServiceServer).QueryStats(ctx, req.(*QueryStatsReq)) - } - return interceptor(ctx, in, info, handler) -} - -func _LibcoreService_ListConnections_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(EmptyReq) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(LibcoreServiceServer).ListConnections(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/libcore.LibcoreService/ListConnections", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(LibcoreServiceServer).ListConnections(ctx, req.(*EmptyReq)) - } - return interceptor(ctx, in, info, handler) -} - -// LibcoreService_ServiceDesc is the grpc.ServiceDesc for LibcoreService service. -// It's only intended for direct use with grpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var LibcoreService_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "libcore.LibcoreService", - HandlerType: (*LibcoreServiceServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "Exit", - Handler: _LibcoreService_Exit_Handler, - }, - { - MethodName: "Update", - Handler: _LibcoreService_Update_Handler, - }, - { - MethodName: "Start", - Handler: _LibcoreService_Start_Handler, - }, - { - MethodName: "Stop", - Handler: _LibcoreService_Stop_Handler, - }, - { - MethodName: "Test", - Handler: _LibcoreService_Test_Handler, - }, - { - MethodName: "QueryStats", - Handler: _LibcoreService_QueryStats_Handler, - }, - { - MethodName: "ListConnections", - Handler: _LibcoreService_ListConnections_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "libcore.proto", -} diff --git a/go/grpc_server/gen/update_proto.sh b/go/grpc_server/gen/update_proto.sh deleted file mode 100644 index 709ed22..0000000 --- a/go/grpc_server/gen/update_proto.sh +++ /dev/null @@ -1,3 +0,0 @@ -protoc -I . --go_out=. --go_opt paths=source_relative --go-grpc_out=. --go-grpc_opt paths=source_relative libcore.proto - -# protoc -I . --cpp_out=. --grpc_out=. --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` libcore.proto diff --git a/go/grpc_server/go.mod b/go/grpc_server/go.mod deleted file mode 100644 index 2e7a85e..0000000 --- a/go/grpc_server/go.mod +++ /dev/null @@ -1,21 +0,0 @@ -module grpc_server - -go 1.19 - -require ( - github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 - github.com/matsuridayo/libneko v1.0.0 // replaced - google.golang.org/grpc v1.49.0 - google.golang.org/protobuf v1.28.1 -) - -require ( - github.com/golang/protobuf v1.5.2 // indirect - github.com/google/go-cmp v0.5.8 // indirect - golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e // indirect - golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect - golang.org/x/text v0.3.7 // indirect - google.golang.org/genproto v0.0.0-20211223182754-3ac035c7e7cb // indirect -) - -replace github.com/matsuridayo/libneko v1.0.0 => ../../../libneko diff --git a/go/grpc_server/go.sum b/go/grpc_server/go.sum deleted file mode 100644 index 6140d88..0000000 --- a/go/grpc_server/go.sum +++ /dev/null @@ -1,178 +0,0 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0 h1:eOI3/cP2VTU6uZLDYAoic+eyzzB9YyGmJ7eIjl8rOPg= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e h1:TsQ7F31D3bUCLeqPT0u+yjp1guoArKaNKmCr22PYgTQ= -golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20211223182754-3ac035c7e7cb h1:ZrsicilzPCS/Xr8qtBZZLpy4P9TYXAfl49ctG1/5tgw= -google.golang.org/genproto v0.0.0-20211223182754-3ac035c7e7cb/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.49.0 h1:WTLtQzmQori5FUH25Pq4WT22oCsv8USpQ+F6rqtsmxw= -google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3 h1:fvjTMHxHEw/mxHbtzPi3JCcKXQRAnQTBRo6YCJSVHKI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/go/grpc_server/grpc.go b/go/grpc_server/grpc.go deleted file mode 100644 index 210f780..0000000 --- a/go/grpc_server/grpc.go +++ /dev/null @@ -1,103 +0,0 @@ -package grpc_server - -import ( - "bufio" - "context" - "flag" - "fmt" - "grpc_server/auth" - "grpc_server/gen" - "log" - "net" - "os" - "runtime" - "strconv" - "strings" - "syscall" - "time" - - "github.com/matsuridayo/libneko/neko_common" - - grpc_auth "github.com/grpc-ecosystem/go-grpc-middleware/auth" - "google.golang.org/grpc" -) - -type BaseServer struct { - gen.LibcoreServiceServer -} - -func (s *BaseServer) Exit(ctx context.Context, in *gen.EmptyReq) (out *gen.EmptyResp, _ error) { - out = &gen.EmptyResp{} - - // Connection closed - os.Exit(0) - return -} - -func RunCore(setupCore func(), server gen.LibcoreServiceServer) { - _token := flag.String("token", "", "") - _port := flag.Int("port", 19810, "") - _debug := flag.Bool("debug", false, "") - flag.CommandLine.Parse(os.Args[2:]) - - neko_common.Debug = *_debug - - go func() { - parent, err := os.FindProcess(os.Getppid()) - if err != nil { - log.Fatalln("find parent:", err) - } - if runtime.GOOS == "windows" { - state, err := parent.Wait() - log.Fatalln("parent exited:", state, err) - } else { - for { - time.Sleep(time.Second * 10) - err = parent.Signal(syscall.Signal(0)) - if err != nil { - log.Fatalln("parent exited:", err) - } - } - } - }() - - // Libcore - setupCore() - - // GRPC - lis, err := net.Listen("tcp", "127.0.0.1:"+strconv.Itoa(*_port)) - if err != nil { - log.Fatalf("failed to listen: %v", err) - } - - token := *_token - if token == "" { - os.Stderr.WriteString("Please set a token: ") - s := bufio.NewScanner(os.Stdin) - if s.Scan() { - token = strings.TrimSpace(s.Text()) - } - } - if token == "" { - fmt.Println("You must set a token") - os.Exit(0) - } - os.Stderr.WriteString("token is set\n") - - auther := auth.Authenticator{ - Token: token, - } - - s := grpc.NewServer( - grpc.StreamInterceptor(grpc_auth.StreamServerInterceptor(auther.Authenticate)), - grpc.UnaryInterceptor(grpc_auth.UnaryServerInterceptor(auther.Authenticate)), - ) - gen.RegisterLibcoreServiceServer(s, server) - - name := "nekobox_core" - - log.Printf("%s grpc server listening at %v\n", name, lis.Addr()) - if err := s.Serve(lis); err != nil { - log.Fatalf("failed to serve: %v", err) - } -} diff --git a/go/grpc_server/update.go b/go/grpc_server/update.go deleted file mode 100644 index 2e7224e..0000000 --- a/go/grpc_server/update.go +++ /dev/null @@ -1,116 +0,0 @@ -package grpc_server - -import ( - "context" - "encoding/json" - "grpc_server/gen" - "io" - "net/http" - "os" - "runtime" - "strings" - "time" - - "github.com/matsuridayo/libneko/neko_common" -) - -var update_download_url string - -func (s *BaseServer) Update(ctx context.Context, in *gen.UpdateReq) (*gen.UpdateResp, error) { - ret := &gen.UpdateResp{} - - client := neko_common.CreateProxyHttpClient(neko_common.GetCurrentInstance()) - - if in.Action == gen.UpdateAction_Check { // Check update - ctx, cancel := context.WithTimeout(ctx, time.Second*10) - defer cancel() - - req, _ := http.NewRequestWithContext(ctx, "GET", "https://api.github.com/repos/MatsuriDayo/nekoray/releases", nil) - resp, err := client.Do(req) - if err != nil { - ret.Error = err.Error() - return ret, nil - } - defer resp.Body.Close() - - v := []struct { - HtmlUrl string `json:"html_url"` - Assets []struct { - Name string `json:"name"` - BrowserDownloadUrl string `json:"browser_download_url"` - } `json:"assets"` - Prerelease bool `json:"prerelease"` - Body string `json:"body"` - }{} - err = json.NewDecoder(resp.Body).Decode(&v) - if err != nil { - ret.Error = err.Error() - return ret, nil - } - - nowVer := strings.TrimLeft(neko_common.Version_neko, "nekoray-") - - var search string - if runtime.GOOS == "windows" && runtime.GOARCH == "amd64" { - search = "windows64" - } else if runtime.GOOS == "linux" && runtime.GOARCH == "amd64" { - search = "linux64" - } else if runtime.GOOS == "darwin" { - search = "macos-" + runtime.GOARCH - } else { - ret.Error = "Not official support platform" - return ret, nil - } - - for _, release := range v { - if len(release.Assets) > 0 { - for _, asset := range release.Assets { - if strings.Contains(asset.Name, nowVer) { - return ret, nil // No update - } - if strings.Contains(asset.Name, search) { - if release.Prerelease && !in.CheckPreRelease { - continue - } - update_download_url = asset.BrowserDownloadUrl - ret.AssetsName = asset.Name - ret.DownloadUrl = asset.BrowserDownloadUrl - ret.ReleaseUrl = release.HtmlUrl - ret.ReleaseNote = release.Body - ret.IsPreRelease = release.Prerelease - return ret, nil // update - } - } - } - } - } else { // Download update - if update_download_url == "" { - ret.Error = "?" - return ret, nil - } - - req, _ := http.NewRequestWithContext(ctx, "GET", update_download_url, nil) - resp, err := client.Do(req) - if err != nil { - ret.Error = err.Error() - return ret, nil - } - defer resp.Body.Close() - - f, err := os.OpenFile("../nekoray.zip", os.O_TRUNC|os.O_CREATE|os.O_RDWR, 0644) - if err != nil { - ret.Error = err.Error() - return ret, nil - } - defer f.Close() - - _, err = io.Copy(f, resp.Body) - if err != nil { - ret.Error = err.Error() - return ret, nil - } - f.Sync() - } - - return ret, nil -} diff --git a/libs/.gitignore b/libs/.gitignore deleted file mode 100644 index ecbf89d..0000000 --- a/libs/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/deps* -downloaded \ No newline at end of file diff --git a/libs/build_deps_all.sh b/libs/build_deps_all.sh deleted file mode 100755 index a17b803..0000000 --- a/libs/build_deps_all.sh +++ /dev/null @@ -1,75 +0,0 @@ -#!/bin/bash -set -e - -cd libs - -# 参数 -if [ -z $cmake ]; then - cmake="cmake" -fi -if [ -z $deps ]; then - deps="deps" -fi - -# libs/deps/... -mkdir -p $deps -cd $deps -if [ -z $NKR_PACKAGE ]; then - INSTALL_PREFIX=$PWD/built -else - INSTALL_PREFIX=$PWD/package -fi -rm -rf $INSTALL_PREFIX -mkdir -p $INSTALL_PREFIX - -#### clean #### -clean() { - rm -rf dl.zip yaml-* zxing-* protobuf -} - -#### ZXing v2.0.0 #### -curl -L -o dl.zip https://github.com/nu-book/zxing-cpp/archive/refs/tags/v2.0.0.zip -unzip dl.zip - -cd zxing-* -mkdir -p build -cd build - -$cmake .. -GNinja -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DBUILD_EXAMPLES=OFF -DBUILD_BLACKBOX_TESTS=OFF -DCMAKE_INSTALL_PREFIX=$INSTALL_PREFIX -ninja && ninja install - -cd ../.. - -#### yaml-cpp #### -curl -L -o dl.zip https://github.com/jbeder/yaml-cpp/archive/refs/tags/yaml-cpp-0.7.0.zip -unzip dl.zip - -cd yaml-* -mkdir -p build -cd build - -$cmake .. -GNinja -DBUILD_SHARED_LIBS=OFF -DBUILD_TESTING=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$INSTALL_PREFIX -ninja && ninja install - -cd ../.. - -#### protobuf #### -git clone --recurse-submodules -b v21.4 --depth 1 --shallow-submodules https://github.com/protocolbuffers/protobuf - -#备注:交叉编译要在 host 也安装 protobuf 并且版本一致,编译安装,同参数,安装到 /usr/local - -mkdir -p protobuf/build -cd protobuf/build - -$cmake .. -GNinja \ - -DCMAKE_BUILD_TYPE=Release \ - -DBUILD_SHARED_LIBS=OFF \ - -Dprotobuf_MSVC_STATIC_RUNTIME=OFF \ - -Dprotobuf_BUILD_TESTS=OFF \ - -DCMAKE_INSTALL_PREFIX=$INSTALL_PREFIX -ninja && ninja install - -cd ../.. - -#### -clean diff --git a/libs/build_go.sh b/libs/build_go.sh deleted file mode 100755 index 966ae18..0000000 --- a/libs/build_go.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash -set -e - -source libs/env_deploy.sh -[ "$GOOS" == "windows" ] && [ "$GOARCH" == "amd64" ] && DEST=$DEPLOYMENT/windows64 || true -[ "$GOOS" == "windows" ] && [ "$GOARCH" == "arm64" ] && DEST=$DEPLOYMENT/windows-arm64 || true -[ "$GOOS" == "linux" ] && [ "$GOARCH" == "amd64" ] && DEST=$DEPLOYMENT/linux64 || true -[ "$GOOS" == "linux" ] && [ "$GOARCH" == "arm64" ] && DEST=$DEPLOYMENT/linux-arm64 || true -if [ -z $DEST ]; then - echo "Please set GOOS GOARCH" - exit 1 -fi -rm -rf $DEST -mkdir -p $DEST - -export CGO_ENABLED=0 - -#### Go: updater #### -pushd go/cmd/updater -[ "$GOOS" == "darwin" ] || go build -o $DEST -trimpath -ldflags "-w -s" -[ "$GOOS" == "linux" ] && mv $DEST/updater $DEST/launcher || true -popd - -#### Go: nekobox_core #### -pushd go/cmd/nekobox_core -go build -v -o $DEST -trimpath -ldflags "-w -s -X github.com/matsuridayo/libneko/neko_common.Version_neko=$version_standalone" -tags "with_clash_api,with_gvisor,with_quic,with_wireguard,with_utls,with_ech" -popd diff --git a/libs/build_public_res.sh b/libs/build_public_res.sh deleted file mode 100755 index 0fdbf19..0000000 --- a/libs/build_public_res.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash -set -e - -source libs/env_deploy.sh -DEST=$DEPLOYMENT/public_res -rm -rf $DEST -mkdir -p $DEST - -#### Download geodata #### -curl -fLso $DEST/geoip.dat "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat" -curl -fLso $DEST/geosite.dat "https://github.com/v2fly/domain-list-community/releases/latest/download/dlc.dat" -curl -fLso $DEST/geoip.db "https://github.com/SagerNet/sing-geoip/releases/latest/download/geoip.db" -curl -fLso $DEST/geosite.db "https://github.com/SagerNet/sing-geosite/releases/latest/download/geosite.db" - -#### copy res/public #### -cp res/public/* $DEST diff --git a/libs/deploy_linux64.sh b/libs/deploy_linux64.sh deleted file mode 100755 index 76d0b29..0000000 --- a/libs/deploy_linux64.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/bin/bash -set -e - -source libs/env_deploy.sh -DEST=$DEPLOYMENT/linux64 -rm -rf $DEST -mkdir -p $DEST - -#### copy binary #### -cp $BUILD/nekobox $DEST - -#### Download: prebuilt runtime #### -curl -Lso usr.zip https://github.com/MatsuriDayo/nekoray_qt_runtime/releases/download/20220503/20230202-5.12.8-ubuntu20.04-linux64.zip -unzip usr.zip -mv usr $DEST - - -#### copy so #### -# 5.11 looks buggy on new systems... -exit - -USR_LIB=/usr/lib/x86_64-linux-gnu -mkdir usr -pushd usr -mkdir lib -pushd lib -cp $USR_LIB/libQt5Core.so.5 . -cp $USR_LIB/libQt5DBus.so.5 . -cp $USR_LIB/libQt5Gui.so.5 . -cp $USR_LIB/libQt5Network.so.5 . -cp $USR_LIB/libQt5Svg.so.5 . -cp $USR_LIB/libQt5Widgets.so.5 . -cp $USR_LIB/libQt5X11Extras.so.5 . -cp $USR_LIB/libQt5XcbQpa.so.5 . -cp $USR_LIB/libdouble-conversion.so.? . -cp $USR_LIB/libxcb-util.so.? . -cp $USR_LIB/libicuuc.so.?? . -cp $USR_LIB/libicui18n.so.?? . -cp $USR_LIB/libicudata.so.?? . -popd -mkdir plugins -pushd plugins -cp -r $USR_LIB/qt5/plugins/bearer . -cp -r $USR_LIB/qt5/plugins/iconengines . -cp -r $USR_LIB/qt5/plugins/imageformats . -cp -r $USR_LIB/qt5/plugins/platforminputcontexts . -cp -r $USR_LIB/qt5/plugins/platforms . -cp -r $USR_LIB/qt5/plugins/xcbglintegrations . -popd -popd -mv usr $DEST diff --git a/libs/deploy_windows64.sh b/libs/deploy_windows64.sh deleted file mode 100755 index a513aad..0000000 --- a/libs/deploy_windows64.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash -set -e - -source libs/env_deploy.sh -DEST=$DEPLOYMENT/windows64 -rm -rf $DEST -mkdir -p $DEST - -#### copy exe #### -cp $BUILD/nekobox.exe $DEST - -#### deploy qt & DLL runtime #### -pushd $DEST -windeployqt nekobox.exe --no-compiler-runtime --no-system-d3d-compiler --no-opengl-sw --verbose 2 -rm -rf translations -rm -rf libEGL.dll libGLESv2.dll Qt6Pdf.dll - -if [ "$DL_QT_VER" != "5.15" ]; then - cp $SRC_ROOT/qtsdk/Qt/bin/libcrypto-3-x64.dll . - cp $SRC_ROOT/qtsdk/Qt/bin/libssl-3-x64.dll . -fi - -popd - -#### prepare deployment #### -cp $BUILD/*.pdb $DEPLOYMENT diff --git a/libs/download_qtsdk_win.sh b/libs/download_qtsdk_win.sh deleted file mode 100644 index f683210..0000000 --- a/libs/download_qtsdk_win.sh +++ /dev/null @@ -1,10 +0,0 @@ -mkdir qtsdk -cd qtsdk -if [ "$DL_QT_VER" == "5.15" ]; then - curl -LSO https://github.com/MatsuriDayo/nekoray_qt_runtime/releases/download/20220503/Qt5.15.7-Windows-x86_64-VS2019-16.11.20-20221103.7z -else - curl -LSO https://github.com/MatsuriDayo/nekoray_qt_runtime/releases/download/20220503/Qt6.7.2-Windows-x86_64-VS2022-17.10.3-20240621.7z -fi -7z x *.7z -rm *.7z -mv Qt* Qt diff --git a/libs/env_deploy.sh b/libs/env_deploy.sh deleted file mode 100644 index 9682533..0000000 --- a/libs/env_deploy.sh +++ /dev/null @@ -1,4 +0,0 @@ -SRC_ROOT="$PWD" -DEPLOYMENT="$SRC_ROOT/deployment" -BUILD="$SRC_ROOT/build" -version_standalone="nekoray-"$(cat nekoray_version.txt) # 下次改 diff --git a/libs/env_qtsdk.sh b/libs/env_qtsdk.sh deleted file mode 100644 index 0cf6eaa..0000000 --- a/libs/env_qtsdk.sh +++ /dev/null @@ -1,8 +0,0 @@ -echo "Setting Qt Sdk Dir to" "$1" -export Qt5_DIR="$1" -export Qt6_DIR=$Qt5_DIR -export PATH=$PATH:$Qt5_DIR/bin -export LD_LIBRARY_PATH=$Qt5_DIR/lib -export PKG_CONFIG_PATH=$Qt5_DIR/lib/pkgconfig -export QT_PLUGIN_PATH=$Qt5_DIR/plugins -export QML2_IMPORT_PATH=$Qt5_DIR/lib/qml diff --git a/libs/format_cpp.sh b/libs/format_cpp.sh deleted file mode 100755 index 1251ad5..0000000 --- a/libs/format_cpp.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -git ls-files | grep -E "\.cpp|\.h" | grep -v "3rdparty" | xargs -n1 clang-format -i diff --git a/libs/get_source.sh b/libs/get_source.sh deleted file mode 100755 index b416bd7..0000000 --- a/libs/get_source.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/bash -set -e - -source libs/env_deploy.sh -ENV_NEKORAY=1 -source libs/get_source_env.sh -pushd .. - -#### - -if [ ! -d "sing-box" ]; then - git clone --no-checkout https://github.com/MatsuriDayo/sing-box.git -fi -pushd sing-box -git checkout "$COMMIT_SING_BOX" - -popd - -#### - -if [ ! -d "sing-quic" ]; then - git clone --no-checkout https://github.com/MatsuriDayo/sing-quic.git -fi -pushd sing-quic -git checkout "$COMMIT_SING_QUIC" - -popd - -#### - -if [ ! -d "libneko" ]; then - git clone --no-checkout https://github.com/MatsuriDayo/libneko.git -fi -pushd libneko -git checkout "$COMMIT_LIBNEKO" - -popd - -#### - -popd diff --git a/libs/get_source_env.sh b/libs/get_source_env.sh deleted file mode 100644 index 1f35b7a..0000000 --- a/libs/get_source_env.sh +++ /dev/null @@ -1,3 +0,0 @@ -export COMMIT_SING_BOX="06557f6cef23160668122a17a818b378b5a216b5" -export COMMIT_SING_QUIC="b49ce60d9b3622d5238fee96bfd3c5f6e3915b42" -export COMMIT_LIBNEKO="1c47a3af71990a7b2192e03292b4d246c308ef0b" diff --git a/libs/package_appimage.sh b/libs/package_appimage.sh deleted file mode 100644 index c6c3882..0000000 --- a/libs/package_appimage.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash - -sudo apt-get install fuse -y - -cp -r linux64 nekobox.AppDir - -# The file for Appimage - -rm nekobox.AppDir/launcher - -cat >nekobox.AppDir/nekobox.desktop <<-EOF -[Desktop Entry] -Name=nekobox -Exec=echo "nekobox started" -Icon=nekobox -Type=Application -Categories=Network -EOF - -cat >nekobox.AppDir/AppRun <<-EOF -#!/bin/bash -echo "PATH: \${PATH}" -echo "nekobox runing on: \$APPDIR" -LD_LIBRARY_PATH=\${APPDIR}/usr/lib QT_PLUGIN_PATH=\${APPDIR}/usr/plugins \${APPDIR}/nekobox -appdata "\$@" -EOF - -chmod +x nekobox.AppDir/AppRun - -# build - -curl -fLSO https://github.com/AppImage/AppImageKit/releases/latest/download/appimagetool-x86_64.AppImage -chmod +x appimagetool-x86_64.AppImage -./appimagetool-x86_64.AppImage nekobox.AppDir - -# clean - -rm appimagetool-x86_64.AppImage -rm -rf nekobox.AppDir diff --git a/libs/package_debian.sh b/libs/package_debian.sh deleted file mode 100644 index 491aa7d..0000000 --- a/libs/package_debian.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/bash - -version="$1" - -mkdir -p nekoray/DEBIAN -mkdir -p nekoray/opt -cp -r linux64 nekoray/opt/ -mv nekoray/opt/linux64 nekoray/opt/nekoray -rm -rf nekoray/opt/nekoray/usr -rm nekoray/opt/nekoray/launcher - -# basic -cat >nekoray/DEBIAN/control <<-EOF -Package: nekoray -Version: $version -Architecture: amd64 -Maintainer: MatsuriDayo nekoha_matsuri@protonmail.com -Depends: libxcb-xinerama0, libqt5core5a, libqt5gui5, libqt5network5, libqt5widgets5, libqt5svg5, libqt5x11extras5, desktop-file-utils -Description: Qt based cross-platform GUI proxy configuration manager (backend: v2ray / sing-box) -EOF - -cat >nekoray/DEBIAN/postinst <<-EOF -if [ ! -s /usr/share/applications/nekoray.desktop ]; then - cat >/usr/share/applications/nekoray.desktop<<-END -[Desktop Entry] -Name=nekoray -Comment=Qt based cross-platform GUI proxy configuration manager (backend: sing-box) -Exec=sh -c "PATH=/opt/nekoray:\$PATH /opt/nekoray/nekobox -appdata" -Icon=/opt/nekoray/nekobox.png -Terminal=false -Type=Application -Categories=Network;Application; -END -fi - -setcap cap_net_admin=ep /opt/nekoray/nekobox_core - -update-desktop-database -EOF - -sudo chmod 0755 nekoray/DEBIAN/postinst - -# desktop && PATH - -sudo dpkg-deb -Zxz --build nekoray diff --git a/main/Const.hpp b/main/Const.hpp deleted file mode 100644 index 38d328c..0000000 --- a/main/Const.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -namespace NekoGui { - namespace DomainMatcher { - enum DomainMatcher { - DEFAULT, - MPH, - }; - } - - namespace SniffingMode { - enum SniffingMode { - DISABLE, - FOR_ROUTING, - FOR_DESTINATION, - }; - } - - namespace CoreType { - enum CoreType { - V2RAY, // DO NOT USE - SING_BOX, - }; - } -} // namespace NekoGui diff --git a/main/GuiUtils.hpp b/main/GuiUtils.hpp deleted file mode 100644 index 792d171..0000000 --- a/main/GuiUtils.hpp +++ /dev/null @@ -1,93 +0,0 @@ -#pragma once - -// Dialogs - -#define Dialog_DialogBasicSettings "DialogBasicSettings" -#define Dialog_DialogEditProfile "DialogEditProfile" -#define Dialog_DialogManageGroups "DialogManageGroups" -#define Dialog_DialogManageRoutes "DialogManageRoutes" - -// Utils - -#define QRegExpValidator_Number new QRegularExpressionValidator(QRegularExpression("^[0-9]+$"), this) - -// NekoRay Save&Load - -#define P_C_LOAD_STRING(a) CACHE.a = bean->a; -#define P_C_SAVE_STRING(a) bean->a = CACHE.a; -#define D_C_LOAD_STRING(a) CACHE.a = NekoGui::dataStore->a; -#define D_C_SAVE_STRING(a) NekoGui::dataStore->a = CACHE.a; - -#define P_LOAD_STRING(a) ui->a->setText(bean->a); -#define P_LOAD_STRING_PLAIN(a) ui->a->setPlainText(bean->a); -#define P_SAVE_STRING(a) bean->a = ui->a->text(); -#define P_SAVE_STRING_PLAIN(a) bean->a = ui->a->toPlainText(); - -#define D_LOAD_STRING(a) ui->a->setText(NekoGui::dataStore->a); -#define D_LOAD_STRING_PLAIN(a) ui->a->setPlainText(NekoGui::dataStore->a); -#define D_SAVE_STRING(a) NekoGui::dataStore->a = ui->a->text(); -#define D_SAVE_STRING_PLAIN(a) NekoGui::dataStore->a = ui->a->toPlainText(); - -#define P_LOAD_INT(a) \ - ui->a->setText(Int2String(bean->a)); \ - ui->a->setValidator(QRegExpValidator_Number); -#define P_SAVE_INT(a) bean->a = ui->a->text().toInt(); - -#define D_LOAD_INT(a) \ - ui->a->setText(Int2String(NekoGui::dataStore->a)); \ - ui->a->setValidator(QRegExpValidator_Number); -#define D_SAVE_INT(a) NekoGui::dataStore->a = ui->a->text().toInt(); - -#define P_LOAD_COMBO_STRING(a) ui->a->setCurrentText(bean->a); -#define P_SAVE_COMBO_STRING(a) bean->a = ui->a->currentText(); - -#define D_LOAD_COMBO_STRING(a) ui->a->setCurrentText(NekoGui::dataStore->a); -#define D_SAVE_COMBO_STRING(a) NekoGui::dataStore->a = ui->a->currentText(); - -#define P_LOAD_COMBO_INT(a) ui->a->setCurrentIndex(bean->a); -#define P_SAVE_COMBO_INT(a) bean->a = ui->a->currentIndex(); - -#define D_LOAD_BOOL(a) ui->a->setChecked(NekoGui::dataStore->a); -#define D_SAVE_BOOL(a) NekoGui::dataStore->a = ui->a->isChecked(); - -#define P_LOAD_BOOL(a) ui->a->setChecked(bean->a); -#define P_SAVE_BOOL(a) bean->a = ui->a->isChecked(); - -#define D_LOAD_INT_ENABLE(i, e) \ - if (NekoGui::dataStore->i > 0) { \ - ui->e->setChecked(true); \ - ui->i->setText(Int2String(NekoGui::dataStore->i)); \ - } else { \ - ui->e->setChecked(false); \ - ui->i->setText(Int2String(-NekoGui::dataStore->i)); \ - } \ - ui->i->setValidator(QRegExpValidator_Number); -#define D_SAVE_INT_ENABLE(i, e) \ - if (ui->e->isChecked()) { \ - NekoGui::dataStore->i = ui->i->text().toInt(); \ - } else { \ - NekoGui::dataStore->i = -ui->i->text().toInt(); \ - } - -#define C_EDIT_JSON_ALLOW_EMPTY(a) \ - auto editor = new JsonEditor(QString2QJsonObject(CACHE.a), this); \ - auto result = editor->OpenEditor(); \ - CACHE.a = QJsonObject2QString(result, true); \ - if (result.isEmpty()) CACHE.a = ""; \ - editor->deleteLater(); - -// - -#define ADD_ASTERISK(parent) \ - for (auto label: parent->findChildren()) { \ - auto text = label->text(); \ - if (!label->toolTip().isEmpty() && !text.endsWith("*")) { \ - label->setText(text + "*"); \ - } \ - } \ - for (auto checkBox: parent->findChildren()) { \ - auto text = checkBox->text(); \ - if (!checkBox->toolTip().isEmpty() && !text.endsWith("*")) { \ - checkBox->setText(text + "*"); \ - } \ - } diff --git a/main/HTTPRequestHelper.cpp b/main/HTTPRequestHelper.cpp deleted file mode 100644 index 62c8cd2..0000000 --- a/main/HTTPRequestHelper.cpp +++ /dev/null @@ -1,85 +0,0 @@ -#include "HTTPRequestHelper.hpp" - -#include -#include -#include -#include -#include - -#include "main/NekoGui.hpp" - -namespace NekoGui_network { - - NekoHTTPResponse NetworkRequestHelper::HttpGet(const QUrl &url) { - QNetworkRequest request; - QNetworkAccessManager accessManager; - request.setUrl(url); - // Set proxy - if (NekoGui::dataStore->sub_use_proxy) { - QNetworkProxy p; - // Note: sing-box mixed socks5 protocol error - p.setType(QNetworkProxy::HttpProxy); - p.setHostName("127.0.0.1"); - p.setPort(NekoGui::dataStore->inbound_socks_port); - if (NekoGui::dataStore->inbound_auth->NeedAuth()) { - p.setUser(NekoGui::dataStore->inbound_auth->username); - p.setPassword(NekoGui::dataStore->inbound_auth->password); - } - accessManager.setProxy(p); - if (NekoGui::dataStore->started_id < 0) { - return NekoHTTPResponse{QObject::tr("Request with proxy but no profile started.")}; - } - } - if (accessManager.proxy().type() == QNetworkProxy::Socks5Proxy) { - auto cap = accessManager.proxy().capabilities(); - accessManager.proxy().setCapabilities(cap | QNetworkProxy::HostNameLookupCapability); - } - // Set attribute -#if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)) - request.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy); -#endif - request.setHeader(QNetworkRequest::KnownHeaders::UserAgentHeader, NekoGui::dataStore->GetUserAgent()); - if (NekoGui::dataStore->sub_insecure) { - QSslConfiguration c; - c.setPeerVerifyMode(QSslSocket::PeerVerifyMode::VerifyNone); - request.setSslConfiguration(c); - } - // - auto _reply = accessManager.get(request); - connect(_reply, &QNetworkReply::sslErrors, _reply, [](const QList &errors) { - QStringList error_str; - for (const auto &err: errors) { - error_str << err.errorString(); - } - MW_show_log(QStringLiteral("SSL Errors: %1 %2").arg(error_str.join(","), NekoGui::dataStore->sub_insecure ? "(Ignored)" : "")); - }); - // Wait for response - auto abortTimer = new QTimer; - abortTimer->setSingleShot(true); - abortTimer->setInterval(10000); - QObject::connect(abortTimer, &QTimer::timeout, _reply, &QNetworkReply::abort); - abortTimer->start(); - { - QEventLoop loop; - QObject::connect(_reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); - loop.exec(); - } - if (abortTimer != nullptr) { - abortTimer->stop(); - abortTimer->deleteLater(); - } - // - auto result = NekoHTTPResponse{_reply->error() == QNetworkReply::NetworkError::NoError ? "" : _reply->errorString(), - _reply->readAll(), _reply->rawHeaderPairs()}; - _reply->deleteLater(); - return result; - } - - QString NetworkRequestHelper::GetHeader(const QList> &header, const QString &name) { - for (const auto &p: header) { - if (QString(p.first).toLower() == name.toLower()) return p.second; - } - return ""; - } - -} // namespace NekoGui_network diff --git a/main/HTTPRequestHelper.hpp b/main/HTTPRequestHelper.hpp deleted file mode 100644 index 76760f0..0000000 --- a/main/HTTPRequestHelper.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -namespace NekoGui_network { - struct NekoHTTPResponse { - QString error; - QByteArray data; - QList> header; - }; - - class NetworkRequestHelper : QObject { - Q_OBJECT - - explicit NetworkRequestHelper(QObject *parent) : QObject(parent){}; - - ~NetworkRequestHelper() override = default; - ; - - public: - static NekoHTTPResponse HttpGet(const QUrl &url); - - static QString GetHeader(const QList> &header, const QString &name); - }; -} // namespace NekoGui_network - -using namespace NekoGui_network; diff --git a/main/NekoGui.cpp b/main/NekoGui.cpp deleted file mode 100644 index e84c337..0000000 --- a/main/NekoGui.cpp +++ /dev/null @@ -1,462 +0,0 @@ -#include "NekoGui.hpp" -#include "fmt/Preset.hpp" - -#include -#include -#include -#include -#include -#include -#include - -#ifdef Q_OS_WIN -#include "sys/windows/guihelper.h" -#else -#ifdef Q_OS_LINUX -#include -#endif -#include -#endif - -namespace NekoGui_ConfigItem { - - // 添加关联 - void JsonStore::_add(configItem *item) { - _map.insert(item->name, std::shared_ptr(item)); - } - - QString JsonStore::_name(void *p) { - for (const auto &_item: _map) { - if (_item->ptr == p) return _item->name; - } - return {}; - } - - std::shared_ptr JsonStore::_get(const QString &name) { - // 直接 [] 会设置一个 nullptr ,所以先判断是否存在 - if (_map.contains(name)) { - return _map[name]; - } - return nullptr; - } - - void JsonStore::_setValue(const QString &name, void *p) { - auto item = _get(name); - if (item == nullptr) return; - - switch (item->type) { - case itemType::string: - *(QString *) item->ptr = *(QString *) p; - break; - case itemType::boolean: - *(bool *) item->ptr = *(bool *) p; - break; - case itemType::integer: - *(int *) item->ptr = *(int *) p; - break; - case itemType::integer64: - *(long long *) item->ptr = *(long long *) p; - break; - // others... - case stringList: - case integerList: - case jsonStore: - break; - } - } - - QJsonObject JsonStore::ToJson(const QStringList &without) { - QJsonObject object; - for (const auto &_item: _map) { - auto item = _item.get(); - if (without.contains(item->name)) continue; - switch (item->type) { - case itemType::string: - // Allow Empty - if (!((QString *) item->ptr)->isEmpty()) { - object.insert(item->name, *(QString *) item->ptr); - } - break; - case itemType::integer: - object.insert(item->name, *(int *) item->ptr); - break; - case itemType::integer64: - object.insert(item->name, *(long long *) item->ptr); - break; - case itemType::boolean: - object.insert(item->name, *(bool *) item->ptr); - break; - case itemType::stringList: - object.insert(item->name, QList2QJsonArray(*(QList *) item->ptr)); - break; - case itemType::integerList: - object.insert(item->name, QList2QJsonArray(*(QList *) item->ptr)); - break; - case itemType::jsonStore: - // _add 时应关联对应 JsonStore 的指针 - object.insert(item->name, ((JsonStore *) item->ptr)->ToJson()); - break; - } - } - return object; - } - - QByteArray JsonStore::ToJsonBytes() { - QJsonDocument document; - document.setObject(ToJson()); - return document.toJson(save_control_compact ? QJsonDocument::Compact : QJsonDocument::Indented); - } - - void JsonStore::FromJson(QJsonObject object) { - for (const auto &key: object.keys()) { - if (_map.count(key) == 0) { - continue; - } - - auto value = object[key]; - auto item = _map[key].get(); - - if (item == nullptr) - continue; // 故意忽略 - - // 根据类型修改ptr的内容 - switch (item->type) { - case itemType::string: - if (value.type() != QJsonValue::String) { - continue; - } - *(QString *) item->ptr = value.toString(); - break; - case itemType::integer: - if (value.type() != QJsonValue::Double) { - continue; - } - *(int *) item->ptr = value.toInt(); - break; - case itemType::integer64: - if (value.type() != QJsonValue::Double) { - continue; - } - *(long long *) item->ptr = value.toDouble(); - break; - case itemType::boolean: - if (value.type() != QJsonValue::Bool) { - continue; - } - *(bool *) item->ptr = value.toBool(); - break; - case itemType::stringList: - if (value.type() != QJsonValue::Array) { - continue; - } - *(QList *) item->ptr = QJsonArray2QListString(value.toArray()); - break; - case itemType::integerList: - if (value.type() != QJsonValue::Array) { - continue; - } - *(QList *) item->ptr = QJsonArray2QListInt(value.toArray()); - break; - case itemType::jsonStore: - if (value.type() != QJsonValue::Object) { - continue; - } - ((JsonStore *) item->ptr)->FromJson(value.toObject()); - break; - } - } - - if (callback_after_load != nullptr) callback_after_load(); - } - - void JsonStore::FromJsonBytes(const QByteArray &data) { - QJsonParseError error{}; - auto document = QJsonDocument::fromJson(data, &error); - - if (error.error != error.NoError) { - qDebug() << "QJsonParseError" << error.errorString(); - return; - } - - FromJson(document.object()); - } - - bool JsonStore::Save() { - if (callback_before_save != nullptr) callback_before_save(); - if (save_control_no_save) return false; - - auto save_content = ToJsonBytes(); - auto changed = last_save_content != save_content; - last_save_content = save_content; - - QFile file; - file.setFileName(fn); - file.open(QIODevice::ReadWrite | QIODevice::Truncate); - file.write(save_content); - file.close(); - - return changed; - } - - bool JsonStore::Load() { - QFile file; - file.setFileName(fn); - - if (!file.exists() && !load_control_must) { - return false; - } - - bool ok = file.open(QIODevice::ReadOnly); - if (!ok) { - MessageBoxWarning("error", "can not open config " + fn + "\n" + file.errorString()); - } else { - last_save_content = file.readAll(); - FromJsonBytes(last_save_content); - } - - file.close(); - return ok; - } - -} // namespace NekoGui_ConfigItem - -namespace NekoGui { - - DataStore *dataStore = new DataStore(); - - // datastore - - DataStore::DataStore() : JsonStore() { - _add(new configItem("extraCore", dynamic_cast(extraCore), itemType::jsonStore)); - _add(new configItem("inbound_auth", dynamic_cast(inbound_auth), itemType::jsonStore)); - - _add(new configItem("user_agent2", &user_agent, itemType::string)); - _add(new configItem("test_url", &test_latency_url, itemType::string)); - _add(new configItem("test_url_dl", &test_download_url, itemType::string)); - _add(new configItem("test_dl_timeout", &test_download_timeout, itemType::integer)); - _add(new configItem("current_group", ¤t_group, itemType::integer)); - _add(new configItem("inbound_address", &inbound_address, itemType::string)); - _add(new configItem("inbound_socks_port", &inbound_socks_port, itemType::integer)); - _add(new configItem("log_level", &log_level, itemType::string)); - _add(new configItem("mux_protocol", &mux_protocol, itemType::string)); - _add(new configItem("mux_concurrency", &mux_concurrency, itemType::integer)); - _add(new configItem("mux_padding", &mux_padding, itemType::boolean)); - _add(new configItem("mux_default_on", &mux_default_on, itemType::boolean)); - _add(new configItem("traffic_loop_interval", &traffic_loop_interval, itemType::integer)); - _add(new configItem("test_concurrent", &test_concurrent, itemType::integer)); - _add(new configItem("theme", &theme, itemType::string)); - _add(new configItem("custom_inbound", &custom_inbound, itemType::string)); - _add(new configItem("custom_route", &custom_route_global, itemType::string)); - _add(new configItem("sub_use_proxy", &sub_use_proxy, itemType::boolean)); - _add(new configItem("remember_id", &remember_id, itemType::integer)); - _add(new configItem("remember_enable", &remember_enable, itemType::boolean)); - _add(new configItem("language", &language, itemType::integer)); - _add(new configItem("spmode2", &remember_spmode, itemType::stringList)); - _add(new configItem("skip_cert", &skip_cert, itemType::boolean)); - _add(new configItem("hk_mw", &hotkey_mainwindow, itemType::string)); - _add(new configItem("hk_group", &hotkey_group, itemType::string)); - _add(new configItem("hk_route", &hotkey_route, itemType::string)); - _add(new configItem("hk_spmenu", &hotkey_system_proxy_menu, itemType::string)); - _add(new configItem("fakedns", &fake_dns, itemType::boolean)); - _add(new configItem("active_routing", &active_routing, itemType::string)); - _add(new configItem("mw_size", &mw_size, itemType::string)); - _add(new configItem("conn_stat", &connection_statistics, itemType::boolean)); - _add(new configItem("vpn_impl", &vpn_implementation, itemType::integer)); - _add(new configItem("vpn_mtu", &vpn_mtu, itemType::integer)); - _add(new configItem("vpn_ipv6", &vpn_ipv6, itemType::boolean)); - _add(new configItem("vpn_hide_console", &vpn_hide_console, itemType::boolean)); - _add(new configItem("vpn_strict_route", &vpn_strict_route, itemType::boolean)); - _add(new configItem("vpn_bypass_process", &vpn_rule_process, itemType::string)); - _add(new configItem("vpn_bypass_cidr", &vpn_rule_cidr, itemType::string)); - _add(new configItem("vpn_rule_white", &vpn_rule_white, itemType::boolean)); - _add(new configItem("check_include_pre", &check_include_pre, itemType::boolean)); - _add(new configItem("sp_format", &system_proxy_format, itemType::string)); - _add(new configItem("sub_clear", &sub_clear, itemType::boolean)); - _add(new configItem("sub_insecure", &sub_insecure, itemType::boolean)); - _add(new configItem("sub_auto_update", &sub_auto_update, itemType::integer)); - _add(new configItem("log_ignore", &log_ignore, itemType::stringList)); - _add(new configItem("start_minimal", &start_minimal, itemType::boolean)); - _add(new configItem("max_log_line", &max_log_line, itemType::integer)); - _add(new configItem("splitter_state", &splitter_state, itemType::string)); - _add(new configItem("utlsFingerprint", &utlsFingerprint, itemType::string)); - _add(new configItem("core_box_clash_api", &core_box_clash_api, itemType::integer)); - _add(new configItem("core_box_clash_api_secret", &core_box_clash_api_secret, itemType::string)); - _add(new configItem("core_box_underlying_dns", &core_box_underlying_dns, itemType::string)); - _add(new configItem("vpn_internal_tun", &vpn_internal_tun, itemType::boolean)); - } - - void DataStore::UpdateStartedId(int id) { - started_id = id; - if (remember_enable) { - remember_id = id; - Save(); - } else if (remember_id >= 0) { - remember_id = -1919; - Save(); - } - } - - QString DataStore::GetUserAgent(bool isDefault) const { - if (user_agent.isEmpty()) { - isDefault = true; - } - if (isDefault) { - QString version = SubStrBefore(NKR_VERSION, "-"); - if (!version.contains(".")) version = "2.0"; - return "NekoBox/PC/" + version + " (Prefer ClashMeta Format)"; - } - return user_agent; - } - - // preset routing - Routing::Routing(int preset) : JsonStore() { - if (preset == 1) { - direct_ip = - "geoip:cn\n" - "geoip:private"; - direct_domain = "geosite:cn"; - proxy_ip = ""; - proxy_domain = ""; - block_ip = ""; - block_domain = - "geosite:category-ads-all\n" - "domain:appcenter.ms\n" - "domain:firebase.io\n" - "domain:crashlytics.com\n"; - } - if (!Preset::SingBox::DomainStrategy.contains(domain_strategy)) domain_strategy = ""; - if (!Preset::SingBox::DomainStrategy.contains(outbound_domain_strategy)) outbound_domain_strategy = ""; - _add(new configItem("direct_ip", &this->direct_ip, itemType::string)); - _add(new configItem("direct_domain", &this->direct_domain, itemType::string)); - _add(new configItem("proxy_ip", &this->proxy_ip, itemType::string)); - _add(new configItem("proxy_domain", &this->proxy_domain, itemType::string)); - _add(new configItem("block_ip", &this->block_ip, itemType::string)); - _add(new configItem("block_domain", &this->block_domain, itemType::string)); - _add(new configItem("def_outbound", &this->def_outbound, itemType::string)); - _add(new configItem("custom", &this->custom, itemType::string)); - // - _add(new configItem("remote_dns", &this->remote_dns, itemType::string)); - _add(new configItem("remote_dns_strategy", &this->remote_dns_strategy, itemType::string)); - _add(new configItem("direct_dns", &this->direct_dns, itemType::string)); - _add(new configItem("direct_dns_strategy", &this->direct_dns_strategy, itemType::string)); - _add(new configItem("domain_strategy", &this->domain_strategy, itemType::string)); - _add(new configItem("outbound_domain_strategy", &this->outbound_domain_strategy, itemType::string)); - _add(new configItem("dns_routing", &this->dns_routing, itemType::boolean)); - _add(new configItem("sniffing_mode", &this->sniffing_mode, itemType::integer)); - _add(new configItem("use_dns_object", &this->use_dns_object, itemType::boolean)); - _add(new configItem("dns_object", &this->dns_object, itemType::string)); - _add(new configItem("dns_final_out", &this->dns_final_out, itemType::string)); - } - - QString Routing::DisplayRouting() const { - return QStringLiteral("[Proxy] %1\n[Proxy] %2\n[Direct] %3\n[Direct] %4\n[Block] %5\n[Block] %6\n[Default Outbound] %7\n[DNS] %8") - .arg(SplitLinesSkipSharp(proxy_domain).join(","), 10) - .arg(SplitLinesSkipSharp(proxy_ip).join(","), 10) - .arg(SplitLinesSkipSharp(direct_domain).join(","), 10) - .arg(SplitLinesSkipSharp(direct_ip).join(","), 10) - .arg(SplitLinesSkipSharp(block_domain).join(","), 10) - .arg(SplitLinesSkipSharp(block_ip).join(","), 10) - .arg(def_outbound) - .arg(use_dns_object ? "DNS Object" : "Simple DNS"); - } - - QStringList Routing::List() { - QDir dr(ROUTES_PREFIX); - return dr.entryList(QDir::Files); - } - - bool Routing::SetToActive(const QString &name) { - NekoGui::dataStore->routing = std::make_unique(); - NekoGui::dataStore->routing->load_control_must = true; - NekoGui::dataStore->routing->fn = ROUTES_PREFIX + name; - auto ok = NekoGui::dataStore->routing->Load(); - if (ok) { - NekoGui::dataStore->active_routing = name; - NekoGui::dataStore->Save(); - } - return ok; - } - - // NO default extra core - - ExtraCore::ExtraCore() : JsonStore() { - _add(new configItem("core_map", &this->core_map, itemType::string)); - } - - QString ExtraCore::Get(const QString &id) const { - auto obj = QString2QJsonObject(core_map); - for (const auto &c: obj.keys()) { - if (c == id) return obj[id].toString(); - } - return ""; - } - - void ExtraCore::Set(const QString &id, const QString &path) { - auto obj = QString2QJsonObject(core_map); - obj[id] = path; - core_map = QJsonObject2QString(obj, true); - } - - void ExtraCore::Delete(const QString &id) { - auto obj = QString2QJsonObject(core_map); - obj.remove(id); - core_map = QJsonObject2QString(obj, true); - } - - InboundAuthorization::InboundAuthorization() : JsonStore() { - _add(new configItem("user", &this->username, itemType::string)); - _add(new configItem("pass", &this->password, itemType::string)); - } - - bool InboundAuthorization::NeedAuth() const { - return !username.trimmed().isEmpty() && !password.trimmed().isEmpty(); - } - - // System Utils - - QString FindCoreAsset(const QString &name) { - QStringList search{}; - search << QApplication::applicationDirPath(); - search << "/usr/share/sing-geoip"; - search << "/usr/share/sing-geosite"; - search << "/usr/share/sing-box"; - search << "/usr/lib/nekobox"; - search << "/usr/share/nekobox"; - for (const auto &dir: search) { - if (dir.isEmpty()) continue; - QFileInfo asset(dir + "/" + name); - if (asset.exists()) { - return asset.absoluteFilePath(); - } - } - return {}; - } - - QString FindNekoBoxCoreRealPath() { - auto fn = QApplication::applicationDirPath() + "/nekobox_core"; - auto fi = QFileInfo(fn); - if (fi.isSymLink()) return fi.symLinkTarget(); - return fn; - } - - short isAdminCache = -1; - - // IsAdmin 主要判断:有无权限启动 Tun - bool IsAdmin() { - if (isAdminCache >= 0) return isAdminCache; - - bool admin = false; -#ifdef Q_OS_WIN - admin = Windows_IsInAdmin(); -#else -#ifdef Q_OS_LINUX - admin |= Linux_GetCapString(FindNekoBoxCoreRealPath()).contains("cap_net_admin"); -#endif - admin |= geteuid() == 0; -#endif - - isAdminCache = admin; - return admin; - }; - -} // namespace NekoGui diff --git a/main/NekoGui.hpp b/main/NekoGui.hpp deleted file mode 100644 index a54a32e..0000000 --- a/main/NekoGui.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include "Const.hpp" -#include "NekoGui_Utils.hpp" -#include "NekoGui_ConfigItem.hpp" -#include "NekoGui_DataStore.hpp" - -// Switch core support - -namespace NekoGui { - inline int coreType = CoreType::SING_BOX; - - QString FindCoreAsset(const QString &name); - - QString FindNekoBoxCoreRealPath(); - - bool IsAdmin(); -} // namespace NekoGui - -#define ROUTES_PREFIX_NAME QStringLiteral("routes_box") -#define ROUTES_PREFIX QString(ROUTES_PREFIX_NAME + "/") diff --git a/main/NekoGui_ConfigItem.hpp b/main/NekoGui_ConfigItem.hpp deleted file mode 100644 index 152ac3e..0000000 --- a/main/NekoGui_ConfigItem.hpp +++ /dev/null @@ -1,70 +0,0 @@ -// DO NOT INCLUDE THIS - -namespace NekoGui_ConfigItem { - // config 工具 - enum itemType { - string, - integer, - integer64, - boolean, - stringList, - integerList, - jsonStore, - }; - - class configItem { - public: - QString name; - void *ptr; - itemType type; - - configItem(QString n, void *p, itemType t) { - name = std::move(n); - ptr = p; - type = t; - } - }; - - // 可格式化对象 - class JsonStore { - public: - QMap> _map; - - std::function callback_after_load = nullptr; - std::function callback_before_save = nullptr; - - QString fn; - bool load_control_must = false; // must load from file - bool save_control_compact = false; - bool save_control_no_save = false; - QByteArray last_save_content; - - JsonStore() = default; - - explicit JsonStore(QString fileName) { - fn = std::move(fileName); - } - - void _add(configItem *item); - - QString _name(void *p); - - std::shared_ptr _get(const QString &name); - - void _setValue(const QString &name, void *p); - - QJsonObject ToJson(const QStringList &without = {}); - - QByteArray ToJsonBytes(); - - void FromJson(QJsonObject object); - - void FromJsonBytes(const QByteArray &data); - - bool Save(); - - bool Load(); - }; -} // namespace NekoGui_ConfigItem - -using namespace NekoGui_ConfigItem; diff --git a/main/NekoGui_DataStore.hpp b/main/NekoGui_DataStore.hpp deleted file mode 100644 index ec0ff24..0000000 --- a/main/NekoGui_DataStore.hpp +++ /dev/null @@ -1,182 +0,0 @@ -// DO NOT INCLUDE THIS - -namespace NekoGui { - - class Routing : public JsonStore { - public: - QString direct_ip; - QString direct_domain; - QString proxy_ip; - QString proxy_domain; - QString block_ip; - QString block_domain; - QString def_outbound = "proxy"; - QString custom = "{\"rules\": []}"; - - // DNS - QString remote_dns = "https://dns.google/dns-query"; - QString remote_dns_strategy = ""; - QString direct_dns = "https://doh.pub/dns-query"; - QString direct_dns_strategy = ""; - bool dns_routing = true; - bool use_dns_object = false; - QString dns_object = ""; - QString dns_final_out = "proxy"; - - // Misc - QString domain_strategy = "AsIs"; - QString outbound_domain_strategy = "AsIs"; - int sniffing_mode = SniffingMode::FOR_ROUTING; - - explicit Routing(int preset = 0); - - [[nodiscard]] QString DisplayRouting() const; - - static QStringList List(); - - static bool SetToActive(const QString &name); - }; - - class ExtraCore : public JsonStore { - public: - QString core_map; - - explicit ExtraCore(); - - [[nodiscard]] QString Get(const QString &id) const; - - void Set(const QString &id, const QString &path); - - void Delete(const QString &id); - }; - - class InboundAuthorization : public JsonStore { - public: - QString username; - QString password; - - InboundAuthorization(); - - [[nodiscard]] bool NeedAuth() const; - }; - - class DataStore : public JsonStore { - public: - // Running - - QString core_token; - int core_port = 19810; - int started_id = -1919; - bool core_running = false; - bool prepare_exit = false; - bool spmode_vpn = false; - bool spmode_system_proxy = false; - bool need_keep_vpn_off = false; - QString appdataDir = ""; - QStringList ignoreConnTag = {}; - - std::unique_ptr routing; - int imported_count = 0; - bool refreshing_group_list = false; - bool refreshing_group = false; - int resolve_count = 0; - - // Flags - QStringList argv = {}; - bool flag_use_appdata = false; - bool flag_many = false; - bool flag_tray = false; - bool flag_debug = false; - bool flag_restart_tun_on = false; - bool flag_reorder = false; - - // Saved - - // Misc - QString log_level = "info"; - QString test_latency_url = "http://cp.cloudflare.com/"; - QString test_download_url = "http://cachefly.cachefly.net/10mb.test"; - int test_download_timeout = 30; - int test_concurrent = 5; - bool old_share_link_format = true; - int traffic_loop_interval = 1000; - bool connection_statistics = false; - int current_group = 0; // group id - QString mux_protocol = "h2mux"; - bool mux_padding = false; - int mux_concurrency = 8; - bool mux_default_on = false; - QString theme = "0"; - int language = 0; - QString mw_size = ""; - bool check_include_pre = false; - QString system_proxy_format = ""; - QStringList log_ignore = {}; - bool start_minimal = false; - int max_log_line = 200; - QString splitter_state = ""; - - // Subscription - QString user_agent = ""; // set at main.cpp - bool sub_use_proxy = false; - bool sub_clear = false; - bool sub_insecure = false; - int sub_auto_update = -30; - - // Security - bool skip_cert = false; - QString utlsFingerprint = ""; - - // Remember - QStringList remember_spmode = {}; - int remember_id = -1919; - bool remember_enable = false; - - // Socks & HTTP Inbound - QString inbound_address = "127.0.0.1"; - int inbound_socks_port = 2080; // or Mixed - InboundAuthorization *inbound_auth = new InboundAuthorization; - QString custom_inbound = "{\"inbounds\": []}"; - - // Routing - QString custom_route_global = "{\"rules\": []}"; - QString active_routing = "Default"; - - // VPN - bool fake_dns = false; - bool vpn_internal_tun = true; - int vpn_implementation = 0; - int vpn_mtu = 9000; - bool vpn_ipv6 = false; - bool vpn_hide_console = true; - bool vpn_strict_route = false; - bool vpn_rule_white = false; - QString vpn_rule_process = ""; - QString vpn_rule_cidr = ""; - - // Hotkey - QString hotkey_mainwindow = ""; - QString hotkey_group = ""; - QString hotkey_route = ""; - QString hotkey_system_proxy_menu = ""; - - // Core - int core_box_clash_api = -9090; - QString core_box_clash_api_secret = ""; - QString core_box_underlying_dns = ""; - - // Other Core - ExtraCore *extraCore = new ExtraCore; - - // Methods - - DataStore(); - - void UpdateStartedId(int id); - - QString GetUserAgent(bool isDefault = false) const; - }; - - extern DataStore *dataStore; - -} // namespace NekoGui diff --git a/main/NekoGui_Utils.cpp b/main/NekoGui_Utils.cpp deleted file mode 100644 index 92a0672..0000000 --- a/main/NekoGui_Utils.cpp +++ /dev/null @@ -1,261 +0,0 @@ -#include "NekoGui_Utils.hpp" - -#include "3rdparty/base64.h" -#include "3rdparty/QThreadCreateThread.hpp" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef Q_OS_WIN -#include "sys/windows/guihelper.h" -#endif - -QStringList SplitLines(const QString &_string) { -#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) - return _string.split(QRegularExpression("[\r\n]"), Qt::SplitBehaviorFlags::SkipEmptyParts); -#else - return _string.split(QRegularExpression("[\r\n]"), QString::SkipEmptyParts); -#endif -} - -QStringList SplitLinesSkipSharp(const QString &_string, int maxLine) { - auto lines = SplitLines(_string); - QStringList newLines; - int i = 0; - for (const auto &line: lines) { - if (line.trimmed().startsWith("#")) continue; - newLines << line; - if (maxLine > 0 && ++i >= maxLine) break; - } - return newLines; -} - -QByteArray DecodeB64IfValid(const QString &input, QByteArray::Base64Options options) { - Qt515Base64::Base64Options newOptions = Qt515Base64::Base64Option::AbortOnBase64DecodingErrors; - if (options.testFlag(QByteArray::Base64UrlEncoding)) newOptions |= Qt515Base64::Base64Option::Base64UrlEncoding; - if (options.testFlag(QByteArray::OmitTrailingEquals)) newOptions |= Qt515Base64::Base64Option::OmitTrailingEquals; - auto result = Qt515Base64::QByteArray_fromBase64Encoding(input.toUtf8(), newOptions); - if (result) { - return result.decoded; - } - return {}; -} - -QString QStringList2Command(const QStringList &list) { - QStringList new_list; - for (auto str: list) { - auto q = "\"" + str.replace("\"", "\\\"") + "\""; - new_list << q; - } - return new_list.join(" "); -} - -QString GetQueryValue(const QUrlQuery &q, const QString &key, const QString &def) { - auto a = q.queryItemValue(key); - if (a.isEmpty()) { - return def; - } - return a; -} - -QString GetRandomString(int randomStringLength) { - std::random_device rd; - std::mt19937 mt(rd()); - - const QString possibleCharacters("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"); - - std::uniform_int_distribution dist(0, possibleCharacters.length() - 1); - - QString randomString; - for (int i = 0; i < randomStringLength; ++i) { - QChar nextChar = possibleCharacters.at(dist(mt)); - randomString.append(nextChar); - } - return randomString; -} - -quint64 GetRandomUint64() { - std::random_device rd; - std::mt19937 mt(rd()); - std::uniform_int_distribution dist; - return dist(mt); -} - -// QString >> QJson -QJsonObject QString2QJsonObject(const QString &jsonString) { - QJsonDocument jsonDocument = QJsonDocument::fromJson(jsonString.toUtf8()); - QJsonObject jsonObject = jsonDocument.object(); - return jsonObject; -} - -// QJson >> QString -QString QJsonObject2QString(const QJsonObject &jsonObject, bool compact) { - return QJsonDocument(jsonObject).toJson(compact ? QJsonDocument::Compact : QJsonDocument::Indented); -} - -template -QJsonArray QList2QJsonArray(const QList &list) { - QVariantList list2; - for (auto &item: list) - list2.append(item); - return QJsonArray::fromVariantList(list2); -} - -template QJsonArray QList2QJsonArray(const QList &list); -template QJsonArray QList2QJsonArray(const QList &list); - -QList QJsonArray2QListInt(const QJsonArray &arr) { - QList list2; - for (auto item: arr) - list2.append(item.toInt()); - return list2; -} - -QList QJsonArray2QListString(const QJsonArray &arr) { - QList list2; - for (auto item: arr) - list2.append(item.toString()); - return list2; -} - -QByteArray ReadFile(const QString &path) { - QFile file(path); - file.open(QFile::ReadOnly); - return file.readAll(); -} - -QString ReadFileText(const QString &path) { - QFile file(path); - file.open(QFile::ReadOnly | QFile::Text); - QTextStream stream(&file); - return stream.readAll(); -} - -int MkPort() { - QTcpServer s; - s.listen(); - auto port = s.serverPort(); - s.close(); - return port; -} - -QString ReadableSize(const qint64 &size) { - double sizeAsDouble = size; - static QStringList measures; - if (measures.isEmpty()) - measures << "B" - << "KiB" - << "MiB" - << "GiB" - << "TiB" - << "PiB" - << "EiB" - << "ZiB" - << "YiB"; - QStringListIterator it(measures); - QString measure(it.next()); - while (sizeAsDouble >= 1024.0 && it.hasNext()) { - measure = it.next(); - sizeAsDouble /= 1024.0; - } - return QString::fromLatin1("%1 %2").arg(sizeAsDouble, 0, 'f', 2).arg(measure); -} - -bool IsIpAddress(const QString &str) { - auto address = QHostAddress(str); - if (address.protocol() == QAbstractSocket::IPv4Protocol || address.protocol() == QAbstractSocket::IPv6Protocol) - return true; - return false; -} - -bool IsIpAddressV4(const QString &str) { - auto address = QHostAddress(str); - if (address.protocol() == QAbstractSocket::IPv4Protocol) - return true; - return false; -} - -bool IsIpAddressV6(const QString &str) { - auto address = QHostAddress(str); - if (address.protocol() == QAbstractSocket::IPv6Protocol) - return true; - return false; -} - -QString DisplayTime(long long time, int formatType) { - QDateTime t; - t.setMSecsSinceEpoch(time * 1000); - return QLocale().toString(t, QLocale::FormatType(formatType)); -} - -QWidget *GetMessageBoxParent() { - auto activeWindow = QApplication::activeWindow(); - if (activeWindow == nullptr && mainwindow != nullptr) { - if (mainwindow->isVisible()) return mainwindow; - return nullptr; - } - return activeWindow; -} - -int MessageBoxWarning(const QString &title, const QString &text) { - return QMessageBox::warning(GetMessageBoxParent(), title, text); -} - -int MessageBoxInfo(const QString &title, const QString &text) { - return QMessageBox::information(GetMessageBoxParent(), title, text); -} - -void ActivateWindow(QWidget *w) { - w->setWindowState(w->windowState() & ~Qt::WindowMinimized); - w->setVisible(true); -#ifdef Q_OS_WIN - Windows_QWidget_SetForegroundWindow(w); -#endif - w->raise(); - w->activateWindow(); -} - -void runOnUiThread(const std::function &callback, QObject *parent) { - // any thread - auto *timer = new QTimer(); - auto thread = dynamic_cast(parent); - if (thread == nullptr) { - timer->moveToThread(parent == nullptr ? mainwindow->thread() : parent->thread()); - } else { - timer->moveToThread(thread); - } - timer->setSingleShot(true); - QObject::connect(timer, &QTimer::timeout, [=]() { - // main thread - callback(); - timer->deleteLater(); - }); - QMetaObject::invokeMethod(timer, "start", Qt::QueuedConnection, Q_ARG(int, 0)); -} - -void runOnNewThread(const std::function &callback) { - createQThread(callback)->start(); -} - -void setTimeout(const std::function &callback, QObject *obj, int timeout) { - auto t = new QTimer; - QObject::connect(t, &QTimer::timeout, obj, [=] { - callback(); - t->deleteLater(); - }); - t->setSingleShot(true); - t->setInterval(timeout); - t->start(); -} diff --git a/main/NekoGui_Utils.hpp b/main/NekoGui_Utils.hpp deleted file mode 100644 index 5c21d34..0000000 --- a/main/NekoGui_Utils.hpp +++ /dev/null @@ -1,176 +0,0 @@ -// DO NOT INCLUDE THIS - -#include -#include -#include -#include -#include - -// - -inline QString software_name = "NekoBox"; -inline QString software_core_name = "sing-box"; - -// Main Functions - -inline std::function MF_release_runguard; - -// MainWindow functions -class QWidget; -inline QWidget *mainwindow; -inline std::function MW_show_log; -inline std::function MW_show_log_ext; -inline std::function MW_show_log_ext_vt100; -inline std::function MW_dialog_message; - -// Dispatchers - -class QThread; -inline QThread *DS_cores; - -// Timers - -class QTimer; -inline QTimer *TM_auto_update_subsctiption; -inline std::function TM_auto_update_subsctiption_Reset_Minute; - -// String - -#define FIRST_OR_SECOND(a, b) a.isEmpty() ? b : a - -inline const QString UNICODE_LRO = QString::fromUtf8(QByteArray::fromHex("E280AD")); - -#define Int2String(num) QString::number(num) - -inline QString SubStrBefore(QString str, const QString &sub) { - if (!str.contains(sub)) return str; - return str.left(str.indexOf(sub)); -} - -inline QString SubStrAfter(QString str, const QString &sub) { - if (!str.contains(sub)) return str; - return str.right(str.length() - str.indexOf(sub) - sub.length()); -} - -QString QStringList2Command(const QStringList &list); - -QStringList SplitLines(const QString &_string); - -QStringList SplitLinesSkipSharp(const QString &_string, int maxLine = 0); - -// Base64 - -QByteArray DecodeB64IfValid(const QString &input, QByteArray::Base64Options options = QByteArray::Base64Option::Base64Encoding); - -// URL - -class QUrlQuery; - -#define GetQuery(url) QUrlQuery((url).query(QUrl::ComponentFormattingOption::FullyDecoded)); - -QString GetQueryValue(const QUrlQuery &q, const QString &key, const QString &def = ""); - -QString GetRandomString(int randomStringLength); - -quint64 GetRandomUint64(); - -// JSON - -class QJsonObject; -class QJsonArray; - -QJsonObject QString2QJsonObject(const QString &jsonString); - -QString QJsonObject2QString(const QJsonObject &jsonObject, bool compact); - -template -QJsonArray QList2QJsonArray(const QList &list); - -QList QJsonArray2QListInt(const QJsonArray &arr); - -#define QJSONARRAY_ADD(arr, add) \ - for (const auto &a: (add)) { \ - (arr) += a; \ - } -#define QJSONOBJECT_COPY(src, dst, key) \ - if (src.contains(key)) dst[key] = src[key]; -#define QJSONOBJECT_COPY2(src, dst, src_key, dst_key) \ - if (src.contains(src_key)) dst[dst_key] = src[src_key]; - -QList QJsonArray2QListString(const QJsonArray &arr); - -// Files - -QByteArray ReadFile(const QString &path); - -QString ReadFileText(const QString &path); - -// Validators - -bool IsIpAddress(const QString &str); - -bool IsIpAddressV4(const QString &str); - -bool IsIpAddressV6(const QString &str); - -// [2001:4860:4860::8888] -> 2001:4860:4860::8888 -inline QString UnwrapIPV6Host(QString &str) { - return str.replace("[", "").replace("]", ""); -} - -// [2001:4860:4860::8888] or 2001:4860:4860::8888 -> [2001:4860:4860::8888] -inline QString WrapIPV6Host(QString &str) { - if (!IsIpAddressV6(str)) return str; - return "[" + UnwrapIPV6Host(str) + "]"; -} - -inline QString DisplayAddress(QString serverAddress, int serverPort) { - if (serverAddress.isEmpty() && serverPort == 0) return {}; - return WrapIPV6Host(serverAddress) + ":" + Int2String(serverPort); -}; - -// Format & Misc - -int MkPort(); - -QString DisplayTime(long long time, int formatType = 0); - -QString ReadableSize(const qint64 &size); - -inline bool InRange(unsigned x, unsigned low, unsigned high) { - return (low <= x && x <= high); -} - -inline bool IsValidPort(int port) { - return InRange(port, 1, 65535); -} - -// UI - -QWidget *GetMessageBoxParent(); - -int MessageBoxWarning(const QString &title, const QString &text); - -int MessageBoxInfo(const QString &title, const QString &text); - -void ActivateWindow(QWidget *w); - -// - -void runOnUiThread(const std::function &callback, QObject *parent = nullptr); - -void runOnNewThread(const std::function &callback); - -template -inline void connectOnce(EMITTER *emitter, SIGNAL signal, RECEIVER *receiver, ReceiverFunc f, - Qt::ConnectionType connectionType = Qt::AutoConnection) { - auto connection = std::make_shared(); - auto onTriggered = [connection, f](auto... arguments) { - std::invoke(f, arguments...); - QObject::disconnect(*connection); - }; - - *connection = QObject::connect(emitter, signal, receiver, onTriggered, connectionType); -} - -void setTimeout(const std::function &callback, QObject *obj, int timeout = 0); diff --git a/main/main.cpp b/main/main.cpp deleted file mode 100644 index b14f04f..0000000 --- a/main/main.cpp +++ /dev/null @@ -1,242 +0,0 @@ -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "3rdparty/RunGuard.hpp" -#include "main/NekoGui.hpp" - -#include "ui/mainwindow_interface.h" - -#ifdef Q_OS_WIN -#include "sys/windows/MiniDump.h" -#endif - -void signal_handler(int signum) { - if (qApp) { - GetMainWindow()->on_commitDataRequest(); - qApp->exit(); - } -} - -QTranslator* trans = nullptr; -QTranslator* trans_qt = nullptr; - -void loadTranslate(const QString& locale) { - if (trans != nullptr) { - trans->deleteLater(); - } - if (trans_qt != nullptr) { - trans_qt->deleteLater(); - } - // - trans = new QTranslator; - trans_qt = new QTranslator; - QLocale::setDefault(QLocale(locale)); - // - if (trans->load(":/translations/" + locale + ".qm")) { - QCoreApplication::installTranslator(trans); - } - if (trans_qt->load(QApplication::applicationDirPath() + "/qtbase_" + locale + ".qm")) { - QCoreApplication::installTranslator(trans_qt); - } -} - -#define LOCAL_SERVER_PREFIX "nekoraylocalserver-" - -int main(int argc, char* argv[]) { - // Core dump -#ifdef Q_OS_WIN - Windows_SetCrashHandler(); -#endif - - // pre-init QApplication -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) && QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) - QApplication::setAttribute(Qt::AA_DisableWindowContextHelpButton); -#endif -#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) - QApplication::setAttribute(Qt::AA_DontUseNativeDialogs); -#endif - QApplication::setQuitOnLastWindowClosed(false); - auto preQApp = new QApplication(argc, argv); - - // Clean - QDir::setCurrent(QApplication::applicationDirPath()); - if (QFile::exists("updater.old")) { - QFile::remove("updater.old"); - } -#ifndef Q_OS_WIN - if (!QFile::exists("updater")) { - QFile::link("launcher", "updater"); - } -#endif - - // Flags - NekoGui::dataStore->argv = QApplication::arguments(); - if (NekoGui::dataStore->argv.contains("-many")) NekoGui::dataStore->flag_many = true; - if (NekoGui::dataStore->argv.contains("-appdata")) { - NekoGui::dataStore->flag_use_appdata = true; - int appdataIndex = NekoGui::dataStore->argv.indexOf("-appdata"); - if (NekoGui::dataStore->argv.size() > appdataIndex + 1 && !NekoGui::dataStore->argv.at(appdataIndex + 1).startsWith("-")) { - NekoGui::dataStore->appdataDir = NekoGui::dataStore->argv.at(appdataIndex + 1); - } - } - if (NekoGui::dataStore->argv.contains("-tray")) NekoGui::dataStore->flag_tray = true; - if (NekoGui::dataStore->argv.contains("-debug")) NekoGui::dataStore->flag_debug = true; - if (NekoGui::dataStore->argv.contains("-flag_restart_tun_on")) NekoGui::dataStore->flag_restart_tun_on = true; - if (NekoGui::dataStore->argv.contains("-flag_reorder")) NekoGui::dataStore->flag_reorder = true; -#ifdef NKR_CPP_USE_APPDATA - NekoGui::dataStore->flag_use_appdata = true; // Example: Package & MacOS -#endif -#ifdef NKR_CPP_DEBUG - NekoGui::dataStore->flag_debug = true; -#endif - - // dirs & clean - auto wd = QDir(QApplication::applicationDirPath()); - if (NekoGui::dataStore->flag_use_appdata) { - QApplication::setApplicationName("nekoray"); - if (!NekoGui::dataStore->appdataDir.isEmpty()) { - wd.setPath(NekoGui::dataStore->appdataDir); - } else { - wd.setPath(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation)); - } - } - if (!wd.exists()) wd.mkpath(wd.absolutePath()); - if (!wd.exists("config")) wd.mkdir("config"); - QDir::setCurrent(wd.absoluteFilePath("config")); - QDir("temp").removeRecursively(); - - // init QApplication - delete preQApp; - QApplication a(argc, argv); - - // dispatchers - DS_cores = new QThread; - DS_cores->start(); - - // RunGuard - RunGuard guard("nekoray" + wd.absolutePath()); - quint64 guard_data_in = GetRandomUint64(); - quint64 guard_data_out = 0; - if (!NekoGui::dataStore->flag_many && !guard.tryToRun(&guard_data_in)) { - // Some Good System - if (guard.isAnotherRunning(&guard_data_out)) { - // Wake up a running instance - QLocalSocket socket; - socket.connectToServer(LOCAL_SERVER_PREFIX + Int2String(guard_data_out)); - qDebug() << socket.fullServerName(); - if (!socket.waitForConnected(500)) { - qDebug() << "Failed to wake a running instance."; - return 0; - } - qDebug() << "connected to local server, try to raise another program"; - return 0; - } - // Some Bad System - QMessageBox::warning(nullptr, "NekoGui", "RunGuard disallow to run, use -many to force start."); - return 0; - } - MF_release_runguard = [&] { guard.release(); }; - -// icons -#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)) - QIcon::setFallbackSearchPaths(QStringList{ - ":/neko", - ":/icon", - }); -#endif - - // icon for no theme - if (QIcon::themeName().isEmpty()) { - QIcon::setThemeName("breeze"); - } - - // Dir - QDir dir; - bool dir_success = true; - if (!dir.exists("profiles")) { - dir_success &= dir.mkdir("profiles"); - } - if (!dir.exists("groups")) { - dir_success &= dir.mkdir("groups"); - } - if (!dir.exists(ROUTES_PREFIX_NAME)) { - dir_success &= dir.mkdir(ROUTES_PREFIX_NAME); - } - if (!dir_success) { - QMessageBox::warning(nullptr, "Error", "No permission to write " + dir.absolutePath()); - return 1; - } - - // Load dataStore - switch (NekoGui::coreType) { - case NekoGui::CoreType::SING_BOX: - NekoGui::dataStore->fn = "groups/nekobox.json"; - break; - default: - MessageBoxWarning("Error", "Unknown coreType."); - return 0; - } - auto isLoaded = NekoGui::dataStore->Load(); - if (!isLoaded) { - NekoGui::dataStore->Save(); - } - - // Datastore & Flags - if (NekoGui::dataStore->start_minimal) NekoGui::dataStore->flag_tray = true; - - // load routing - NekoGui::dataStore->routing = std::make_unique(); - NekoGui::dataStore->routing->fn = ROUTES_PREFIX + NekoGui::dataStore->active_routing; - isLoaded = NekoGui::dataStore->routing->Load(); - if (!isLoaded) { - NekoGui::dataStore->routing->Save(); - } - - // Translate - QString locale; - switch (NekoGui::dataStore->language) { - case 1: // English - break; - case 2: - locale = "zh_CN"; - break; - case 3: - locale = "fa_IR"; // farsi(iran) - break; - case 4: - locale = "ru_RU"; // Russian - break; - default: - locale = QLocale().name(); - } - QGuiApplication::tr("QT_LAYOUT_DIRECTION"); - loadTranslate(locale); - - // Signals - signal(SIGTERM, signal_handler); - signal(SIGINT, signal_handler); - - // QLocalServer - QLocalServer server; - auto server_name = LOCAL_SERVER_PREFIX + Int2String(guard_data_in); - QLocalServer::removeServer(server_name); - server.listen(server_name); - QObject::connect(&server, &QLocalServer::newConnection, &a, [&] { - auto socket = server.nextPendingConnection(); - qDebug() << "nextPendingConnection:" << server_name << socket; - socket->deleteLater(); - // raise main window - MW_dialog_message("", "Raise"); - }); - - UI_InitMainWindow(); - return QApplication::exec(); -} diff --git a/nekoray_version.txt b/nekoray_version.txt deleted file mode 100644 index 866d240..0000000 --- a/nekoray_version.txt +++ /dev/null @@ -1 +0,0 @@ -4.0.1-2024-12-12 diff --git a/res/dashboard-notice.html b/res/dashboard-notice.html deleted file mode 100644 index cfea1c7..0000000 --- a/res/dashboard-notice.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - -

-

Please put your clash dashboard files to "./config/dashboard" dir.

-

For example, you can download from the following URL.

-

- Download Yacd-meta - or - Use online -

-

- - - \ No newline at end of file diff --git a/res/icon/dialog-question.svg b/res/icon/dialog-question.svg deleted file mode 100644 index 7ff4bc4..0000000 --- a/res/icon/dialog-question.svg +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/res/icon/internet-web-browser.svg b/res/icon/internet-web-browser.svg deleted file mode 100644 index 138a1a3..0000000 --- a/res/icon/internet-web-browser.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/res/icon/material/cancel.svg b/res/icon/material/cancel.svg deleted file mode 100644 index 3327c05..0000000 --- a/res/icon/material/cancel.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/res/icon/material/delete.svg b/res/icon/material/delete.svg deleted file mode 100644 index 21c80c2..0000000 --- a/res/icon/material/delete.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/res/icon/material/history.svg b/res/icon/material/history.svg deleted file mode 100644 index 20c490c..0000000 --- a/res/icon/material/history.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/res/icon/material/lock-open-outline.svg b/res/icon/material/lock-open-outline.svg deleted file mode 100644 index 4e0291d..0000000 --- a/res/icon/material/lock-open-outline.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/res/icon/material/lock-outline.svg b/res/icon/material/lock-outline.svg deleted file mode 100644 index 4dee801..0000000 --- a/res/icon/material/lock-outline.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/res/icon/material/swap-horizontal.svg b/res/icon/material/swap-horizontal.svg deleted file mode 100644 index 3f30649..0000000 --- a/res/icon/material/swap-horizontal.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/res/icon/material/swap-vertical.svg b/res/icon/material/swap-vertical.svg deleted file mode 100644 index 41d46a9..0000000 --- a/res/icon/material/swap-vertical.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/res/icon/network-server.svg b/res/icon/network-server.svg deleted file mode 100644 index 0806722..0000000 --- a/res/icon/network-server.svg +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - diff --git a/res/icon/preferences.svg b/res/icon/preferences.svg deleted file mode 100644 index 875b939..0000000 --- a/res/icon/preferences.svg +++ /dev/null @@ -1,141 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/res/icon/system-run.svg b/res/icon/system-run.svg deleted file mode 100644 index 45494f4..0000000 --- a/res/icon/system-run.svg +++ /dev/null @@ -1,190 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/res/icon/system-software-update.svg b/res/icon/system-software-update.svg deleted file mode 100644 index e8567fb..0000000 --- a/res/icon/system-software-update.svg +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/res/neko.css b/res/neko.css deleted file mode 100644 index 512e281..0000000 --- a/res/neko.css +++ /dev/null @@ -1,3 +0,0 @@ -QMessageBox { - messagebox-text-interaction-flags: 5; -} diff --git a/res/neko.qrc b/res/neko.qrc deleted file mode 100644 index 10e97e1..0000000 --- a/res/neko.qrc +++ /dev/null @@ -1,24 +0,0 @@ - - - icon/internet-web-browser.svg - icon/system-run.svg - icon/preferences.svg - icon/network-server.svg - icon/dialog-question.svg - icon/system-software-update.svg - icon/material/lock-open-outline.svg - icon/material/lock-outline.svg - icon/material/cancel.svg - icon/material/history.svg - icon/material/swap-vertical.svg - icon/material/delete.svg - icon/material/swap-horizontal.svg - - - public/nekobox.png - neko.css - vpn/vpn-run-root.sh - vpn/sing-box-vpn.json - dashboard-notice.html - - diff --git a/res/nekobox.ico b/res/nekobox.ico deleted file mode 100644 index 451e66f..0000000 Binary files a/res/nekobox.ico and /dev/null differ diff --git a/res/public/nekobox.png b/res/public/nekobox.png deleted file mode 100644 index 4ba56b0..0000000 Binary files a/res/public/nekobox.png and /dev/null differ diff --git a/res/public/qtbase_zh_CN.qm b/res/public/qtbase_zh_CN.qm deleted file mode 100644 index 8f4354d..0000000 Binary files a/res/public/qtbase_zh_CN.qm and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss.qrc b/res/theme/feiyangqingyun/qss.qrc deleted file mode 100644 index 5541c0d..0000000 --- a/res/theme/feiyangqingyun/qss.qrc +++ /dev/null @@ -1,76 +0,0 @@ - - - qss/flatgray.css - qss/lightblue.css - qss/flatgray/add_bottom.png - qss/flatgray/add_left.png - qss/flatgray/add_right.png - qss/flatgray/add_top.png - qss/flatgray/arrow_bottom.png - qss/flatgray/arrow_left.png - qss/flatgray/arrow_right.png - qss/flatgray/arrow_top.png - qss/flatgray/branch_close.png - qss/flatgray/branch_open.png - qss/flatgray/calendar_nextmonth.png - qss/flatgray/calendar_prevmonth.png - qss/flatgray/checkbox_checked.png - qss/flatgray/checkbox_checked_disable.png - qss/flatgray/checkbox_parcial.png - qss/flatgray/checkbox_parcial_disable.png - qss/flatgray/checkbox_unchecked.png - qss/flatgray/checkbox_unchecked_disable.png - qss/flatgray/menu_checked.png - qss/flatgray/radiobutton_checked.png - qss/flatgray/radiobutton_checked_disable.png - qss/flatgray/radiobutton_unchecked.png - qss/flatgray/radiobutton_unchecked_disable.png - qss/lightblue/add_bottom.png - qss/lightblue/add_left.png - qss/lightblue/add_right.png - qss/lightblue/add_top.png - qss/lightblue/arrow_bottom.png - qss/lightblue/arrow_left.png - qss/lightblue/arrow_right.png - qss/lightblue/arrow_top.png - qss/lightblue/branch_close.png - qss/lightblue/branch_open.png - qss/lightblue/calendar_nextmonth.png - qss/lightblue/calendar_prevmonth.png - qss/lightblue/checkbox_checked.png - qss/lightblue/checkbox_checked_disable.png - qss/lightblue/checkbox_parcial.png - qss/lightblue/checkbox_parcial_disable.png - qss/lightblue/checkbox_unchecked.png - qss/lightblue/checkbox_unchecked_disable.png - qss/lightblue/menu_checked.png - qss/lightblue/radiobutton_checked.png - qss/lightblue/radiobutton_checked_disable.png - qss/lightblue/radiobutton_unchecked.png - qss/lightblue/radiobutton_unchecked_disable.png - qss/blacksoft.css - qss/blacksoft/add_bottom.png - qss/blacksoft/add_left.png - qss/blacksoft/add_right.png - qss/blacksoft/add_top.png - qss/blacksoft/arrow_bottom.png - qss/blacksoft/arrow_left.png - qss/blacksoft/arrow_right.png - qss/blacksoft/arrow_top.png - qss/blacksoft/branch_close.png - qss/blacksoft/branch_open.png - qss/blacksoft/calendar_nextmonth.png - qss/blacksoft/calendar_prevmonth.png - qss/blacksoft/checkbox_checked.png - qss/blacksoft/checkbox_checked_disable.png - qss/blacksoft/checkbox_parcial.png - qss/blacksoft/checkbox_parcial_disable.png - qss/blacksoft/checkbox_unchecked.png - qss/blacksoft/checkbox_unchecked_disable.png - qss/blacksoft/menu_checked.png - qss/blacksoft/radiobutton_checked.png - qss/blacksoft/radiobutton_checked_disable.png - qss/blacksoft/radiobutton_unchecked.png - qss/blacksoft/radiobutton_unchecked_disable.png - - diff --git a/res/theme/feiyangqingyun/qss/blacksoft.css b/res/theme/feiyangqingyun/qss/blacksoft.css deleted file mode 100644 index 09a607a..0000000 --- a/res/theme/feiyangqingyun/qss/blacksoft.css +++ /dev/null @@ -1,679 +0,0 @@ -QPalette{background:#444444;}*{outline:0px;color:#DCDCDC;} - -QGraphicsView{ -border:1px solid #242424; -qproperty-backgroundBrush:#444444; -} - -QWidget[form="true"],QLabel[frameShape="1"]{ -border:1px solid #242424; -border-radius:0px; -} - -QWidget[form="bottom"]{ -background:#484848; -} - -QWidget[form="bottom"] .QFrame{ -border:1px solid #DCDCDC; -} - -QWidget[form="bottom"] QLabel,QWidget[form="title"] QLabel{ -border-radius:0px; -color:#DCDCDC; -background:none; -border-style:none; -} - -QWidget[form="title"],QWidget[nav="left"],QWidget[nav="top"] QAbstractButton{ -border-style:none; -border-radius:0px; -padding:5px; -color:#DCDCDC; -background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #484848,stop:1 #383838); -} - -QWidget[nav="top"] QAbstractButton:hover,QWidget[nav="top"] QAbstractButton:pressed,QWidget[nav="top"] QAbstractButton:checked{ -border-style:solid; -border-width:0px 0px 2px 0px; -padding:4px 4px 2px 4px; -border-color:#AAAAAA; -background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #646464,stop:1 #525252); -} - -QWidget[nav="left"] QAbstractButton{ -border-radius:0px; -color:#DCDCDC; -background:none; -border-style:none; -} - -QWidget[nav="left"] QAbstractButton:hover{ -color:#FFFFFF; -background-color:#AAAAAA; -} - -QWidget[nav="left"] QAbstractButton:checked,QWidget[nav="left"] QAbstractButton:pressed{ -color:#DCDCDC; -border-style:solid; -border-width:0px 0px 0px 2px; -padding:4px 4px 4px 2px; -border-color:#AAAAAA; -background-color:#444444; -} - -QWidget[video="true"] QLabel{ -color:#DCDCDC; -border:1px solid #242424; -background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #484848,stop:1 #383838); -} - -QWidget[video="true"] QLabel:focus{ -border:1px solid #AAAAAA; -background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #646464,stop:1 #525252); -} - -QLineEdit:read-only{ -background-color:#484848; -} - -QLineEdit,QTextEdit,QPlainTextEdit,QSpinBox,QDoubleSpinBox,QComboBox,QDateEdit,QTimeEdit,QDateTimeEdit{ -border:1px solid #242424; -border-radius:3px; -padding:2px; -background:none; -selection-background-color:#AAAAAA; -selection-color:#FFFFFF; -} - -QLineEdit:focus,QTextEdit:focus,QPlainTextEdit:focus,QSpinBox:focus,QDoubleSpinBox:focus,QComboBox:focus,QDateEdit:focus,QTimeEdit:focus,QDateTimeEdit:focus,QLineEdit:hover,QTextEdit:hover,QPlainTextEdit:hover,QSpinBox:hover,QDoubleSpinBox:hover,QComboBox:hover,QDateEdit:hover,QTimeEdit:hover,QDateTimeEdit:hover{ -border:1px solid #242424; -} - -QLineEdit[echoMode="2"]{ -lineedit-password-character:9679; -} - -.QFrame{ -border:1px solid #242424; -border-radius:3px; -} - -.QGroupBox{ -border:1px solid #242424; -border-radius:5px; -margin-top:3ex; -} - -.QGroupBox::title{ -subcontrol-origin:margin; -position:relative; -left:10px; -} - -.QPushButton,.QToolButton{ -border-style:none; -border:1px solid #242424; -color:#DCDCDC; -padding:5px; -min-height:15px; -border-radius:5px; -background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #484848,stop:1 #383838); -} - -.QPushButton:hover,.QToolButton:hover{ -background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #646464,stop:1 #525252); -} - -.QPushButton:pressed,.QToolButton:pressed{ -background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #484848,stop:1 #383838); -} - -.QToolButton::menu-indicator{ -image:None; -} - -QToolButton#btnMenu,QPushButton#btnMenu_Min,QPushButton#btnMenu_Max,QPushButton#btnMenu_Close{ -border-radius:3px; -color:#DCDCDC; -padding:3px; -margin:0px; -background:none; -border-style:none; -} - -QToolButton#btnMenu:hover,QPushButton#btnMenu_Min:hover,QPushButton#btnMenu_Max:hover{ -color:#FFFFFF; -margin:1px 1px 2px 1px; -background-color:rgba(51,127,209,230); -} - -QPushButton#btnMenu_Close:hover{ -color:#FFFFFF; -margin:1px 1px 2px 1px; -background-color:rgba(238,0,0,128); -} - -QRadioButton::indicator{ -width:15px; -height:15px; -} - -QRadioButton::indicator::unchecked{ -image:url(:/qss/blacksoft/radiobutton_unchecked.png); -} - -QRadioButton::indicator::unchecked:disabled{ -image:url(:/qss/blacksoft/radiobutton_unchecked_disable.png); -} - -QRadioButton::indicator::checked{ -image:url(:/qss/blacksoft/radiobutton_checked.png); -} - -QRadioButton::indicator::checked:disabled{ -image:url(:/qss/blacksoft/radiobutton_checked_disable.png); -} - -QGroupBox::indicator,QTreeView::indicator,QListView::indicator,QTableView::indicator{ -padding:0px 0px 0px 0px; -} - -QCheckBox::indicator,QGroupBox::indicator,QTreeView::indicator,QListView::indicator,QTableView::indicator{ -width:13px; -height:13px; -} - -QCheckBox::indicator:unchecked,QGroupBox::indicator:unchecked,QTreeView::indicator:unchecked,QListView::indicator:unchecked,QTableView::indicator:unchecked{ -image:url(:/qss/blacksoft/checkbox_unchecked.png); -} - -QCheckBox::indicator:unchecked:disabled,QGroupBox::indicator:unchecked:disabled,QTreeView::indicator:unchecked:disabled,QListView::indicator:unchecked:disabled,QTableView::indicator:unchecked:disabled{ -image:url(:/qss/blacksoft/checkbox_unchecked_disable.png); -} - -QCheckBox::indicator:checked,QGroupBox::indicator:checked,QTreeView::indicator:checked,QListView::indicator:checked,QTableView::indicator:checked{ -image:url(:/qss/blacksoft/checkbox_checked.png); -} - -QCheckBox::indicator:checked:disabled,QGroupBox::indicator:checked:disabled,QTreeView::indicator:checked:disabled,QListView::indicator:checked:disabled,QTableView::indicator:checked:disabled{ -image:url(:/qss/blacksoft/checkbox_checked_disable.png); -} - -QCheckBox::indicator:indeterminate,QGroupBox::indicator:indeterminate,QTreeView::indicator:indeterminate,QListView::indicator:indeterminate,QTableView::indicator:indeterminate{ -image:url(:/qss/blacksoft/checkbox_parcial.png); -} - -QCheckBox::indicator:indeterminate:disabled,QGroupBox::indicator:indeterminate:disabled,QTreeView::indicator:indeterminate:disabled,QListView::indicator:indeterminate:disabled,QTableView::indicator:indeterminate:disabled{ -image:url(:/qss/blacksoft/checkbox_parcial_disable.png); -} - -QTimeEdit::up-button,QDateEdit::up-button,QDateTimeEdit::up-button,QDoubleSpinBox::up-button,QSpinBox::up-button{ -image:url(:/qss/blacksoft/add_top.png); -width:10px; -height:10px; -padding:2px 5px 0px 0px; -} - -QTimeEdit::down-button,QDateEdit::down-button,QDateTimeEdit::down-button,QDoubleSpinBox::down-button,QSpinBox::down-button{ -image:url(:/qss/blacksoft/add_bottom.png); -width:10px; -height:10px; -padding:0px 5px 2px 0px; -} - -QTimeEdit::up-button:pressed,QDateEdit::up-button:pressed,QDateTimeEdit::up-button:pressed,QDoubleSpinBox::up-button:pressed,QSpinBox::up-button:pressed{ -top:-2px; -} - -QTimeEdit::down-button:pressed,QDateEdit::down-button:pressed,QDateTimeEdit::down-button:pressed,QDoubleSpinBox::down-button:pressed,QSpinBox::down-button:pressed,QSpinBox::down-button:pressed{ -bottom:-2px; -} - -QComboBox::down-arrow,QDateEdit[calendarPopup="true"]::down-arrow,QTimeEdit[calendarPopup="true"]::down-arrow,QDateTimeEdit[calendarPopup="true"]::down-arrow{ -image:url(:/qss/blacksoft/add_bottom.png); -width:10px; -height:10px; -right:2px; -} - -QComboBox::drop-down,QDateEdit::drop-down,QTimeEdit::drop-down,QDateTimeEdit::drop-down{ -subcontrol-origin:padding; -subcontrol-position:top right; -width:15px; -border-left-width:0px; -border-left-style:solid; -border-top-right-radius:3px; -border-bottom-right-radius:3px; -border-left-color:#242424; -} - -QComboBox::drop-down:on{ -top:1px; -} - -QMenuBar::item{ -color:#DCDCDC; -background-color:#484848; -margin:0px; -padding:3px 10px; -} - -QMenu,QMenuBar,QMenu:disabled,QMenuBar:disabled{ -color:#DCDCDC; -background-color:#484848; -border:1px solid #242424; -margin:0px; -} - -QMenu::item{ -padding:3px 20px; -} - -QMenu::indicator{ -width:20px; -height:13px; -} - -QMenu::indicator::checked{ -image:url(:/qss/blacksoft/menu_checked.png); -} - -QMenu::right-arrow{ -image:url(:/qss/blacksoft/arrow_right.png); -width:13px; -height:13px; -padding:0px 3px 0px 0px; -} - -QMenu::item:selected,QMenuBar::item:selected{ -color:#DCDCDC; -border:0px solid #242424; -background:#646464; -} - -QMenu::separator{ -height:1px; -background:#242424; -} - -QProgressBar{ -min-height:10px; -background:#484848; -border-radius:5px; -text-align:center; -border:1px solid #484848; -} - -QProgressBar:chunk{ -border-radius:5px; -background-color:#242424; -} - -QSlider::groove:horizontal{ -height:8px; -border-radius:4px; -background:#484848; -} - -QSlider::add-page:horizontal{ -height:8px; -border-radius:4px; -background:#484848; -} - -QSlider::sub-page:horizontal{ -height:8px; -border-radius:4px; -background:#242424; -} - -QSlider::handle:horizontal{ -width:13px; -margin-top:-3px; -margin-bottom:-3px; -border-radius:6px; -background:qradialgradient(spread:pad,cx:0.5,cy:0.5,radius:0.5,fx:0.5,fy:0.5,stop:0.6 #444444,stop:0.8 #242424); -} - -QSlider::groove:vertical{ -width:8px; -border-radius:4px; -background:#484848; -} - -QSlider::add-page:vertical{ -width:8px; -border-radius:4px; -background:#242424; -} - -QSlider::sub-page:vertical{ -width:8px; -border-radius:4px; -background:#484848; -} - -QSlider::handle:vertical{ -height:14px; -margin-left:-3px; -margin-right:-3px; -border-radius:6px; -background:qradialgradient(spread:pad,cx:0.5,cy:0.5,radius:0.5,fx:0.5,fy:0.5,stop:0.6 #444444,stop:0.8 #242424); -} - -QScrollBar:horizontal{ -background:#484848; -padding:0px; -border-radius:6px; -max-height:12px; -} - -QScrollBar::handle:horizontal{ -background:#242424; -min-width:50px; -border-radius:6px; -} - -QScrollBar::handle:horizontal:hover{ -background:#AAAAAA; -} - -QScrollBar::handle:horizontal:pressed{ -background:#AAAAAA; -} - -QScrollBar::add-page:horizontal{ -background:none; -} - -QScrollBar::sub-page:horizontal{ -background:none; -} - -QScrollBar::add-line:horizontal{ -background:none; -} - -QScrollBar::sub-line:horizontal{ -background:none; -} - -QScrollBar:vertical{ -background:#484848; -padding:0px; -border-radius:6px; -max-width:12px; -} - -QScrollBar::handle:vertical{ -background:#242424; -min-height:50px; -border-radius:6px; -} - -QScrollBar::handle:vertical:hover{ -background:#AAAAAA; -} - -QScrollBar::handle:vertical:pressed{ -background:#AAAAAA; -} - -QScrollBar::add-page:vertical{ -background:none; -} - -QScrollBar::sub-page:vertical{ -background:none; -} - -QScrollBar::add-line:vertical{ -background:none; -} - -QScrollBar::sub-line:vertical{ -background:none; -} - -QScrollArea{ -border:0px; -} - -QTreeView,QListView,QTableView,QTabWidget::pane{ -border:1px solid #242424; -selection-background-color:#646464; -selection-color:#DCDCDC; -alternate-background-color:#525252; -gridline-color:#242424; -} - -QTreeView::branch:closed:has-children{ -margin:4px; -border-image:url(:/qss/blacksoft/branch_open.png); -} - -QTreeView::branch:open:has-children{ -margin:4px; -border-image:url(:/qss/blacksoft/branch_close.png); -} - -QTreeView,QListView,QTableView,QSplitter::handle,QTreeView::branch{ -background:#444444; -} - -QTableView::item:selected,QListView::item:selected,QTreeView::item:selected{ -color:#DCDCDC; -background:#383838; -} - -QTableView::item:hover,QListView::item:hover,QTreeView::item:hover,QHeaderView,QHeaderView::section,QTableCornerButton:section{ -color:#DCDCDC; -background:#525252; -} - -QTableView::item,QListView::item,QTreeView::item{ -padding:1px; -margin:0px; -border:0px; -} - -QHeaderView::section,QTableCornerButton:section{ -padding:3px; -margin:0px; -border:1px solid #242424; -border-left-width:0px; -border-right-width:1px; -border-top-width:0px; -border-bottom-width:1px; -} - -QTabBar::tab{ -border:1px solid #242424; -color:#DCDCDC; -margin:0px; -background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #646464,stop:1 #525252); -} - -QTabBar::tab:selected{ -border-style:solid; -border-color:#AAAAAA; -background:#444444; -} - -QTabBar::tab:top,QTabBar::tab:bottom{ -padding:3px 8px 3px 8px; -} - -QTabBar::tab:left,QTabBar::tab:right{ -padding:8px 3px 8px 3px; -} - -QTabBar::tab:top:selected{ -border-width:2px 0px 0px 0px; -} - -QTabBar::tab:right:selected{ -border-width:0px 0px 0px 2px; -} - -QTabBar::tab:bottom:selected{ -border-width:0px 0px 2px 0px; -} - -QTabBar::tab:left:selected{ -border-width:0px 2px 0px 0px; -} - -QTabBar::tab:first:top:selected,QTabBar::tab:first:bottom:selected{ -border-left-width:1px; -border-left-color:#242424; -} - -QTabBar::tab:first:left:selected,QTabBar::tab:first:right:selected{ -border-top-width:1px; -border-top-color:#242424; -} - -QTabBar::tab:last:top:selected,QTabBar::tab:last:bottom:selected{ -border-right-width:1px; -border-right-color:#242424; -} - -QTabBar::tab:last:left:selected,QTabBar::tab:last:right:selected{ -border-bottom-width:1px; -border-bottom-color:#242424; -} - -QStatusBar::item{ -border:0px solid #484848; -border-radius:3px; -} - -QToolBox::tab,QGroupBox#gboxDevicePanel,QGroupBox#gboxDeviceTitle,QFrame#gboxDevicePanel,QFrame#gboxDeviceTitle{ -padding:3px; -border-radius:5px; -color:#DCDCDC; -background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #484848,stop:1 #383838); -} - -QToolTip{ -border:0px solid #DCDCDC; -padding:1px; -color:#DCDCDC; -background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #484848,stop:1 #383838); -} - -QToolBox::tab:selected{ -background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #646464,stop:1 #525252); -} - -QPrintPreviewDialog QToolButton{ -border:0px solid #DCDCDC; -border-radius:0px; -margin:0px; -padding:3px; -background:none; -} - -QColorDialog QPushButton,QFileDialog QPushButton{ -min-width:80px; -} - -QToolButton#qt_calendar_prevmonth{ -icon-size:0px; -min-width:20px; -image:url(:/qss/blacksoft/calendar_prevmonth.png); -} - -QToolButton#qt_calendar_nextmonth{ -icon-size:0px; -min-width:20px; -image:url(:/qss/blacksoft/calendar_nextmonth.png); -} - -QToolButton#qt_calendar_prevmonth,QToolButton#qt_calendar_nextmonth,QToolButton#qt_calendar_monthbutton,QToolButton#qt_calendar_yearbutton{ -border:0px solid #DCDCDC; -border-radius:3px; -margin:3px 3px 3px 3px; -padding:3px; -background:none; -} - -QToolButton#qt_calendar_prevmonth:hover,QToolButton#qt_calendar_nextmonth:hover,QToolButton#qt_calendar_monthbutton:hover,QToolButton#qt_calendar_yearbutton:hover,QToolButton#qt_calendar_prevmonth:pressed,QToolButton#qt_calendar_nextmonth:pressed,QToolButton#qt_calendar_monthbutton:pressed,QToolButton#qt_calendar_yearbutton:pressed{ -border:1px solid #242424; -} - -QCalendarWidget QSpinBox#qt_calendar_yearedit{ -margin:2px; -} - -QCalendarWidget QToolButton::menu-indicator{ -image:None; -} - -QCalendarWidget QTableView{ -border-width:0px; -} - -QCalendarWidget QWidget#qt_calendar_navigationbar{ -border:1px solid #242424; -border-width:1px 1px 0px 1px; -background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #484848,stop:1 #383838); -} - -QTableView[model="true"]::item{ -padding:0px; -margin:0px; -} - -QTableView QLineEdit,QTableView QComboBox,QTableView QSpinBox,QTableView QDoubleSpinBox,QTableView QDateEdit,QTableView QTimeEdit,QTableView QDateTimeEdit{ -border-width:0px; -border-radius:0px; -} - -QTableView QLineEdit:focus,QTableView QComboBox:focus,QTableView QSpinBox:focus,QTableView QDoubleSpinBox:focus,QTableView QDateEdit:focus,QTableView QTimeEdit:focus,QTableView QDateTimeEdit:focus{ -border-width:0px; -border-radius:0px; -} - -QLineEdit,QTextEdit,QPlainTextEdit,QSpinBox,QDoubleSpinBox,QComboBox,QDateEdit,QTimeEdit,QDateTimeEdit{ -background:#444444; -} - -QTabWidget::pane:top{top:-1px;} -QTabWidget::pane:bottom{bottom:-1px;} -QTabWidget::pane:left{right:-1px;} -QTabWidget::pane:right{left:-1px;} - -QDialog,QDial,#QUIWidgetMain{ -background-color:#444444; -color:#DCDCDC; -} - -QDialogButtonBox>QPushButton{ -min-width:50px; -} - -QListView[noborder="true"],QTreeView[noborder="true"],QTabWidget[noborder="true"]::pane{ -border-width:0px; -} - -QToolBar>*,QStatusBar>*{ -margin:2px; -} - -*:disabled,QMenu::item:disabled,QTabBar:tab:disabled,QHeaderView::section:disabled{ -background:#444444; -border-color:#484848; -color:#242424; -} - -/*TextColor:#DCDCDC*/ -/*PanelColor:#444444*/ -/*BorderColor:#242424*/ -/*NormalColorStart:#484848*/ -/*NormalColorEnd:#383838*/ -/*DarkColorStart:#646464*/ -/*DarkColorEnd:#525252*/ -/*HighColor:#AAAAAA*/ \ No newline at end of file diff --git a/res/theme/feiyangqingyun/qss/blacksoft/add_bottom.png b/res/theme/feiyangqingyun/qss/blacksoft/add_bottom.png deleted file mode 100644 index b4a5f14..0000000 Binary files a/res/theme/feiyangqingyun/qss/blacksoft/add_bottom.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/blacksoft/add_left.png b/res/theme/feiyangqingyun/qss/blacksoft/add_left.png deleted file mode 100644 index 165ebd0..0000000 Binary files a/res/theme/feiyangqingyun/qss/blacksoft/add_left.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/blacksoft/add_right.png b/res/theme/feiyangqingyun/qss/blacksoft/add_right.png deleted file mode 100644 index 4c79925..0000000 Binary files a/res/theme/feiyangqingyun/qss/blacksoft/add_right.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/blacksoft/add_top.png b/res/theme/feiyangqingyun/qss/blacksoft/add_top.png deleted file mode 100644 index f76300f..0000000 Binary files a/res/theme/feiyangqingyun/qss/blacksoft/add_top.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/blacksoft/arrow_bottom.png b/res/theme/feiyangqingyun/qss/blacksoft/arrow_bottom.png deleted file mode 100644 index 39d7cbc..0000000 Binary files a/res/theme/feiyangqingyun/qss/blacksoft/arrow_bottom.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/blacksoft/arrow_left.png b/res/theme/feiyangqingyun/qss/blacksoft/arrow_left.png deleted file mode 100644 index 1353cb8..0000000 Binary files a/res/theme/feiyangqingyun/qss/blacksoft/arrow_left.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/blacksoft/arrow_right.png b/res/theme/feiyangqingyun/qss/blacksoft/arrow_right.png deleted file mode 100644 index 0e50d47..0000000 Binary files a/res/theme/feiyangqingyun/qss/blacksoft/arrow_right.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/blacksoft/arrow_top.png b/res/theme/feiyangqingyun/qss/blacksoft/arrow_top.png deleted file mode 100644 index d2c71e8..0000000 Binary files a/res/theme/feiyangqingyun/qss/blacksoft/arrow_top.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/blacksoft/branch_close.png b/res/theme/feiyangqingyun/qss/blacksoft/branch_close.png deleted file mode 100644 index 58a7d13..0000000 Binary files a/res/theme/feiyangqingyun/qss/blacksoft/branch_close.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/blacksoft/branch_open.png b/res/theme/feiyangqingyun/qss/blacksoft/branch_open.png deleted file mode 100644 index a072d68..0000000 Binary files a/res/theme/feiyangqingyun/qss/blacksoft/branch_open.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/blacksoft/calendar_nextmonth.png b/res/theme/feiyangqingyun/qss/blacksoft/calendar_nextmonth.png deleted file mode 100644 index b06ae31..0000000 Binary files a/res/theme/feiyangqingyun/qss/blacksoft/calendar_nextmonth.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/blacksoft/calendar_prevmonth.png b/res/theme/feiyangqingyun/qss/blacksoft/calendar_prevmonth.png deleted file mode 100644 index 46d4d62..0000000 Binary files a/res/theme/feiyangqingyun/qss/blacksoft/calendar_prevmonth.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/blacksoft/checkbox_checked.png b/res/theme/feiyangqingyun/qss/blacksoft/checkbox_checked.png deleted file mode 100644 index b5ba6ef..0000000 Binary files a/res/theme/feiyangqingyun/qss/blacksoft/checkbox_checked.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/blacksoft/checkbox_checked_disable.png b/res/theme/feiyangqingyun/qss/blacksoft/checkbox_checked_disable.png deleted file mode 100644 index f6aab40..0000000 Binary files a/res/theme/feiyangqingyun/qss/blacksoft/checkbox_checked_disable.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/blacksoft/checkbox_parcial.png b/res/theme/feiyangqingyun/qss/blacksoft/checkbox_parcial.png deleted file mode 100644 index cd1645f..0000000 Binary files a/res/theme/feiyangqingyun/qss/blacksoft/checkbox_parcial.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/blacksoft/checkbox_parcial_disable.png b/res/theme/feiyangqingyun/qss/blacksoft/checkbox_parcial_disable.png deleted file mode 100644 index dd0918f..0000000 Binary files a/res/theme/feiyangqingyun/qss/blacksoft/checkbox_parcial_disable.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/blacksoft/checkbox_unchecked.png b/res/theme/feiyangqingyun/qss/blacksoft/checkbox_unchecked.png deleted file mode 100644 index 8a23968..0000000 Binary files a/res/theme/feiyangqingyun/qss/blacksoft/checkbox_unchecked.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/blacksoft/checkbox_unchecked_disable.png b/res/theme/feiyangqingyun/qss/blacksoft/checkbox_unchecked_disable.png deleted file mode 100644 index e2a2262..0000000 Binary files a/res/theme/feiyangqingyun/qss/blacksoft/checkbox_unchecked_disable.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/blacksoft/menu_checked.png b/res/theme/feiyangqingyun/qss/blacksoft/menu_checked.png deleted file mode 100644 index 4fca11f..0000000 Binary files a/res/theme/feiyangqingyun/qss/blacksoft/menu_checked.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/blacksoft/radiobutton_checked.png b/res/theme/feiyangqingyun/qss/blacksoft/radiobutton_checked.png deleted file mode 100644 index 69e499f..0000000 Binary files a/res/theme/feiyangqingyun/qss/blacksoft/radiobutton_checked.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/blacksoft/radiobutton_checked_disable.png b/res/theme/feiyangqingyun/qss/blacksoft/radiobutton_checked_disable.png deleted file mode 100644 index f098cc5..0000000 Binary files a/res/theme/feiyangqingyun/qss/blacksoft/radiobutton_checked_disable.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/blacksoft/radiobutton_unchecked.png b/res/theme/feiyangqingyun/qss/blacksoft/radiobutton_unchecked.png deleted file mode 100644 index 3f36472..0000000 Binary files a/res/theme/feiyangqingyun/qss/blacksoft/radiobutton_unchecked.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/blacksoft/radiobutton_unchecked_disable.png b/res/theme/feiyangqingyun/qss/blacksoft/radiobutton_unchecked_disable.png deleted file mode 100644 index f729f17..0000000 Binary files a/res/theme/feiyangqingyun/qss/blacksoft/radiobutton_unchecked_disable.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/flatgray.css b/res/theme/feiyangqingyun/qss/flatgray.css deleted file mode 100644 index 883e90f..0000000 --- a/res/theme/feiyangqingyun/qss/flatgray.css +++ /dev/null @@ -1,679 +0,0 @@ -QPalette{background:#FFFFFF;}*{outline:0px;color:#57595B;} - -QGraphicsView{ -border:1px solid #B6B6B6; -qproperty-backgroundBrush:#FFFFFF; -} - -QWidget[form="true"],QLabel[frameShape="1"]{ -border:1px solid #B6B6B6; -border-radius:0px; -} - -QWidget[form="bottom"]{ -background:#E4E4E4; -} - -QWidget[form="bottom"] .QFrame{ -border:1px solid #57595B; -} - -QWidget[form="bottom"] QLabel,QWidget[form="title"] QLabel{ -border-radius:0px; -color:#57595B; -background:none; -border-style:none; -} - -QWidget[form="title"],QWidget[nav="left"],QWidget[nav="top"] QAbstractButton{ -border-style:none; -border-radius:0px; -padding:5px; -color:#57595B; -background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #E4E4E4,stop:1 #E4E4E4); -} - -QWidget[nav="top"] QAbstractButton:hover,QWidget[nav="top"] QAbstractButton:pressed,QWidget[nav="top"] QAbstractButton:checked{ -border-style:solid; -border-width:0px 0px 2px 0px; -padding:4px 4px 2px 4px; -border-color:#575959; -background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #F6F6F6,stop:1 #F6F6F6); -} - -QWidget[nav="left"] QAbstractButton{ -border-radius:0px; -color:#57595B; -background:none; -border-style:none; -} - -QWidget[nav="left"] QAbstractButton:hover{ -color:#FFFFFF; -background-color:#575959; -} - -QWidget[nav="left"] QAbstractButton:checked,QWidget[nav="left"] QAbstractButton:pressed{ -color:#57595B; -border-style:solid; -border-width:0px 0px 0px 2px; -padding:4px 4px 4px 2px; -border-color:#575959; -background-color:#FFFFFF; -} - -QWidget[video="true"] QLabel{ -color:#57595B; -border:1px solid #B6B6B6; -background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #E4E4E4,stop:1 #E4E4E4); -} - -QWidget[video="true"] QLabel:focus{ -border:1px solid #575959; -background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #F6F6F6,stop:1 #F6F6F6); -} - -QLineEdit:read-only{ -background-color:#E4E4E4; -} - -QLineEdit,QTextEdit,QPlainTextEdit,QSpinBox,QDoubleSpinBox,QComboBox,QDateEdit,QTimeEdit,QDateTimeEdit{ -border:1px solid #B6B6B6; -border-radius:3px; -padding:2px; -background:none; -selection-background-color:#575959; -selection-color:#FFFFFF; -} - -QLineEdit:focus,QTextEdit:focus,QPlainTextEdit:focus,QSpinBox:focus,QDoubleSpinBox:focus,QComboBox:focus,QDateEdit:focus,QTimeEdit:focus,QDateTimeEdit:focus,QLineEdit:hover,QTextEdit:hover,QPlainTextEdit:hover,QSpinBox:hover,QDoubleSpinBox:hover,QComboBox:hover,QDateEdit:hover,QTimeEdit:hover,QDateTimeEdit:hover{ -border:1px solid #B6B6B6; -} - -QLineEdit[echoMode="2"]{ -lineedit-password-character:9679; -} - -.QFrame{ -border:1px solid #B6B6B6; -border-radius:3px; -} - -.QGroupBox{ -border:1px solid #B6B6B6; -border-radius:5px; -margin-top:3ex; -} - -.QGroupBox::title{ -subcontrol-origin:margin; -position:relative; -left:10px; -} - -.QPushButton,.QToolButton{ -border-style:none; -border:1px solid #B6B6B6; -color:#57595B; -padding:5px; -min-height:15px; -border-radius:5px; -background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #E4E4E4,stop:1 #E4E4E4); -} - -.QPushButton:hover,.QToolButton:hover{ -background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #F6F6F6,stop:1 #F6F6F6); -} - -.QPushButton:pressed,.QToolButton:pressed{ -background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #E4E4E4,stop:1 #E4E4E4); -} - -.QToolButton::menu-indicator{ -image:None; -} - -QToolButton#btnMenu,QPushButton#btnMenu_Min,QPushButton#btnMenu_Max,QPushButton#btnMenu_Close{ -border-radius:3px; -color:#57595B; -padding:3px; -margin:0px; -background:none; -border-style:none; -} - -QToolButton#btnMenu:hover,QPushButton#btnMenu_Min:hover,QPushButton#btnMenu_Max:hover{ -color:#FFFFFF; -margin:1px 1px 2px 1px; -background-color:rgba(51,127,209,230); -} - -QPushButton#btnMenu_Close:hover{ -color:#FFFFFF; -margin:1px 1px 2px 1px; -background-color:rgba(238,0,0,128); -} - -QRadioButton::indicator{ -width:15px; -height:15px; -} - -QRadioButton::indicator::unchecked{ -image:url(:/qss/flatgray/radiobutton_unchecked.png); -} - -QRadioButton::indicator::unchecked:disabled{ -image:url(:/qss/flatgray/radiobutton_unchecked_disable.png); -} - -QRadioButton::indicator::checked{ -image:url(:/qss/flatgray/radiobutton_checked.png); -} - -QRadioButton::indicator::checked:disabled{ -image:url(:/qss/flatgray/radiobutton_checked_disable.png); -} - -QGroupBox::indicator,QTreeView::indicator,QListView::indicator,QTableView::indicator{ -padding:0px 0px 0px 0px; -} - -QCheckBox::indicator,QGroupBox::indicator,QTreeView::indicator,QListView::indicator,QTableView::indicator{ -width:13px; -height:13px; -} - -QCheckBox::indicator:unchecked,QGroupBox::indicator:unchecked,QTreeView::indicator:unchecked,QListView::indicator:unchecked,QTableView::indicator:unchecked{ -image:url(:/qss/flatgray/checkbox_unchecked.png); -} - -QCheckBox::indicator:unchecked:disabled,QGroupBox::indicator:unchecked:disabled,QTreeView::indicator:unchecked:disabled,QListView::indicator:unchecked:disabled,QTableView::indicator:unchecked:disabled{ -image:url(:/qss/flatgray/checkbox_unchecked_disable.png); -} - -QCheckBox::indicator:checked,QGroupBox::indicator:checked,QTreeView::indicator:checked,QListView::indicator:checked,QTableView::indicator:checked{ -image:url(:/qss/flatgray/checkbox_checked.png); -} - -QCheckBox::indicator:checked:disabled,QGroupBox::indicator:checked:disabled,QTreeView::indicator:checked:disabled,QListView::indicator:checked:disabled,QTableView::indicator:checked:disabled{ -image:url(:/qss/flatgray/checkbox_checked_disable.png); -} - -QCheckBox::indicator:indeterminate,QGroupBox::indicator:indeterminate,QTreeView::indicator:indeterminate,QListView::indicator:indeterminate,QTableView::indicator:indeterminate{ -image:url(:/qss/flatgray/checkbox_parcial.png); -} - -QCheckBox::indicator:indeterminate:disabled,QGroupBox::indicator:indeterminate:disabled,QTreeView::indicator:indeterminate:disabled,QListView::indicator:indeterminate:disabled,QTableView::indicator:indeterminate:disabled{ -image:url(:/qss/flatgray/checkbox_parcial_disable.png); -} - -QTimeEdit::up-button,QDateEdit::up-button,QDateTimeEdit::up-button,QDoubleSpinBox::up-button,QSpinBox::up-button{ -image:url(:/qss/flatgray/add_top.png); -width:10px; -height:10px; -padding:2px 5px 0px 0px; -} - -QTimeEdit::down-button,QDateEdit::down-button,QDateTimeEdit::down-button,QDoubleSpinBox::down-button,QSpinBox::down-button{ -image:url(:/qss/flatgray/add_bottom.png); -width:10px; -height:10px; -padding:0px 5px 2px 0px; -} - -QTimeEdit::up-button:pressed,QDateEdit::up-button:pressed,QDateTimeEdit::up-button:pressed,QDoubleSpinBox::up-button:pressed,QSpinBox::up-button:pressed{ -top:-2px; -} - -QTimeEdit::down-button:pressed,QDateEdit::down-button:pressed,QDateTimeEdit::down-button:pressed,QDoubleSpinBox::down-button:pressed,QSpinBox::down-button:pressed,QSpinBox::down-button:pressed{ -bottom:-2px; -} - -QComboBox::down-arrow,QDateEdit[calendarPopup="true"]::down-arrow,QTimeEdit[calendarPopup="true"]::down-arrow,QDateTimeEdit[calendarPopup="true"]::down-arrow{ -image:url(:/qss/flatgray/add_bottom.png); -width:10px; -height:10px; -right:2px; -} - -QComboBox::drop-down,QDateEdit::drop-down,QTimeEdit::drop-down,QDateTimeEdit::drop-down{ -subcontrol-origin:padding; -subcontrol-position:top right; -width:15px; -border-left-width:0px; -border-left-style:solid; -border-top-right-radius:3px; -border-bottom-right-radius:3px; -border-left-color:#B6B6B6; -} - -QComboBox::drop-down:on{ -top:1px; -} - -QMenuBar::item{ -color:#57595B; -background-color:#E4E4E4; -margin:0px; -padding:3px 10px; -} - -QMenu,QMenuBar,QMenu:disabled,QMenuBar:disabled{ -color:#57595B; -background-color:#E4E4E4; -border:1px solid #B6B6B6; -margin:0px; -} - -QMenu::item{ -padding:3px 20px; -} - -QMenu::indicator{ -width:20px; -height:13px; -} - -QMenu::indicator::checked{ -image:url(:/qss/flatgray/menu_checked.png); -} - -QMenu::right-arrow{ -image:url(:/qss/flatgray/arrow_right.png); -width:13px; -height:13px; -padding:0px 3px 0px 0px; -} - -QMenu::item:selected,QMenuBar::item:selected{ -color:#57595B; -border:0px solid #B6B6B6; -background:#F6F6F6; -} - -QMenu::separator{ -height:1px; -background:#B6B6B6; -} - -QProgressBar{ -min-height:10px; -background:#E4E4E4; -border-radius:5px; -text-align:center; -border:1px solid #E4E4E4; -} - -QProgressBar:chunk{ -border-radius:5px; -background-color:#B6B6B6; -} - -QSlider::groove:horizontal{ -height:8px; -border-radius:4px; -background:#E4E4E4; -} - -QSlider::add-page:horizontal{ -height:8px; -border-radius:4px; -background:#E4E4E4; -} - -QSlider::sub-page:horizontal{ -height:8px; -border-radius:4px; -background:#B6B6B6; -} - -QSlider::handle:horizontal{ -width:13px; -margin-top:-3px; -margin-bottom:-3px; -border-radius:6px; -background:qradialgradient(spread:pad,cx:0.5,cy:0.5,radius:0.5,fx:0.5,fy:0.5,stop:0.6 #FFFFFF,stop:0.8 #B6B6B6); -} - -QSlider::groove:vertical{ -width:8px; -border-radius:4px; -background:#E4E4E4; -} - -QSlider::add-page:vertical{ -width:8px; -border-radius:4px; -background:#B6B6B6; -} - -QSlider::sub-page:vertical{ -width:8px; -border-radius:4px; -background:#E4E4E4; -} - -QSlider::handle:vertical{ -height:14px; -margin-left:-3px; -margin-right:-3px; -border-radius:6px; -background:qradialgradient(spread:pad,cx:0.5,cy:0.5,radius:0.5,fx:0.5,fy:0.5,stop:0.6 #FFFFFF,stop:0.8 #B6B6B6); -} - -QScrollBar:horizontal{ -background:#E4E4E4; -padding:0px; -border-radius:6px; -max-height:12px; -} - -QScrollBar::handle:horizontal{ -background:#B6B6B6; -min-width:50px; -border-radius:6px; -} - -QScrollBar::handle:horizontal:hover{ -background:#575959; -} - -QScrollBar::handle:horizontal:pressed{ -background:#575959; -} - -QScrollBar::add-page:horizontal{ -background:none; -} - -QScrollBar::sub-page:horizontal{ -background:none; -} - -QScrollBar::add-line:horizontal{ -background:none; -} - -QScrollBar::sub-line:horizontal{ -background:none; -} - -QScrollBar:vertical{ -background:#E4E4E4; -padding:0px; -border-radius:6px; -max-width:12px; -} - -QScrollBar::handle:vertical{ -background:#B6B6B6; -min-height:50px; -border-radius:6px; -} - -QScrollBar::handle:vertical:hover{ -background:#575959; -} - -QScrollBar::handle:vertical:pressed{ -background:#575959; -} - -QScrollBar::add-page:vertical{ -background:none; -} - -QScrollBar::sub-page:vertical{ -background:none; -} - -QScrollBar::add-line:vertical{ -background:none; -} - -QScrollBar::sub-line:vertical{ -background:none; -} - -QScrollArea{ -border:0px; -} - -QTreeView,QListView,QTableView,QTabWidget::pane{ -border:1px solid #B6B6B6; -selection-background-color:#F6F6F6; -selection-color:#57595B; -alternate-background-color:#F6F6F6; -gridline-color:#B6B6B6; -} - -QTreeView::branch:closed:has-children{ -margin:4px; -border-image:url(:/qss/flatgray/branch_open.png); -} - -QTreeView::branch:open:has-children{ -margin:4px; -border-image:url(:/qss/flatgray/branch_close.png); -} - -QTreeView,QListView,QTableView,QSplitter::handle,QTreeView::branch{ -background:#FFFFFF; -} - -QTableView::item:selected,QListView::item:selected,QTreeView::item:selected{ -color:#57595B; -background:#E4E4E4; -} - -QTableView::item:hover,QListView::item:hover,QTreeView::item:hover,QHeaderView,QHeaderView::section,QTableCornerButton:section{ -color:#57595B; -background:#F6F6F6; -} - -QTableView::item,QListView::item,QTreeView::item{ -padding:1px; -margin:0px; -border:0px; -} - -QHeaderView::section,QTableCornerButton:section{ -padding:3px; -margin:0px; -border:1px solid #B6B6B6; -border-left-width:0px; -border-right-width:1px; -border-top-width:0px; -border-bottom-width:1px; -} - -QTabBar::tab{ -border:1px solid #B6B6B6; -color:#57595B; -margin:0px; -background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #F6F6F6,stop:1 #F6F6F6); -} - -QTabBar::tab:selected{ -border-style:solid; -border-color:#575959; -background:#FFFFFF; -} - -QTabBar::tab:top,QTabBar::tab:bottom{ -padding:3px 8px 3px 8px; -} - -QTabBar::tab:left,QTabBar::tab:right{ -padding:8px 3px 8px 3px; -} - -QTabBar::tab:top:selected{ -border-width:2px 0px 0px 0px; -} - -QTabBar::tab:right:selected{ -border-width:0px 0px 0px 2px; -} - -QTabBar::tab:bottom:selected{ -border-width:0px 0px 2px 0px; -} - -QTabBar::tab:left:selected{ -border-width:0px 2px 0px 0px; -} - -QTabBar::tab:first:top:selected,QTabBar::tab:first:bottom:selected{ -border-left-width:1px; -border-left-color:#B6B6B6; -} - -QTabBar::tab:first:left:selected,QTabBar::tab:first:right:selected{ -border-top-width:1px; -border-top-color:#B6B6B6; -} - -QTabBar::tab:last:top:selected,QTabBar::tab:last:bottom:selected{ -border-right-width:1px; -border-right-color:#B6B6B6; -} - -QTabBar::tab:last:left:selected,QTabBar::tab:last:right:selected{ -border-bottom-width:1px; -border-bottom-color:#B6B6B6; -} - -QStatusBar::item{ -border:0px solid #E4E4E4; -border-radius:3px; -} - -QToolBox::tab,QGroupBox#gboxDevicePanel,QGroupBox#gboxDeviceTitle,QFrame#gboxDevicePanel,QFrame#gboxDeviceTitle{ -padding:3px; -border-radius:5px; -color:#57595B; -background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #E4E4E4,stop:1 #E4E4E4); -} - -QToolTip{ -border:0px solid #57595B; -padding:1px; -color:#57595B; -background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #E4E4E4,stop:1 #E4E4E4); -} - -QToolBox::tab:selected{ -background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #F6F6F6,stop:1 #F6F6F6); -} - -QPrintPreviewDialog QToolButton{ -border:0px solid #57595B; -border-radius:0px; -margin:0px; -padding:3px; -background:none; -} - -QColorDialog QPushButton,QFileDialog QPushButton{ -min-width:80px; -} - -QToolButton#qt_calendar_prevmonth{ -icon-size:0px; -min-width:20px; -image:url(:/qss/flatgray/calendar_prevmonth.png); -} - -QToolButton#qt_calendar_nextmonth{ -icon-size:0px; -min-width:20px; -image:url(:/qss/flatgray/calendar_nextmonth.png); -} - -QToolButton#qt_calendar_prevmonth,QToolButton#qt_calendar_nextmonth,QToolButton#qt_calendar_monthbutton,QToolButton#qt_calendar_yearbutton{ -border:0px solid #57595B; -border-radius:3px; -margin:3px 3px 3px 3px; -padding:3px; -background:none; -} - -QToolButton#qt_calendar_prevmonth:hover,QToolButton#qt_calendar_nextmonth:hover,QToolButton#qt_calendar_monthbutton:hover,QToolButton#qt_calendar_yearbutton:hover,QToolButton#qt_calendar_prevmonth:pressed,QToolButton#qt_calendar_nextmonth:pressed,QToolButton#qt_calendar_monthbutton:pressed,QToolButton#qt_calendar_yearbutton:pressed{ -border:1px solid #B6B6B6; -} - -QCalendarWidget QSpinBox#qt_calendar_yearedit{ -margin:2px; -} - -QCalendarWidget QToolButton::menu-indicator{ -image:None; -} - -QCalendarWidget QTableView{ -border-width:0px; -} - -QCalendarWidget QWidget#qt_calendar_navigationbar{ -border:1px solid #B6B6B6; -border-width:1px 1px 0px 1px; -background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #E4E4E4,stop:1 #E4E4E4); -} - -QTableView[model="true"]::item{ -padding:0px; -margin:0px; -} - -QTableView QLineEdit,QTableView QComboBox,QTableView QSpinBox,QTableView QDoubleSpinBox,QTableView QDateEdit,QTableView QTimeEdit,QTableView QDateTimeEdit{ -border-width:0px; -border-radius:0px; -} - -QTableView QLineEdit:focus,QTableView QComboBox:focus,QTableView QSpinBox:focus,QTableView QDoubleSpinBox:focus,QTableView QDateEdit:focus,QTableView QTimeEdit:focus,QTableView QDateTimeEdit:focus{ -border-width:0px; -border-radius:0px; -} - -QLineEdit,QTextEdit,QPlainTextEdit,QSpinBox,QDoubleSpinBox,QComboBox,QDateEdit,QTimeEdit,QDateTimeEdit{ -background:#FFFFFF; -} - -QTabWidget::pane:top{top:-1px;} -QTabWidget::pane:bottom{bottom:-1px;} -QTabWidget::pane:left{right:-1px;} -QTabWidget::pane:right{left:-1px;} - -QDialog,QDial,#QUIWidgetMain{ -background-color:#FFFFFF; -color:#57595B; -} - -QDialogButtonBox>QPushButton{ -min-width:50px; -} - -QListView[noborder="true"],QTreeView[noborder="true"],QTabWidget[noborder="true"]::pane{ -border-width:0px; -} - -QToolBar>*,QStatusBar>*{ -margin:2px; -} - -*:disabled,QMenu::item:disabled,QTabBar:tab:disabled,QHeaderView::section:disabled{ -background:#FFFFFF; -border-color:#E4E4E4; -color:#B6B6B6; -} - -/*TextColor:#57595B*/ -/*PanelColor:#FFFFFF*/ -/*BorderColor:#B6B6B6*/ -/*NormalColorStart:#E4E4E4*/ -/*NormalColorEnd:#E4E4E4*/ -/*DarkColorStart:#F6F6F6*/ -/*DarkColorEnd:#F6F6F6*/ -/*HighColor:#575959*/ \ No newline at end of file diff --git a/res/theme/feiyangqingyun/qss/flatgray/add_bottom.png b/res/theme/feiyangqingyun/qss/flatgray/add_bottom.png deleted file mode 100644 index 868e687..0000000 Binary files a/res/theme/feiyangqingyun/qss/flatgray/add_bottom.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/flatgray/add_left.png b/res/theme/feiyangqingyun/qss/flatgray/add_left.png deleted file mode 100644 index d9d5127..0000000 Binary files a/res/theme/feiyangqingyun/qss/flatgray/add_left.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/flatgray/add_right.png b/res/theme/feiyangqingyun/qss/flatgray/add_right.png deleted file mode 100644 index be8dd1a..0000000 Binary files a/res/theme/feiyangqingyun/qss/flatgray/add_right.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/flatgray/add_top.png b/res/theme/feiyangqingyun/qss/flatgray/add_top.png deleted file mode 100644 index ef55ce1..0000000 Binary files a/res/theme/feiyangqingyun/qss/flatgray/add_top.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/flatgray/arrow_bottom.png b/res/theme/feiyangqingyun/qss/flatgray/arrow_bottom.png deleted file mode 100644 index 37307b7..0000000 Binary files a/res/theme/feiyangqingyun/qss/flatgray/arrow_bottom.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/flatgray/arrow_left.png b/res/theme/feiyangqingyun/qss/flatgray/arrow_left.png deleted file mode 100644 index aa4312b..0000000 Binary files a/res/theme/feiyangqingyun/qss/flatgray/arrow_left.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/flatgray/arrow_right.png b/res/theme/feiyangqingyun/qss/flatgray/arrow_right.png deleted file mode 100644 index 4db5efa..0000000 Binary files a/res/theme/feiyangqingyun/qss/flatgray/arrow_right.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/flatgray/arrow_top.png b/res/theme/feiyangqingyun/qss/flatgray/arrow_top.png deleted file mode 100644 index 0da1cad..0000000 Binary files a/res/theme/feiyangqingyun/qss/flatgray/arrow_top.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/flatgray/branch_close.png b/res/theme/feiyangqingyun/qss/flatgray/branch_close.png deleted file mode 100644 index f5b6d34..0000000 Binary files a/res/theme/feiyangqingyun/qss/flatgray/branch_close.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/flatgray/branch_open.png b/res/theme/feiyangqingyun/qss/flatgray/branch_open.png deleted file mode 100644 index 6392c13..0000000 Binary files a/res/theme/feiyangqingyun/qss/flatgray/branch_open.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/flatgray/calendar_nextmonth.png b/res/theme/feiyangqingyun/qss/flatgray/calendar_nextmonth.png deleted file mode 100644 index 6cb40d7..0000000 Binary files a/res/theme/feiyangqingyun/qss/flatgray/calendar_nextmonth.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/flatgray/calendar_prevmonth.png b/res/theme/feiyangqingyun/qss/flatgray/calendar_prevmonth.png deleted file mode 100644 index 8a17d0f..0000000 Binary files a/res/theme/feiyangqingyun/qss/flatgray/calendar_prevmonth.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/flatgray/checkbox_checked.png b/res/theme/feiyangqingyun/qss/flatgray/checkbox_checked.png deleted file mode 100644 index 8808382..0000000 Binary files a/res/theme/feiyangqingyun/qss/flatgray/checkbox_checked.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/flatgray/checkbox_checked_disable.png b/res/theme/feiyangqingyun/qss/flatgray/checkbox_checked_disable.png deleted file mode 100644 index 9aa0a10..0000000 Binary files a/res/theme/feiyangqingyun/qss/flatgray/checkbox_checked_disable.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/flatgray/checkbox_parcial.png b/res/theme/feiyangqingyun/qss/flatgray/checkbox_parcial.png deleted file mode 100644 index 97376f3..0000000 Binary files a/res/theme/feiyangqingyun/qss/flatgray/checkbox_parcial.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/flatgray/checkbox_parcial_disable.png b/res/theme/feiyangqingyun/qss/flatgray/checkbox_parcial_disable.png deleted file mode 100644 index b9b286f..0000000 Binary files a/res/theme/feiyangqingyun/qss/flatgray/checkbox_parcial_disable.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/flatgray/checkbox_unchecked.png b/res/theme/feiyangqingyun/qss/flatgray/checkbox_unchecked.png deleted file mode 100644 index 50c25e2..0000000 Binary files a/res/theme/feiyangqingyun/qss/flatgray/checkbox_unchecked.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/flatgray/checkbox_unchecked_disable.png b/res/theme/feiyangqingyun/qss/flatgray/checkbox_unchecked_disable.png deleted file mode 100644 index 7c4c7db..0000000 Binary files a/res/theme/feiyangqingyun/qss/flatgray/checkbox_unchecked_disable.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/flatgray/menu_checked.png b/res/theme/feiyangqingyun/qss/flatgray/menu_checked.png deleted file mode 100644 index 6a1c729..0000000 Binary files a/res/theme/feiyangqingyun/qss/flatgray/menu_checked.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/flatgray/radiobutton_checked.png b/res/theme/feiyangqingyun/qss/flatgray/radiobutton_checked.png deleted file mode 100644 index 513a41e..0000000 Binary files a/res/theme/feiyangqingyun/qss/flatgray/radiobutton_checked.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/flatgray/radiobutton_checked_disable.png b/res/theme/feiyangqingyun/qss/flatgray/radiobutton_checked_disable.png deleted file mode 100644 index 8d16af5..0000000 Binary files a/res/theme/feiyangqingyun/qss/flatgray/radiobutton_checked_disable.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/flatgray/radiobutton_unchecked.png b/res/theme/feiyangqingyun/qss/flatgray/radiobutton_unchecked.png deleted file mode 100644 index 8ef34fb..0000000 Binary files a/res/theme/feiyangqingyun/qss/flatgray/radiobutton_unchecked.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/flatgray/radiobutton_unchecked_disable.png b/res/theme/feiyangqingyun/qss/flatgray/radiobutton_unchecked_disable.png deleted file mode 100644 index f70c364..0000000 Binary files a/res/theme/feiyangqingyun/qss/flatgray/radiobutton_unchecked_disable.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/lightblue.css b/res/theme/feiyangqingyun/qss/lightblue.css deleted file mode 100644 index 590189b..0000000 --- a/res/theme/feiyangqingyun/qss/lightblue.css +++ /dev/null @@ -1,679 +0,0 @@ -QPalette{background:#EAF7FF;}*{outline:0px;color:#386487;} - -QGraphicsView{ -border:1px solid #C0DCF2; -qproperty-backgroundBrush:#EAF7FF; -} - -QWidget[form="true"],QLabel[frameShape="1"],QGraphicsView{ -border:1px solid #C0DCF2; -border-radius:0px; -} - -QWidget[form="bottom"]{ -background:#DEF0FE; -} - -QWidget[form="bottom"] .QFrame{ -border:1px solid #386487; -} - -QWidget[form="bottom"] QLabel,QWidget[form="title"] QLabel{ -border-radius:0px; -color:#386487; -background:none; -border-style:none; -} - -QWidget[form="title"],QWidget[nav="left"],QWidget[nav="top"] QAbstractButton{ -border-style:none; -border-radius:0px; -padding:5px; -color:#386487; -background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #DEF0FE,stop:1 #C0DEF6); -} - -QWidget[nav="top"] QAbstractButton:hover,QWidget[nav="top"] QAbstractButton:pressed,QWidget[nav="top"] QAbstractButton:checked{ -border-style:solid; -border-width:0px 0px 2px 0px; -padding:4px 4px 2px 4px; -border-color:#386488; -background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #F2F9FF,stop:1 #DAEFFF); -} - -QWidget[nav="left"] QAbstractButton{ -border-radius:0px; -color:#386487; -background:none; -border-style:none; -} - -QWidget[nav="left"] QAbstractButton:hover{ -color:#FFFFFF; -background-color:#386488; -} - -QWidget[nav="left"] QAbstractButton:checked,QWidget[nav="left"] QAbstractButton:pressed{ -color:#386487; -border-style:solid; -border-width:0px 0px 0px 2px; -padding:4px 4px 4px 2px; -border-color:#386488; -background-color:#EAF7FF; -} - -QWidget[video="true"] QLabel{ -color:#386487; -border:1px solid #C0DCF2; -background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #DEF0FE,stop:1 #C0DEF6); -} - -QWidget[video="true"] QLabel:focus{ -border:1px solid #386488; -background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #F2F9FF,stop:1 #DAEFFF); -} - -QLineEdit:read-only{ -background-color:#DEF0FE; -} - -QLineEdit,QTextEdit,QPlainTextEdit,QSpinBox,QDoubleSpinBox,QComboBox,QDateEdit,QTimeEdit,QDateTimeEdit{ -border:1px solid #C0DCF2; -border-radius:3px; -padding:2px; -background:none; -selection-background-color:#386488; -selection-color:#FFFFFF; -} - -QLineEdit:focus,QTextEdit:focus,QPlainTextEdit:focus,QSpinBox:focus,QDoubleSpinBox:focus,QComboBox:focus,QDateEdit:focus,QTimeEdit:focus,QDateTimeEdit:focus,QLineEdit:hover,QTextEdit:hover,QPlainTextEdit:hover,QSpinBox:hover,QDoubleSpinBox:hover,QComboBox:hover,QDateEdit:hover,QTimeEdit:hover,QDateTimeEdit:hover{ -border:1px solid #C0DCF2; -} - -QLineEdit[echoMode="2"]{ -lineedit-password-character:9679; -} - -.QFrame{ -border:1px solid #C0DCF2; -border-radius:3px; -} - -.QGroupBox{ -border:1px solid #C0DCF2; -border-radius:5px; -margin-top:3ex; -} - -.QGroupBox::title{ -subcontrol-origin:margin; -position:relative; -left:10px; -} - -.QPushButton,.QToolButton{ -border-style:none; -border:1px solid #C0DCF2; -color:#386487; -padding:5px; -min-height:15px; -border-radius:5px; -background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #DEF0FE,stop:1 #C0DEF6); -} - -.QPushButton:hover,.QToolButton:hover{ -background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #F2F9FF,stop:1 #DAEFFF); -} - -.QPushButton:pressed,.QToolButton:pressed{ -background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #DEF0FE,stop:1 #C0DEF6); -} - -.QToolButton::menu-indicator{ -image:None; -} - -QToolButton#btnMenu,QPushButton#btnMenu_Min,QPushButton#btnMenu_Max,QPushButton#btnMenu_Close{ -border-radius:3px; -color:#386487; -padding:3px; -margin:0px; -background:none; -border-style:none; -} - -QToolButton#btnMenu:hover,QPushButton#btnMenu_Min:hover,QPushButton#btnMenu_Max:hover{ -color:#FFFFFF; -margin:1px 1px 2px 1px; -background-color:rgba(51,127,209,230); -} - -QPushButton#btnMenu_Close:hover{ -color:#FFFFFF; -margin:1px 1px 2px 1px; -background-color:rgba(238,0,0,128); -} - -QRadioButton::indicator{ -width:15px; -height:15px; -} - -QRadioButton::indicator::unchecked{ -image:url(:/qss/lightblue/radiobutton_unchecked.png); -} - -QRadioButton::indicator::unchecked:disabled{ -image:url(:/qss/lightblue/radiobutton_unchecked_disable.png); -} - -QRadioButton::indicator::checked{ -image:url(:/qss/lightblue/radiobutton_checked.png); -} - -QRadioButton::indicator::checked:disabled{ -image:url(:/qss/lightblue/radiobutton_checked_disable.png); -} - -QGroupBox::indicator,QTreeView::indicator,QListView::indicator,QTableView::indicator{ -padding:0px 0px 0px 0px; -} - -QCheckBox::indicator,QGroupBox::indicator,QTreeView::indicator,QListView::indicator,QTableView::indicator{ -width:13px; -height:13px; -} - -QCheckBox::indicator:unchecked,QGroupBox::indicator:unchecked,QTreeView::indicator:unchecked,QListView::indicator:unchecked,QTableView::indicator:unchecked{ -image:url(:/qss/lightblue/checkbox_unchecked.png); -} - -QCheckBox::indicator:unchecked:disabled,QGroupBox::indicator:unchecked:disabled,QTreeView::indicator:unchecked:disabled,QListView::indicator:unchecked:disabled,QTableView::indicator:unchecked:disabled{ -image:url(:/qss/lightblue/checkbox_unchecked_disable.png); -} - -QCheckBox::indicator:checked,QGroupBox::indicator:checked,QTreeView::indicator:checked,QListView::indicator:checked,QTableView::indicator:checked{ -image:url(:/qss/lightblue/checkbox_checked.png); -} - -QCheckBox::indicator:checked:disabled,QGroupBox::indicator:checked:disabled,QTreeView::indicator:checked:disabled,QListView::indicator:checked:disabled,QTableView::indicator:checked:disabled{ -image:url(:/qss/lightblue/checkbox_checked_disable.png); -} - -QCheckBox::indicator:indeterminate,QGroupBox::indicator:indeterminate,QTreeView::indicator:indeterminate,QListView::indicator:indeterminate,QTableView::indicator:indeterminate{ -image:url(:/qss/lightblue/checkbox_parcial.png); -} - -QCheckBox::indicator:indeterminate:disabled,QGroupBox::indicator:indeterminate:disabled,QTreeView::indicator:indeterminate:disabled,QListView::indicator:indeterminate:disabled,QTableView::indicator:indeterminate:disabled{ -image:url(:/qss/lightblue/checkbox_parcial_disable.png); -} - -QTimeEdit::up-button,QDateEdit::up-button,QDateTimeEdit::up-button,QDoubleSpinBox::up-button,QSpinBox::up-button{ -image:url(:/qss/lightblue/add_top.png); -width:10px; -height:10px; -padding:2px 5px 0px 0px; -} - -QTimeEdit::down-button,QDateEdit::down-button,QDateTimeEdit::down-button,QDoubleSpinBox::down-button,QSpinBox::down-button{ -image:url(:/qss/lightblue/add_bottom.png); -width:10px; -height:10px; -padding:0px 5px 2px 0px; -} - -QTimeEdit::up-button:pressed,QDateEdit::up-button:pressed,QDateTimeEdit::up-button:pressed,QDoubleSpinBox::up-button:pressed,QSpinBox::up-button:pressed{ -top:-2px; -} - -QTimeEdit::down-button:pressed,QDateEdit::down-button:pressed,QDateTimeEdit::down-button:pressed,QDoubleSpinBox::down-button:pressed,QSpinBox::down-button:pressed,QSpinBox::down-button:pressed{ -bottom:-2px; -} - -QComboBox::down-arrow,QDateEdit[calendarPopup="true"]::down-arrow,QTimeEdit[calendarPopup="true"]::down-arrow,QDateTimeEdit[calendarPopup="true"]::down-arrow{ -image:url(:/qss/lightblue/add_bottom.png); -width:10px; -height:10px; -right:2px; -} - -QComboBox::drop-down,QDateEdit::drop-down,QTimeEdit::drop-down,QDateTimeEdit::drop-down{ -subcontrol-origin:padding; -subcontrol-position:top right; -width:15px; -border-left-width:0px; -border-left-style:solid; -border-top-right-radius:3px; -border-bottom-right-radius:3px; -border-left-color:#C0DCF2; -} - -QComboBox::drop-down:on{ -top:1px; -} - -QMenuBar::item{ -color:#386487; -background-color:#DEF0FE; -margin:0px; -padding:3px 10px; -} - -QMenu,QMenuBar,QMenu:disabled,QMenuBar:disabled{ -color:#386487; -background-color:#DEF0FE; -border:1px solid #C0DCF2; -margin:0px; -} - -QMenu::item{ -padding:3px 20px; -} - -QMenu::indicator{ -width:20px; -height:13px; -} - -QMenu::indicator::checked{ -image:url(:/qss/lightblue/menu_checked.png); -} - -QMenu::right-arrow{ -image:url(:/qss/lightblue/arrow_right.png); -width:13px; -height:13px; -padding:0px 3px 0px 0px; -} - -QMenu::item:selected,QMenuBar::item:selected{ -color:#386487; -border:0px solid #C0DCF2; -background:#F2F9FF; -} - -QMenu::separator{ -height:1px; -background:#C0DCF2; -} - -QProgressBar{ -min-height:10px; -background:#DEF0FE; -border-radius:5px; -text-align:center; -border:1px solid #DEF0FE; -} - -QProgressBar:chunk{ -border-radius:5px; -background-color:#C0DCF2; -} - -QSlider::groove:horizontal{ -height:8px; -border-radius:4px; -background:#DEF0FE; -} - -QSlider::add-page:horizontal{ -height:8px; -border-radius:4px; -background:#DEF0FE; -} - -QSlider::sub-page:horizontal{ -height:8px; -border-radius:4px; -background:#C0DCF2; -} - -QSlider::handle:horizontal{ -width:13px; -margin-top:-3px; -margin-bottom:-3px; -border-radius:6px; -background:qradialgradient(spread:pad,cx:0.5,cy:0.5,radius:0.5,fx:0.5,fy:0.5,stop:0.6 #EAF7FF,stop:0.8 #C0DCF2); -} - -QSlider::groove:vertical{ -width:8px; -border-radius:4px; -background:#DEF0FE; -} - -QSlider::add-page:vertical{ -width:8px; -border-radius:4px; -background:#C0DCF2; -} - -QSlider::sub-page:vertical{ -width:8px; -border-radius:4px; -background:#DEF0FE; -} - -QSlider::handle:vertical{ -height:14px; -margin-left:-3px; -margin-right:-3px; -border-radius:6px; -background:qradialgradient(spread:pad,cx:0.5,cy:0.5,radius:0.5,fx:0.5,fy:0.5,stop:0.6 #EAF7FF,stop:0.8 #C0DCF2); -} - -QScrollBar:horizontal{ -background:#DEF0FE; -padding:0px; -border-radius:6px; -max-height:12px; -} - -QScrollBar::handle:horizontal{ -background:#C0DCF2; -min-width:50px; -border-radius:6px; -} - -QScrollBar::handle:horizontal:hover{ -background:#386488; -} - -QScrollBar::handle:horizontal:pressed{ -background:#386488; -} - -QScrollBar::add-page:horizontal{ -background:none; -} - -QScrollBar::sub-page:horizontal{ -background:none; -} - -QScrollBar::add-line:horizontal{ -background:none; -} - -QScrollBar::sub-line:horizontal{ -background:none; -} - -QScrollBar:vertical{ -background:#DEF0FE; -padding:0px; -border-radius:6px; -max-width:12px; -} - -QScrollBar::handle:vertical{ -background:#C0DCF2; -min-height:50px; -border-radius:6px; -} - -QScrollBar::handle:vertical:hover{ -background:#386488; -} - -QScrollBar::handle:vertical:pressed{ -background:#386488; -} - -QScrollBar::add-page:vertical{ -background:none; -} - -QScrollBar::sub-page:vertical{ -background:none; -} - -QScrollBar::add-line:vertical{ -background:none; -} - -QScrollBar::sub-line:vertical{ -background:none; -} - -QScrollArea{ -border:0px; -} - -QTreeView,QListView,QTableView,QTabWidget::pane{ -border:1px solid #C0DCF2; -selection-background-color:#F2F9FF; -selection-color:#386487; -alternate-background-color:#DAEFFF; -gridline-color:#C0DCF2; -} - -QTreeView::branch:closed:has-children{ -margin:4px; -border-image:url(:/qss/lightblue/branch_open.png); -} - -QTreeView::branch:open:has-children{ -margin:4px; -border-image:url(:/qss/lightblue/branch_close.png); -} - -QTreeView,QListView,QTableView,QSplitter::handle,QTreeView::branch{ -background:#EAF7FF; -} - -QTableView::item:selected,QListView::item:selected,QTreeView::item:selected{ -color:#386487; -background:#C0DEF6; -} - -QTableView::item:hover,QListView::item:hover,QTreeView::item:hover,QHeaderView,QHeaderView::section,QTableCornerButton:section{ -color:#386487; -background:#DAEFFF; -} - -QTableView::item,QListView::item,QTreeView::item{ -padding:1px; -margin:0px; -border:0px; -} - -QHeaderView::section,QTableCornerButton:section{ -padding:3px; -margin:0px; -border:1px solid #C0DCF2; -border-left-width:0px; -border-right-width:1px; -border-top-width:0px; -border-bottom-width:1px; -} - -QTabBar::tab{ -border:1px solid #C0DCF2; -color:#386487; -margin:0px; -background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #F2F9FF,stop:1 #DAEFFF); -} - -QTabBar::tab:selected{ -border-style:solid; -border-color:#386488; -background:#EAF7FF; -} - -QTabBar::tab:top,QTabBar::tab:bottom{ -padding:3px 8px 3px 8px; -} - -QTabBar::tab:left,QTabBar::tab:right{ -padding:8px 3px 8px 3px; -} - -QTabBar::tab:top:selected{ -border-width:2px 0px 0px 0px; -} - -QTabBar::tab:right:selected{ -border-width:0px 0px 0px 2px; -} - -QTabBar::tab:bottom:selected{ -border-width:0px 0px 2px 0px; -} - -QTabBar::tab:left:selected{ -border-width:0px 2px 0px 0px; -} - -QTabBar::tab:first:top:selected,QTabBar::tab:first:bottom:selected{ -border-left-width:1px; -border-left-color:#C0DCF2; -} - -QTabBar::tab:first:left:selected,QTabBar::tab:first:right:selected{ -border-top-width:1px; -border-top-color:#C0DCF2; -} - -QTabBar::tab:last:top:selected,QTabBar::tab:last:bottom:selected{ -border-right-width:1px; -border-right-color:#C0DCF2; -} - -QTabBar::tab:last:left:selected,QTabBar::tab:last:right:selected{ -border-bottom-width:1px; -border-bottom-color:#C0DCF2; -} - -QStatusBar::item{ -border:0px solid #DEF0FE; -border-radius:3px; -} - -QToolBox::tab,QGroupBox#gboxDevicePanel,QGroupBox#gboxDeviceTitle,QFrame#gboxDevicePanel,QFrame#gboxDeviceTitle{ -padding:3px; -border-radius:5px; -color:#386487; -background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #DEF0FE,stop:1 #C0DEF6); -} - -QToolTip{ -border:0px solid #386487; -padding:1px; -color:#386487; -background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #DEF0FE,stop:1 #C0DEF6); -} - -QToolBox::tab:selected{ -background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #F2F9FF,stop:1 #DAEFFF); -} - -QPrintPreviewDialog QToolButton{ -border:0px solid #386487; -border-radius:0px; -margin:0px; -padding:3px; -background:none; -} - -QColorDialog QPushButton,QFileDialog QPushButton{ -min-width:80px; -} - -QToolButton#qt_calendar_prevmonth{ -icon-size:0px; -min-width:20px; -image:url(:/qss/lightblue/calendar_prevmonth.png); -} - -QToolButton#qt_calendar_nextmonth{ -icon-size:0px; -min-width:20px; -image:url(:/qss/lightblue/calendar_nextmonth.png); -} - -QToolButton#qt_calendar_prevmonth,QToolButton#qt_calendar_nextmonth,QToolButton#qt_calendar_monthbutton,QToolButton#qt_calendar_yearbutton{ -border:0px solid #386487; -border-radius:3px; -margin:3px 3px 3px 3px; -padding:3px; -background:none; -} - -QToolButton#qt_calendar_prevmonth:hover,QToolButton#qt_calendar_nextmonth:hover,QToolButton#qt_calendar_monthbutton:hover,QToolButton#qt_calendar_yearbutton:hover,QToolButton#qt_calendar_prevmonth:pressed,QToolButton#qt_calendar_nextmonth:pressed,QToolButton#qt_calendar_monthbutton:pressed,QToolButton#qt_calendar_yearbutton:pressed{ -border:1px solid #C0DCF2; -} - -QCalendarWidget QSpinBox#qt_calendar_yearedit{ -margin:2px; -} - -QCalendarWidget QToolButton::menu-indicator{ -image:None; -} - -QCalendarWidget QTableView{ -border-width:0px; -} - -QCalendarWidget QWidget#qt_calendar_navigationbar{ -border:1px solid #C0DCF2; -border-width:1px 1px 0px 1px; -background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #DEF0FE,stop:1 #C0DEF6); -} - -QTableView[model="true"]::item{ -padding:0px; -margin:0px; -} - -QTableView QLineEdit,QTableView QComboBox,QTableView QSpinBox,QTableView QDoubleSpinBox,QTableView QDateEdit,QTableView QTimeEdit,QTableView QDateTimeEdit{ -border-width:0px; -border-radius:0px; -} - -QTableView QLineEdit:focus,QTableView QComboBox:focus,QTableView QSpinBox:focus,QTableView QDoubleSpinBox:focus,QTableView QDateEdit:focus,QTableView QTimeEdit:focus,QTableView QDateTimeEdit:focus{ -border-width:0px; -border-radius:0px; -} - -QLineEdit,QTextEdit,QPlainTextEdit,QSpinBox,QDoubleSpinBox,QComboBox,QDateEdit,QTimeEdit,QDateTimeEdit{ -background:#EAF7FF; -} - -QTabWidget::pane:top{top:-1px;} -QTabWidget::pane:bottom{bottom:-1px;} -QTabWidget::pane:left{right:-1px;} -QTabWidget::pane:right{left:-1px;} - -QDialog,QDial,#QUIWidgetMain{ -background-color:#EAF7FF; -color:#386487; -} - -QDialogButtonBox>QPushButton{ -min-width:50px; -} - -QListView[noborder="true"],QTreeView[noborder="true"],QTabWidget[noborder="true"]::pane{ -border-width:0px; -} - -QToolBar>*,QStatusBar>*{ -margin:2px; -} - -*:disabled,QMenu::item:disabled,QTabBar:tab:disabled,QHeaderView::section:disabled{ -background:#EAF7FF; -border-color:#DEF0FE; -color:#C0DCF2; -} - -/*TextColor:#386487*/ -/*PanelColor:#EAF7FF*/ -/*BorderColor:#C0DCF2*/ -/*NormalColorStart:#DEF0FE*/ -/*NormalColorEnd:#C0DEF6*/ -/*DarkColorStart:#F2F9FF*/ -/*DarkColorEnd:#DAEFFF*/ -/*HighColor:#386488*/ \ No newline at end of file diff --git a/res/theme/feiyangqingyun/qss/lightblue/add_bottom.png b/res/theme/feiyangqingyun/qss/lightblue/add_bottom.png deleted file mode 100644 index 99eadb9..0000000 Binary files a/res/theme/feiyangqingyun/qss/lightblue/add_bottom.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/lightblue/add_left.png b/res/theme/feiyangqingyun/qss/lightblue/add_left.png deleted file mode 100644 index a7329d3..0000000 Binary files a/res/theme/feiyangqingyun/qss/lightblue/add_left.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/lightblue/add_right.png b/res/theme/feiyangqingyun/qss/lightblue/add_right.png deleted file mode 100644 index 0c0ef6f..0000000 Binary files a/res/theme/feiyangqingyun/qss/lightblue/add_right.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/lightblue/add_top.png b/res/theme/feiyangqingyun/qss/lightblue/add_top.png deleted file mode 100644 index 911f5b4..0000000 Binary files a/res/theme/feiyangqingyun/qss/lightblue/add_top.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/lightblue/arrow_bottom.png b/res/theme/feiyangqingyun/qss/lightblue/arrow_bottom.png deleted file mode 100644 index 6dc9f23..0000000 Binary files a/res/theme/feiyangqingyun/qss/lightblue/arrow_bottom.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/lightblue/arrow_left.png b/res/theme/feiyangqingyun/qss/lightblue/arrow_left.png deleted file mode 100644 index 87171e9..0000000 Binary files a/res/theme/feiyangqingyun/qss/lightblue/arrow_left.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/lightblue/arrow_right.png b/res/theme/feiyangqingyun/qss/lightblue/arrow_right.png deleted file mode 100644 index 604def6..0000000 Binary files a/res/theme/feiyangqingyun/qss/lightblue/arrow_right.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/lightblue/arrow_top.png b/res/theme/feiyangqingyun/qss/lightblue/arrow_top.png deleted file mode 100644 index 3c02231..0000000 Binary files a/res/theme/feiyangqingyun/qss/lightblue/arrow_top.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/lightblue/branch_close.png b/res/theme/feiyangqingyun/qss/lightblue/branch_close.png deleted file mode 100644 index 73492b3..0000000 Binary files a/res/theme/feiyangqingyun/qss/lightblue/branch_close.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/lightblue/branch_open.png b/res/theme/feiyangqingyun/qss/lightblue/branch_open.png deleted file mode 100644 index 9abd65c..0000000 Binary files a/res/theme/feiyangqingyun/qss/lightblue/branch_open.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/lightblue/calendar_nextmonth.png b/res/theme/feiyangqingyun/qss/lightblue/calendar_nextmonth.png deleted file mode 100644 index 36a453b..0000000 Binary files a/res/theme/feiyangqingyun/qss/lightblue/calendar_nextmonth.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/lightblue/calendar_prevmonth.png b/res/theme/feiyangqingyun/qss/lightblue/calendar_prevmonth.png deleted file mode 100644 index cce673f..0000000 Binary files a/res/theme/feiyangqingyun/qss/lightblue/calendar_prevmonth.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/lightblue/checkbox_checked.png b/res/theme/feiyangqingyun/qss/lightblue/checkbox_checked.png deleted file mode 100644 index 524d243..0000000 Binary files a/res/theme/feiyangqingyun/qss/lightblue/checkbox_checked.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/lightblue/checkbox_checked_disable.png b/res/theme/feiyangqingyun/qss/lightblue/checkbox_checked_disable.png deleted file mode 100644 index de9ece8..0000000 Binary files a/res/theme/feiyangqingyun/qss/lightblue/checkbox_checked_disable.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/lightblue/checkbox_parcial.png b/res/theme/feiyangqingyun/qss/lightblue/checkbox_parcial.png deleted file mode 100644 index 1990ead..0000000 Binary files a/res/theme/feiyangqingyun/qss/lightblue/checkbox_parcial.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/lightblue/checkbox_parcial_disable.png b/res/theme/feiyangqingyun/qss/lightblue/checkbox_parcial_disable.png deleted file mode 100644 index cdd3779..0000000 Binary files a/res/theme/feiyangqingyun/qss/lightblue/checkbox_parcial_disable.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/lightblue/checkbox_unchecked.png b/res/theme/feiyangqingyun/qss/lightblue/checkbox_unchecked.png deleted file mode 100644 index 0f766a4..0000000 Binary files a/res/theme/feiyangqingyun/qss/lightblue/checkbox_unchecked.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/lightblue/checkbox_unchecked_disable.png b/res/theme/feiyangqingyun/qss/lightblue/checkbox_unchecked_disable.png deleted file mode 100644 index 25c0cdf..0000000 Binary files a/res/theme/feiyangqingyun/qss/lightblue/checkbox_unchecked_disable.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/lightblue/menu_checked.png b/res/theme/feiyangqingyun/qss/lightblue/menu_checked.png deleted file mode 100644 index bb52701..0000000 Binary files a/res/theme/feiyangqingyun/qss/lightblue/menu_checked.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/lightblue/radiobutton_checked.png b/res/theme/feiyangqingyun/qss/lightblue/radiobutton_checked.png deleted file mode 100644 index cd6561d..0000000 Binary files a/res/theme/feiyangqingyun/qss/lightblue/radiobutton_checked.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/lightblue/radiobutton_checked_disable.png b/res/theme/feiyangqingyun/qss/lightblue/radiobutton_checked_disable.png deleted file mode 100644 index 27a6896..0000000 Binary files a/res/theme/feiyangqingyun/qss/lightblue/radiobutton_checked_disable.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/lightblue/radiobutton_unchecked.png b/res/theme/feiyangqingyun/qss/lightblue/radiobutton_unchecked.png deleted file mode 100644 index 8f0b4fc..0000000 Binary files a/res/theme/feiyangqingyun/qss/lightblue/radiobutton_unchecked.png and /dev/null differ diff --git a/res/theme/feiyangqingyun/qss/lightblue/radiobutton_unchecked_disable.png b/res/theme/feiyangqingyun/qss/lightblue/radiobutton_unchecked_disable.png deleted file mode 100644 index 57c0eb3..0000000 Binary files a/res/theme/feiyangqingyun/qss/lightblue/radiobutton_unchecked_disable.png and /dev/null differ diff --git a/res/vpn/sing-box-vpn.json b/res/vpn/sing-box-vpn.json deleted file mode 100644 index eb8f9a8..0000000 --- a/res/vpn/sing-box-vpn.json +++ /dev/null @@ -1,152 +0,0 @@ -{ - "log": { - "level": "info" - }, - "dns": { - "fakeip": { - "enabled": true, - "inet4_range": "198.18.0.0/15", - "inet6_range": "fc00::/18" - }, - "servers": [ - { - "tag": "dns-remote", - "address": "8.8.8.8", - "detour": "neko-socks" - }, - { - "tag": "dns-direct", - "address": "%DNS_ADDRESS%", - "detour": "direct" - }, - { - "address": "fakeip", - "tag": "dns-fake" - }, - { - "address": "rcode://success", - "tag": "dns-block" - } - ], - "rules": [ - { - "query_type": [ - 32, - 33 - ], - "server": "dns-block" - }, - { - "domain_suffix": [ - ".lan" - ], - "server": "dns-block" - }, - { - "process_name": [ - "nekoray_core", - "nekoray_core.exe", - "nekobox_core", - "nekobox_core.exe" - ], - "server": "dns-direct" - }, - { - "inbound": "%FAKE_DNS_INBOUND%", - "server": "dns-fake" - } - ] - }, - "inbounds": [ - { - "type": "tun", - "tag": "tun-in", - "interface_name": "%TUN_NAME%", - "inet4_address": "172.19.0.1/28", - //%IPV6_ADDRESS% - "mtu": %MTU%, - "auto_route": true, - "strict_route": %STRICT_ROUTE%, - "stack": "%STACK%", - "endpoint_independent_nat": true, - "sniff": false - } - ], - "outbounds": [ - { - "type": "socks", - "tag": "neko-socks", - "udp_fragment": true, - //%SOCKS_USER_PASS% - "server": "127.0.0.1", - "server_port": %PORT% - }, - { - "type": "block", - "tag": "block" - }, - { - "type": "direct", - "tag": "direct" - }, - { - "type": "dns", - "tag": "dns-out" - } - ], - "route": { - "final": "%FINAL_OUT%", - "auto_detect_interface": true, - "rules": [ - { - "network": "udp", - "port": [ - 135, - 137, - 138, - 139, - 5353 - ], - "outbound": "block" - }, - { - "ip_cidr": [ - "224.0.0.0/3", - "ff00::/8" - ], - "outbound": "block" - }, - { - "source_ip_cidr": [ - "224.0.0.0/3", - "ff00::/8" - ], - "outbound": "block" - }, - { - "port": 53, - "process_name": [ - "nekoray_core", - "nekoray_core.exe" - ], - "outbound": "dns-out" - }, - { - "process_name": [ - "nekoray_core", - "nekoray_core.exe", - "nekobox_core", - "nekobox_core.exe" - ], - "outbound": "direct" - } - //%PROCESS_NAME_RULE% - //%CIDR_RULE% - , - { - "port": 53, - "outbound": "dns-out" - } - ] - } -} \ No newline at end of file diff --git a/res/vpn/vpn-run-root.sh b/res/vpn/vpn-run-root.sh deleted file mode 100755 index d0c79ed..0000000 --- a/res/vpn/vpn-run-root.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/sh -set -e -set -x - -if [ "$EUID" -ne 0 ]; then - echo "[Warning] Tun script not running as root" -fi - -command -v pkill >/dev/null 2>&1 || echo "[Warning] pkill not found" - -BASEDIR=$(dirname "$0") -cd $BASEDIR - -pre_start_linux() { - # for Tun2Socket - iptables -I INPUT -s 172.19.0.2 -d 172.19.0.1 -p tcp -j ACCEPT - ip6tables -I INPUT -s fdfe:dcba:9876::2 -d fdfe:dcba:9876::1 -p tcp -j ACCEPT -} - -start() { - pre_start_linux - "./nekobox_core" run -c "$CONFIG_PATH" -} - -stop() { - iptables -D INPUT -s 172.19.0.2 -d 172.19.0.1 -p tcp -j ACCEPT - ip6tables -D INPUT -s fdfe:dcba:9876::2 -d fdfe:dcba:9876::1 -p tcp -j ACCEPT -} - -if [ "$1" != "stop" ]; then - start || true -fi - -stop || true diff --git a/rpc/gRPC.cpp b/rpc/gRPC.cpp deleted file mode 100644 index e588315..0000000 --- a/rpc/gRPC.cpp +++ /dev/null @@ -1,299 +0,0 @@ -#include "gRPC.h" - -#include -#include - -#ifndef NKR_NO_GRPC - -#include "main/NekoGui.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace QtGrpc { - const char *GrpcAcceptEncodingHeader = "grpc-accept-encoding"; - const char *AcceptEncodingHeader = "accept-encoding"; - const char *TEHeader = "te"; - const char *GrpcStatusHeader = "grpc-status"; - const char *GrpcStatusMessage = "grpc-message"; - const int GrpcMessageSizeHeaderSize = 5; - - class NoCache : public QAbstractNetworkCache { - public: - QNetworkCacheMetaData metaData(const QUrl &url) override { - return {}; - } - void updateMetaData(const QNetworkCacheMetaData &metaData) override { - } - QIODevice *data(const QUrl &url) override { - return nullptr; - } - bool remove(const QUrl &url) override { - return false; - } - [[nodiscard]] qint64 cacheSize() const override { - return 0; - } - QIODevice *prepare(const QNetworkCacheMetaData &metaData) override { - return nullptr; - } - void insert(QIODevice *device) override { - } - void clear() override { - } - }; - - class Http2GrpcChannelPrivate { - private: - QThread *thread; - QNetworkAccessManager *nm; - - QString url_base; - QString serviceName; - QByteArray nekoray_auth; - - // async - QNetworkReply *post(const QString &method, const QString &service, const QByteArray &args) { - QUrl callUrl = url_base + "/" + service + "/" + method; - // qDebug() << "Service call url: " << callUrl; - - QNetworkRequest request(callUrl); - // request.setAttribute(QNetworkRequest::CacheSaveControlAttribute, false); - // request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork); -#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0) - request.setAttribute(QNetworkRequest::Http2DirectAttribute, true); -#endif - request.setHeader(QNetworkRequest::ContentTypeHeader, QLatin1String{"application/grpc"}); - request.setRawHeader("Cache-Control", "no-store"); - request.setRawHeader(GrpcAcceptEncodingHeader, QByteArray{"identity,deflate,gzip"}); - request.setRawHeader(AcceptEncodingHeader, QByteArray{"identity,gzip"}); - request.setRawHeader(TEHeader, QByteArray{"trailers"}); - request.setRawHeader("nekoray_auth", nekoray_auth); - - QByteArray msg(GrpcMessageSizeHeaderSize, '\0'); - *reinterpret_cast(msg.data() + 1) = qToBigEndian((int) args.size()); - msg += args; - // qDebug() << "SEND: " << msg.size(); - - QNetworkReply *networkReply = nm->post(request, msg); - return networkReply; - } - - static QByteArray processReply(QNetworkReply *networkReply, QNetworkReply::NetworkError &statusCode) { - // Check if no network error occured - if (networkReply->error() != QNetworkReply::NoError) { - statusCode = networkReply->error(); - return {}; - } - - // Check if server answer with error - auto errCode = networkReply->rawHeader(GrpcStatusHeader).toInt(); - if (errCode != 0) { - QStringList errstr; - errstr << "grpc-status error code:" << Int2String(errCode) << ", error msg:" - << QLatin1String(networkReply->rawHeader(GrpcStatusMessage)); - MW_show_log(errstr.join(" ")); - statusCode = QNetworkReply::NetworkError::ProtocolUnknownError; - return {}; - } - statusCode = QNetworkReply::NetworkError::NoError; - return networkReply->readAll().mid(GrpcMessageSizeHeaderSize); - } - - QNetworkReply::NetworkError call(const QString &method, const QString &service, const QByteArray &args, QByteArray &qByteArray, int timeout_ms) { - QNetworkReply *networkReply = post(method, service, args); - - QTimer *abortTimer = nullptr; - if (timeout_ms > 0) { - abortTimer = new QTimer; - abortTimer->setSingleShot(true); - abortTimer->setInterval(timeout_ms); - QObject::connect(abortTimer, &QTimer::timeout, networkReply, &QNetworkReply::abort); - abortTimer->start(); - } - - { - QEventLoop loop; - QObject::connect(networkReply, &QNetworkReply::finished, &loop, &QEventLoop::quit); - loop.exec(); - } - - if (abortTimer != nullptr) { - abortTimer->stop(); - abortTimer->deleteLater(); - } - - auto grpcStatus = QNetworkReply::NetworkError::ProtocolUnknownError; - qByteArray = processReply(networkReply, grpcStatus); - // qDebug() << __func__ << "RECV: " << qByteArray.toHex() << "grpcStatus" << grpcStatus; - // qDebug() << networkReply->rawHeaderPairs(); - - networkReply->deleteLater(); - return grpcStatus; - } - - public: - Http2GrpcChannelPrivate(const QString &url_, const QString &nekoray_auth_, const QString &serviceName_) { - url_base = "http://" + url_; - nekoray_auth = nekoray_auth_.toLatin1(); - serviceName = serviceName_; - // - thread = new QThread; - nm = new QNetworkAccessManager(); - nm->setCache(new NoCache); - nm->moveToThread(thread); - thread->start(); - } - - ~Http2GrpcChannelPrivate() { - nm->deleteLater(); - thread->quit(); - thread->wait(); - thread->deleteLater(); - } - - QNetworkReply::NetworkError Call(const QString &methodName, - const google::protobuf::Message &req, google::protobuf::Message *rsp, - int timeout_ms = 0) { - if (!NekoGui::dataStore->core_running) return QNetworkReply::NetworkError(-1919); - - std::string reqStr; - req.SerializeToString(&reqStr); - auto requestArray = QByteArray::fromStdString(reqStr); - - QByteArray responseArray; - QNetworkReply::NetworkError err; - QMutex lock; - lock.lock(); - - runOnUiThread( - [&] { - err = call(methodName, serviceName, requestArray, responseArray, timeout_ms); - lock.unlock(); - }, - nm); - - lock.lock(); - lock.unlock(); - // qDebug() << "rsp err" << err; - // qDebug() << "rsp array" << responseArray; - - if (err != QNetworkReply::NetworkError::NoError) { - return err; - } - if (!rsp->ParseFromArray(responseArray.data(), responseArray.size())) { - return QNetworkReply::NetworkError(-114514); - } - return QNetworkReply::NetworkError::NoError; - } - }; -} // namespace QtGrpc - -namespace NekoGui_rpc { - - Client::Client(std::function onError, const QString &target, const QString &token) { - this->make_grpc_channel = [=]() { return std::make_unique(target, token, "libcore.LibcoreService"); }; - this->default_grpc_channel = make_grpc_channel(); - this->onError = std::move(onError); - } - -#define NOT_OK \ - *rpcOK = false; \ - onError(QStringLiteral("QNetworkReply::NetworkError code: %1\n").arg(status)); - - void Client::Exit() { - libcore::EmptyReq request; - libcore::EmptyResp reply; - default_grpc_channel->Call("Exit", request, &reply, 500); - } - - QString Client::Start(bool *rpcOK, const libcore::LoadConfigReq &request) { - libcore::ErrorResp reply; - auto status = default_grpc_channel->Call("Start", request, &reply); - - if (status == QNetworkReply::NoError) { - *rpcOK = true; - return {reply.error().c_str()}; - } else { - NOT_OK - return ""; - } - } - - QString Client::Stop(bool *rpcOK) { - libcore::EmptyReq request; - libcore::ErrorResp reply; - auto status = default_grpc_channel->Call("Stop", request, &reply); - - if (status == QNetworkReply::NoError) { - *rpcOK = true; - return {reply.error().c_str()}; - } else { - NOT_OK - return ""; - } - } - - long long Client::QueryStats(const std::string &tag, const std::string &direct) { - libcore::QueryStatsReq request; - request.set_tag(tag); - request.set_direct(direct); - - libcore::QueryStatsResp reply; - auto status = default_grpc_channel->Call("QueryStats", request, &reply, 500); - - if (status == QNetworkReply::NoError) { - return reply.traffic(); - } else { - return 0; - } - } - - std::string Client::ListConnections() { - libcore::EmptyReq request; - libcore::ListConnectionsResp reply; - auto status = default_grpc_channel->Call("ListConnections", request, &reply, 500); - - if (status == QNetworkReply::NoError) { - return reply.nekoray_connections_json(); - } else { - return ""; - } - } - - // - - libcore::TestResp Client::Test(bool *rpcOK, const libcore::TestReq &request) { - libcore::TestResp reply; - auto status = make_grpc_channel()->Call("Test", request, &reply); - - if (status == QNetworkReply::NoError) { - *rpcOK = true; - return reply; - } else { - NOT_OK - return reply; - } - } - - libcore::UpdateResp Client::Update(bool *rpcOK, const libcore::UpdateReq &request) { - libcore::UpdateResp reply; - auto status = default_grpc_channel->Call("Update", request, &reply); - - if (status == QNetworkReply::NoError) { - *rpcOK = true; - return reply; - } else { - NOT_OK - return reply; - } - } -} // namespace NekoGui_rpc - -#endif diff --git a/rpc/gRPC.h b/rpc/gRPC.h deleted file mode 100644 index 25c03a0..0000000 --- a/rpc/gRPC.h +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -#ifndef NKR_NO_GRPC - -#include "go/grpc_server/gen/libcore.pb.h" -#include - -namespace QtGrpc { - class Http2GrpcChannelPrivate; -} - -namespace NekoGui_rpc { - class Client { - public: - explicit Client(std::function onError, const QString &target, const QString &token); - - void Exit(); - - bool KeepAlive(); - - // QString returns is error string - - QString Start(bool *rpcOK, const libcore::LoadConfigReq &request); - - QString Stop(bool *rpcOK); - - long long QueryStats(const std::string &tag, const std::string &direct); - - std::string ListConnections(); - - libcore::TestResp Test(bool *rpcOK, const libcore::TestReq &request); - - libcore::UpdateResp Update(bool *rpcOK, const libcore::UpdateReq &request); - - private: - std::function()> make_grpc_channel; - std::unique_ptr default_grpc_channel; - std::function onError; - }; - - inline Client *defaultClient; -} // namespace NekoGui_rpc -#endif diff --git a/sub/GroupUpdater.cpp b/sub/GroupUpdater.cpp deleted file mode 100644 index 6ad7eb1..0000000 --- a/sub/GroupUpdater.cpp +++ /dev/null @@ -1,665 +0,0 @@ -#include "db/ProfileFilter.hpp" -#include "fmt/includes.h" -#include "fmt/Preset.hpp" -#include "main/HTTPRequestHelper.hpp" - -#include "GroupUpdater.hpp" - -#include -#include - -#ifndef NKR_NO_YAML - -#include - -#endif - -namespace NekoGui_sub { - - GroupUpdater *groupUpdater = new GroupUpdater; - - void RawUpdater_FixEnt(const std::shared_ptr &ent) { - if (ent == nullptr) return; - auto stream = NekoGui_fmt::GetStreamSettings(ent->bean.get()); - if (stream == nullptr) return; - // 1. "security" - if (stream->security == "none" || stream->security == "0" || stream->security == "false") { - stream->security = ""; - } else if (stream->security == "1" || stream->security == "true") { - stream->security = "tls"; - } - // 2. TLS SNI: v2rayN config builder generate sni like this, so set sni here for their format. - if (stream->security == "tls" && IsIpAddress(ent->bean->serverAddress) && (!stream->host.isEmpty()) && stream->sni.isEmpty()) { - stream->sni = stream->host; - } - } - - void RawUpdater::update(const QString &str) { - // Base64 encoded subscription - if (auto str2 = DecodeB64IfValid(str); !str2.isEmpty()) { - update(str2); - return; - } - - // Clash - if (str.contains("proxies:")) { - updateClash(str); - return; - } - - // Multi line - if (str.count("\n") > 0) { - auto list = str.split("\n"); - for (const auto &str2: list) { - update(str2.trimmed()); - } - return; - } - - std::shared_ptr ent; - bool needFix = true; - - // Nekoray format - if (str.startsWith("nekoray://")) { - needFix = false; - auto link = QUrl(str); - if (!link.isValid()) return; - ent = NekoGui::ProfileManager::NewProxyEntity(link.host()); - if (ent->bean->version == -114514) return; - auto j = DecodeB64IfValid(link.fragment().toUtf8(), QByteArray::Base64UrlEncoding); - if (j.isEmpty()) return; - ent->bean->FromJsonBytes(j); - } - - // SOCKS - if (str.startsWith("socks5://") || str.startsWith("socks4://") || - str.startsWith("socks4a://") || str.startsWith("socks://")) { - ent = NekoGui::ProfileManager::NewProxyEntity("socks"); - auto ok = ent->SocksHTTPBean()->TryParseLink(str); - if (!ok) return; - } - - // HTTP - if (str.startsWith("http://") || str.startsWith("https://")) { - ent = NekoGui::ProfileManager::NewProxyEntity("http"); - auto ok = ent->SocksHTTPBean()->TryParseLink(str); - if (!ok) return; - } - - // ShadowSocks - if (str.startsWith("ss://")) { - ent = NekoGui::ProfileManager::NewProxyEntity("shadowsocks"); - auto ok = ent->ShadowSocksBean()->TryParseLink(str); - if (!ok) return; - } - - // VMess - if (str.startsWith("vmess://")) { - ent = NekoGui::ProfileManager::NewProxyEntity("vmess"); - auto ok = ent->VMessBean()->TryParseLink(str); - if (!ok) return; - } - - // VLESS - if (str.startsWith("vless://")) { - ent = NekoGui::ProfileManager::NewProxyEntity("vless"); - auto ok = ent->TrojanVLESSBean()->TryParseLink(str); - if (!ok) return; - } - - // Trojan - if (str.startsWith("trojan://")) { - ent = NekoGui::ProfileManager::NewProxyEntity("trojan"); - auto ok = ent->TrojanVLESSBean()->TryParseLink(str); - if (!ok) return; - } - - // Naive - if (str.startsWith("naive+")) { - needFix = false; - ent = NekoGui::ProfileManager::NewProxyEntity("naive"); - auto ok = ent->NaiveBean()->TryParseLink(str); - if (!ok) return; - } - - // Hysteria2 - if (str.startsWith("hysteria2://") || str.startsWith("hy2://")) { - needFix = false; - ent = NekoGui::ProfileManager::NewProxyEntity("hysteria2"); - auto ok = ent->QUICBean()->TryParseLink(str); - if (!ok) return; - } - - // TUIC - if (str.startsWith("tuic://")) { - needFix = false; - ent = NekoGui::ProfileManager::NewProxyEntity("tuic"); - auto ok = ent->QUICBean()->TryParseLink(str); - if (!ok) return; - } - - if (ent == nullptr) return; - - // Fix - if (needFix) RawUpdater_FixEnt(ent); - - // End - NekoGui::profileManager->AddProfile(ent, gid_add_to); - updated_order += ent; - } - -#ifndef NKR_NO_YAML - - QString Node2QString(const YAML::Node &n, const QString &def = "") { - try { - return n.as().c_str(); - } catch (const YAML::Exception &ex) { - qDebug() << ex.what(); - return def; - } - } - - QStringList Node2QStringList(const YAML::Node &n) { - try { - if (n.IsSequence()) { - QStringList list; - for (auto item: n) { - list << item.as().c_str(); - } - return list; - } else { - return {}; - } - } catch (const YAML::Exception &ex) { - qDebug() << ex.what(); - return {}; - } - } - - int Node2Int(const YAML::Node &n, const int &def = 0) { - try { - return n.as(); - } catch (const YAML::Exception &ex) { - qDebug() << ex.what(); - return def; - } - } - - bool Node2Bool(const YAML::Node &n, const bool &def = false) { - try { - return n.as(); - } catch (const YAML::Exception &ex) { - try { - return n.as(); - } catch (const YAML::Exception &ex2) { - qDebug() << ex2.what(); - } - qDebug() << ex.what(); - return def; - } - } - - // NodeChild returns the first defined children or Null Node - YAML::Node NodeChild(const YAML::Node &n, const std::list &keys) { - for (const auto &key: keys) { - auto child = n[key]; - if (child.IsDefined()) return child; - } - return {}; - } - -#endif - - // https://github.com/Dreamacro/clash/wiki/configuration - void RawUpdater::updateClash(const QString &str) { -#ifndef NKR_NO_YAML - try { - auto proxies = YAML::Load(str.toStdString())["proxies"]; - for (auto proxy: proxies) { - auto type = Node2QString(proxy["type"]).toLower(); - auto type_clash = type; - - if (type == "ss" || type == "ssr") type = "shadowsocks"; - if (type == "socks5") type = "socks"; - - auto ent = NekoGui::ProfileManager::NewProxyEntity(type); - if (ent->bean->version == -114514) continue; - bool needFix = false; - - // common - ent->bean->name = Node2QString(proxy["name"]); - ent->bean->serverAddress = Node2QString(proxy["server"]); - ent->bean->serverPort = Node2Int(proxy["port"]); - - if (type_clash == "ss") { - auto bean = ent->ShadowSocksBean(); - bean->method = Node2QString(proxy["cipher"]).replace("dummy", "none"); - bean->password = Node2QString(proxy["password"]); - auto plugin_n = proxy["plugin"]; - auto pluginOpts_n = proxy["plugin-opts"]; - - // UDP over TCP - if (Node2Bool(proxy["udp-over-tcp"])) { - bean->uot = Node2Int(proxy["udp-over-tcp-version"]); - if (bean->uot == 0) bean->uot = 2; - } - - if (plugin_n.IsDefined() && pluginOpts_n.IsDefined()) { - QStringList ssPlugin; - auto plugin = Node2QString(plugin_n); - if (plugin == "obfs") { - ssPlugin << "obfs-local"; - ssPlugin << "obfs=" + Node2QString(pluginOpts_n["mode"]); - ssPlugin << "obfs-host=" + Node2QString(pluginOpts_n["host"]); - } else if (plugin == "v2ray-plugin") { - auto mode = Node2QString(pluginOpts_n["mode"]); - auto host = Node2QString(pluginOpts_n["host"]); - auto path = Node2QString(pluginOpts_n["path"]); - ssPlugin << "v2ray-plugin"; - if (!mode.isEmpty() && mode != "websocket") ssPlugin << "mode=" + mode; - if (Node2Bool(pluginOpts_n["tls"])) ssPlugin << "tls"; - if (!host.isEmpty()) ssPlugin << "host=" + host; - if (!path.isEmpty()) ssPlugin << "path=" + path; - // clash only: skip-cert-verify - // clash only: headers - // clash: mux=? - } - bean->plugin = ssPlugin.join(";"); - } - - // sing-mux - auto smux = NodeChild(proxy, {"smux"}); - if (Node2Bool(smux["enabled"])) bean->stream->multiplex_status = 1; - } else if (type == "socks" || type == "http") { - auto bean = ent->SocksHTTPBean(); - bean->username = Node2QString(proxy["username"]); - bean->password = Node2QString(proxy["password"]); - if (Node2Bool(proxy["tls"])) bean->stream->security = "tls"; - if (Node2Bool(proxy["skip-cert-verify"])) bean->stream->allow_insecure = true; - } else if (type == "trojan" || type == "vless") { - needFix = true; - auto bean = ent->TrojanVLESSBean(); - if (type == "vless") { - bean->flow = Node2QString(proxy["flow"]); - bean->password = Node2QString(proxy["uuid"]); - // meta packet encoding - if (Node2Bool(proxy["packet-addr"])) { - bean->stream->packet_encoding = "packetaddr"; - } else { - // For VLESS, default to use xudp - bean->stream->packet_encoding = "xudp"; - } - } else { - bean->password = Node2QString(proxy["password"]); - } - bean->stream->security = "tls"; - bean->stream->network = Node2QString(proxy["network"], "tcp"); - bean->stream->sni = FIRST_OR_SECOND(Node2QString(proxy["sni"]), Node2QString(proxy["servername"])); - bean->stream->alpn = Node2QStringList(proxy["alpn"]).join(","); - bean->stream->allow_insecure = Node2Bool(proxy["skip-cert-verify"]); - bean->stream->utlsFingerprint = Node2QString(proxy["client-fingerprint"]); - if (bean->stream->utlsFingerprint.isEmpty()) { - bean->stream->utlsFingerprint = NekoGui::dataStore->utlsFingerprint; - } - - // sing-mux - auto smux = NodeChild(proxy, {"smux"}); - if (Node2Bool(smux["enabled"])) bean->stream->multiplex_status = 1; - - // opts - auto ws = NodeChild(proxy, {"ws-opts", "ws-opt"}); - if (ws.IsMap()) { - auto headers = ws["headers"]; - for (auto header: headers) { - if (Node2QString(header.first).toLower() == "host") { - bean->stream->host = Node2QString(header.second); - } - } - bean->stream->path = Node2QString(ws["path"]); - bean->stream->ws_early_data_length = Node2Int(ws["max-early-data"]); - bean->stream->ws_early_data_name = Node2QString(ws["early-data-header-name"]); - } - - auto grpc = NodeChild(proxy, {"grpc-opts", "grpc-opt"}); - if (grpc.IsMap()) { - bean->stream->path = Node2QString(grpc["grpc-service-name"]); - } - - auto reality = NodeChild(proxy, {"reality-opts"}); - if (reality.IsMap()) { - bean->stream->reality_pbk = Node2QString(reality["public-key"]); - bean->stream->reality_sid = Node2QString(reality["short-id"]); - } - } else if (type == "vmess") { - needFix = true; - auto bean = ent->VMessBean(); - bean->uuid = Node2QString(proxy["uuid"]); - bean->aid = Node2Int(proxy["alterId"]); - bean->security = Node2QString(proxy["cipher"], bean->security); - bean->stream->network = Node2QString(proxy["network"], "tcp").replace("h2", "http"); - bean->stream->sni = FIRST_OR_SECOND(Node2QString(proxy["sni"]), Node2QString(proxy["servername"])); - bean->stream->alpn = Node2QStringList(proxy["alpn"]).join(","); - if (Node2Bool(proxy["tls"])) bean->stream->security = "tls"; - if (Node2Bool(proxy["skip-cert-verify"])) bean->stream->allow_insecure = true; - bean->stream->utlsFingerprint = Node2QString(proxy["client-fingerprint"]); - bean->stream->utlsFingerprint = Node2QString(proxy["client-fingerprint"]); - if (bean->stream->utlsFingerprint.isEmpty()) { - bean->stream->utlsFingerprint = NekoGui::dataStore->utlsFingerprint; - } - - // sing-mux - auto smux = NodeChild(proxy, {"smux"}); - if (Node2Bool(smux["enabled"])) bean->stream->multiplex_status = 1; - - // meta packet encoding - if (Node2Bool(proxy["xudp"])) bean->stream->packet_encoding = "xudp"; - if (Node2Bool(proxy["packet-addr"])) bean->stream->packet_encoding = "packetaddr"; - - // opts - auto ws = NodeChild(proxy, {"ws-opts", "ws-opt"}); - if (ws.IsMap()) { - auto headers = ws["headers"]; - for (auto header: headers) { - if (Node2QString(header.first).toLower() == "host") { - bean->stream->host = Node2QString(header.second); - } - } - bean->stream->path = Node2QString(ws["path"]); - bean->stream->ws_early_data_length = Node2Int(ws["max-early-data"]); - bean->stream->ws_early_data_name = Node2QString(ws["early-data-header-name"]); - // for Xray - if (Node2QString(ws["early-data-header-name"]) == "Sec-WebSocket-Protocol") { - bean->stream->path += "?ed=" + Node2QString(ws["max-early-data"]); - } - } - - auto grpc = NodeChild(proxy, {"grpc-opts", "grpc-opt"}); - if (grpc.IsMap()) { - bean->stream->path = Node2QString(grpc["grpc-service-name"]); - } - - auto h2 = NodeChild(proxy, {"h2-opts", "h2-opt"}); - if (h2.IsMap()) { - auto hosts = h2["host"]; - for (auto host: hosts) { - bean->stream->host = Node2QString(host); - break; - } - bean->stream->path = Node2QString(h2["path"]); - } - - auto tcp_http = NodeChild(proxy, {"http-opts", "http-opt"}); - if (tcp_http.IsMap()) { - bean->stream->network = "tcp"; - bean->stream->header_type = "http"; - auto headers = tcp_http["headers"]; - for (auto header: headers) { - if (Node2QString(header.first).toLower() == "host") { - bean->stream->host = Node2QString(header.second[0]); - } - break; - } - auto paths = tcp_http["path"]; - for (auto path: paths) { - bean->stream->path = Node2QString(path); - break; - } - } - } else if (type == "hysteria2") { - auto bean = ent->QUICBean(); - - bean->hopPort = Node2QString(proxy["ports"]); - - bean->allowInsecure = Node2Bool(proxy["skip-cert-verify"]); - bean->caText = Node2QString(proxy["ca-str"]); - bean->sni = Node2QString(proxy["sni"]); - - bean->obfsPassword = Node2QString(proxy["obfs-password"]); - bean->password = Node2QString(proxy["password"]); - - bean->uploadMbps = Node2QString(proxy["up"]).split(" ")[0].toInt(); - bean->downloadMbps = Node2QString(proxy["down"]).split(" ")[0].toInt(); - } else if (type == "tuic") { - auto bean = ent->QUICBean(); - - bean->uuid = Node2QString(proxy["uuid"]); - bean->password = Node2QString(proxy["password"]); - - if (Node2Int(proxy["heartbeat-interval"]) != 0) { - bean->heartbeat = Int2String(Node2Int(proxy["heartbeat-interval"])) + "ms"; - } - - bean->udpRelayMode = Node2QString(proxy["udp-relay-mode"], bean->udpRelayMode); - bean->congestionControl = Node2QString(proxy["congestion-controller"], bean->congestionControl); - - bean->disableSni = Node2Bool(proxy["disable-sni"]); - bean->zeroRttHandshake = Node2Bool(proxy["reduce-rtt"]); - bean->allowInsecure = Node2Bool(proxy["skip-cert-verify"]); - bean->alpn = Node2QStringList(proxy["alpn"]).join(","); - bean->caText = Node2QString(proxy["ca-str"]); - bean->sni = Node2QString(proxy["sni"]); - - if (Node2Bool(proxy["udp-over-stream"])) bean->uos = true; - - if (!Node2QString(proxy["ip"]).isEmpty()) { - if (bean->sni.isEmpty()) bean->sni = bean->serverAddress; - bean->serverAddress = Node2QString(proxy["ip"]); - } - } else { - continue; - } - - if (needFix) RawUpdater_FixEnt(ent); - NekoGui::profileManager->AddProfile(ent, gid_add_to); - updated_order += ent; - } - } catch (const YAML::Exception &ex) { - runOnUiThread([=] { - MessageBoxWarning("YAML Exception", ex.what()); - }); - } -#endif - } - - // 在新的 thread 运行 - void GroupUpdater::AsyncUpdate(const QString &str, int _sub_gid, const std::function &finish) { - auto content = str.trimmed(); - bool asURL = false; - bool createNewGroup = false; - - if (_sub_gid < 0 && (content.startsWith("http://") || content.startsWith("https://"))) { - auto items = QStringList{ - QObject::tr("As Subscription (add to this group)"), - QObject::tr("As Subscription (create new group)"), - QObject::tr("As link"), - }; - bool ok; - auto a = QInputDialog::getItem(nullptr, - QObject::tr("url detected"), - QObject::tr("%1\nHow to update?").arg(content), - items, 0, false, &ok); - if (!ok) return; - if (items.indexOf(a) <= 1) asURL = true; - if (items.indexOf(a) == 1) createNewGroup = true; - } - - runOnNewThread([=] { - auto gid = _sub_gid; - if (createNewGroup) { - auto group = NekoGui::ProfileManager::NewGroup(); - group->name = QUrl(str).host(); - group->url = str; - NekoGui::profileManager->AddGroup(group); - gid = group->id; - MW_dialog_message("SubUpdater", "NewGroup"); - } - Update(str, gid, asURL); - emit asyncUpdateCallback(gid); - if (finish != nullptr) finish(); - }); - } - - void GroupUpdater::Update(const QString &_str, int _sub_gid, bool _not_sub_as_url) { - // 创建 rawUpdater - NekoGui::dataStore->imported_count = 0; - auto rawUpdater = std::make_unique(); - rawUpdater->gid_add_to = _sub_gid; - - // 准备 - QString sub_user_info; - bool asURL = _sub_gid >= 0 || _not_sub_as_url; // 把 _str 当作 url 处理(下载内容) - auto content = _str.trimmed(); - auto group = NekoGui::profileManager->GetGroup(_sub_gid); - if (group != nullptr && group->archive) return; - - // 网络请求 - if (asURL) { - auto groupName = group == nullptr ? content : group->name; - MW_show_log(">>>>>>>> " + QObject::tr("Requesting subscription: %1").arg(groupName)); - - auto resp = NetworkRequestHelper::HttpGet(content); - if (!resp.error.isEmpty()) { - MW_show_log("<<<<<<<< " + QObject::tr("Requesting subscription %1 error: %2").arg(groupName, resp.error + "\n" + resp.data)); - return; - } - - content = resp.data; - sub_user_info = NetworkRequestHelper::GetHeader(resp.header, "Subscription-UserInfo"); - - MW_show_log("<<<<<<<< " + QObject::tr("Subscription request fininshed: %1").arg(groupName)); - } - - QList> in; // 更新前 - QList> out_all; // 更新前 + 更新后 - QList> out; // 更新后 - QList> only_in; // 只在更新前有的 - QList> only_out; // 只在更新后有的 - QList> update_del; // 更新前后都有的,需要删除的新配置 - QList> update_keep; // 更新前后都有的,被保留的旧配置 - - // 订阅解析前 - if (group != nullptr) { - in = group->Profiles(); - group->sub_last_update = QDateTime::currentMSecsSinceEpoch() / 1000; - group->info = sub_user_info; - group->order.clear(); - group->Save(); - // - if (NekoGui::dataStore->sub_clear) { - MW_show_log(QObject::tr("Clearing servers...")); - for (const auto &profile: in) { - NekoGui::profileManager->DeleteProfile(profile->id); - } - } - } - - // 解析并添加 profile - rawUpdater->update(content); - - if (group != nullptr) { - out_all = group->Profiles(); - - QString change_text; - - if (NekoGui::dataStore->sub_clear) { - // all is new profile - for (const auto &ent: out_all) { - change_text += "[+] " + ent->bean->DisplayTypeAndName() + "\n"; - } - } else { - // find and delete not updated profile by ProfileFilter - NekoGui::ProfileFilter::OnlyInSrc_ByPointer(out_all, in, out); - NekoGui::ProfileFilter::OnlyInSrc(in, out, only_in); - NekoGui::ProfileFilter::OnlyInSrc(out, in, only_out); - NekoGui::ProfileFilter::Common(in, out, update_keep, update_del, false); - - QString notice_added; - QString notice_deleted; - for (const auto &ent: only_out) { - notice_added += "[+] " + ent->bean->DisplayTypeAndName() + "\n"; - } - for (const auto &ent: only_in) { - notice_deleted += "[-] " + ent->bean->DisplayTypeAndName() + "\n"; - } - - // sort according to order in remote - group->order = {}; - for (const auto &ent: rawUpdater->updated_order) { - auto deleted_index = update_del.indexOf(ent); - if (deleted_index > 0) { - if (deleted_index >= update_keep.count()) continue; // should not happen - auto ent2 = update_keep[deleted_index]; - group->order.append(ent2->id); - } else { - group->order.append(ent->id); - } - } - group->Save(); - - // cleanup - for (const auto &ent: out_all) { - if (!group->order.contains(ent->id)) { - NekoGui::profileManager->DeleteProfile(ent->id); - } - } - - change_text = "\n" + QObject::tr("Added %1 profiles:\n%2\nDeleted %3 Profiles:\n%4") - .arg(only_out.length()) - .arg(notice_added) - .arg(only_in.length()) - .arg(notice_deleted); - if (only_out.length() + only_in.length() == 0) change_text = QObject::tr("Nothing"); - } - - MW_show_log("<<<<<<<< " + QObject::tr("Change of %1:").arg(group->name) + "\n" + change_text); - MW_dialog_message("SubUpdater", "finish-dingyue"); - } else { - NekoGui::dataStore->imported_count = rawUpdater->updated_order.count(); - MW_dialog_message("SubUpdater", "finish"); - } - } -} // namespace NekoGui_sub - -bool UI_update_all_groups_Updating = false; - -#define should_skip_group(g) (g == nullptr || g->url.isEmpty() || g->archive || (onlyAllowed && g->skip_auto_update)) - -void serialUpdateSubscription(const QList &groupsTabOrder, int _order, bool onlyAllowed) { - if (_order >= groupsTabOrder.size()) { - UI_update_all_groups_Updating = false; - return; - } - - // calculate this group - auto group = NekoGui::profileManager->GetGroup(groupsTabOrder[_order]); - if (group == nullptr || should_skip_group(group)) { - serialUpdateSubscription(groupsTabOrder, _order + 1, onlyAllowed); - return; - } - - int nextOrder = _order + 1; - while (nextOrder < groupsTabOrder.size()) { - auto nextGid = groupsTabOrder[nextOrder]; - auto nextGroup = NekoGui::profileManager->GetGroup(nextGid); - if (!should_skip_group(nextGroup)) { - break; - } - nextOrder += 1; - } - - // Async update current group - UI_update_all_groups_Updating = true; - NekoGui_sub::groupUpdater->AsyncUpdate(group->url, group->id, [=] { - serialUpdateSubscription(groupsTabOrder, nextOrder, onlyAllowed); - }); -} - -void UI_update_all_groups(bool onlyAllowed) { - if (UI_update_all_groups_Updating) { - MW_show_log("The last subscription update has not exited."); - return; - } - - auto groupsTabOrder = NekoGui::profileManager->groupsTabOrder; - serialUpdateSubscription(groupsTabOrder, 0, onlyAllowed); -} diff --git a/sub/GroupUpdater.hpp b/sub/GroupUpdater.hpp deleted file mode 100644 index 87d3612..0000000 --- a/sub/GroupUpdater.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#include "db/Database.hpp" - -namespace NekoGui_sub { - class RawUpdater { - public: - void updateClash(const QString &str); - - void update(const QString &str); - - int gid_add_to = -1; // 导入到指定组 -1 为当前选中组 - - QList> updated_order; // 新增的配置,按照导入时处理的先后排序 - }; - - class GroupUpdater : public QObject { - Q_OBJECT - - public: - void AsyncUpdate(const QString &str, int _sub_gid = -1, const std::function &finish = nullptr); - - void Update(const QString &_str, int _sub_gid = -1, bool _not_sub_as_url = false); - - signals: - - void asyncUpdateCallback(int gid); - }; - - extern GroupUpdater *groupUpdater; -} // namespace NekoGui_sub - -// 更新所有订阅 关闭分组窗口时 更新动作继续执行 -void UI_update_all_groups(bool onlyAllowed = false); diff --git a/sys/AutoRun.cpp b/sys/AutoRun.cpp deleted file mode 100644 index dbceffd..0000000 --- a/sys/AutoRun.cpp +++ /dev/null @@ -1,231 +0,0 @@ -#include "AutoRun.hpp" - -#include -#include - -#include "3rdparty/fix_old_qt.h" -#include "main/NekoGui.hpp" - -// macOS headers (possibly OBJ-c) -#if defined(Q_OS_MACOS) -#include -#include -#endif - -#ifdef Q_OS_WIN - -#include - -QString Windows_GenAutoRunString() { - auto appPath = QApplication::applicationFilePath(); - appPath = "\"" + QDir::toNativeSeparators(appPath) + "\""; - appPath += " -tray"; - return appPath; -} - -void AutoRun_SetEnabled(bool enable) { - // 以程序名称作为注册表中的键 - // 根据键获取对应的值(程序路径) - auto appPath = QApplication::applicationFilePath(); - QFileInfo fInfo(appPath); - QString name = fInfo.baseName(); - - QSettings settings("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", QSettings::NativeFormat); - - if (enable) { - settings.setValue(name, Windows_GenAutoRunString()); - } else { - settings.remove(name); - } -} - -bool AutoRun_IsEnabled() { - QSettings settings("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", QSettings::NativeFormat); - - // 以程序名称作为注册表中的键 - // 根据键获取对应的值(程序路径) - auto appPath = QApplication::applicationFilePath(); - QFileInfo fInfo(appPath); - QString name = fInfo.baseName(); - - return settings.value(name).toString() == Windows_GenAutoRunString(); -} - -#endif - -#ifdef Q_OS_MACOS - -void AutoRun_SetEnabled(bool enable) { - // From - // https://github.com/nextcloud/desktop/blob/master/src/common/utility_mac.cpp - QString filePath = QDir(QCoreApplication::applicationDirPath() + QLatin1String("/../..")).absolutePath(); - CFStringRef folderCFStr = CFStringCreateWithCString(0, filePath.toUtf8().data(), kCFStringEncodingUTF8); - CFURLRef urlRef = CFURLCreateWithFileSystemPath(0, folderCFStr, kCFURLPOSIXPathStyle, true); - LSSharedFileListRef loginItems = LSSharedFileListCreate(0, kLSSharedFileListSessionLoginItems, 0); - - if (loginItems && enable) { - // Insert an item to the list. - LSSharedFileListItemRef item = - LSSharedFileListInsertItemURL(loginItems, kLSSharedFileListItemLast, 0, 0, urlRef, 0, 0); - - if (item) CFRelease(item); - - CFRelease(loginItems); - } else if (loginItems && !enable) { - // We need to iterate over the items and check which one is "ours". - UInt32 seedValue; - CFArrayRef itemsArray = LSSharedFileListCopySnapshot(loginItems, &seedValue); - CFStringRef appUrlRefString = CFURLGetString(urlRef); - - for (int i = 0; i < CFArrayGetCount(itemsArray); i++) { - LSSharedFileListItemRef item = (LSSharedFileListItemRef) CFArrayGetValueAtIndex(itemsArray, i); - CFURLRef itemUrlRef = NULL; - - if (LSSharedFileListItemResolve(item, 0, &itemUrlRef, NULL) == noErr && itemUrlRef) { - CFStringRef itemUrlString = CFURLGetString(itemUrlRef); - - if (CFStringCompare(itemUrlString, appUrlRefString, 0) == kCFCompareEqualTo) { - LSSharedFileListItemRemove(loginItems, item); // remove it! - } - - CFRelease(itemUrlRef); - } - } - - CFRelease(itemsArray); - CFRelease(loginItems); - } - - CFRelease(folderCFStr); - CFRelease(urlRef); -} - -bool AutoRun_IsEnabled() { - // From - // https://github.com/nextcloud/desktop/blob/master/src/common/utility_mac.cpp - // this is quite some duplicate code with setLaunchOnStartup, at some - // point we should fix this FIXME. - bool returnValue = false; - QString filePath = QDir(QCoreApplication::applicationDirPath() + QLatin1String("/../..")).absolutePath(); - CFStringRef folderCFStr = CFStringCreateWithCString(0, filePath.toUtf8().data(), kCFStringEncodingUTF8); - CFURLRef urlRef = CFURLCreateWithFileSystemPath(0, folderCFStr, kCFURLPOSIXPathStyle, true); - LSSharedFileListRef loginItems = LSSharedFileListCreate(0, kLSSharedFileListSessionLoginItems, 0); - - if (loginItems) { - // We need to iterate over the items and check which one is "ours". - UInt32 seedValue; - CFArrayRef itemsArray = LSSharedFileListCopySnapshot(loginItems, &seedValue); - CFStringRef appUrlRefString = CFURLGetString(urlRef); // no need for release - - for (int i = 0; i < CFArrayGetCount(itemsArray); i++) { - LSSharedFileListItemRef item = (LSSharedFileListItemRef) CFArrayGetValueAtIndex(itemsArray, i); - CFURLRef itemUrlRef = NULL; - - if (LSSharedFileListItemResolve(item, 0, &itemUrlRef, NULL) == noErr && itemUrlRef) { - CFStringRef itemUrlString = CFURLGetString(itemUrlRef); - - if (CFStringCompare(itemUrlString, appUrlRefString, 0) == kCFCompareEqualTo) { - returnValue = true; - } - - CFRelease(itemUrlRef); - } - } - - CFRelease(itemsArray); - } - - CFRelease(loginItems); - CFRelease(folderCFStr); - CFRelease(urlRef); - return returnValue; -} - -#endif - -#ifdef Q_OS_LINUX - -#include -#include -#include - -#define NEWLINE "\n" - -// launchatlogin.cpp -// ShadowClash -// -// Created by TheWanderingCoel on 2018/6/12. -// Copyright © 2019 Coel Wu. All rights reserved. -// -QString getUserAutostartDir_private() { - QString config = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation); - config += QLatin1String("/autostart/"); - return config; -} - -void AutoRun_SetEnabled(bool enable) { - // From https://github.com/nextcloud/desktop/blob/master/src/common/utility_unix.cpp - QString appName = QCoreApplication::applicationName(); - QString userAutoStartPath = getUserAutostartDir_private(); - QString desktopFileLocation = userAutoStartPath + appName + QLatin1String(".desktop"); - QStringList appCmdList; - - // nekoray: launcher - if (qEnvironmentVariable("NKR_FROM_LAUNCHER") == "1") { - appCmdList << QApplication::applicationDirPath() + "/launcher" - << "--"; - } else { - if (QProcessEnvironment::systemEnvironment().contains("APPIMAGE")) { - appCmdList << QProcessEnvironment::systemEnvironment().value("APPIMAGE"); - } else { - appCmdList << QApplication::applicationFilePath(); - } - } - - appCmdList << "-tray"; - - if (NekoGui::dataStore->flag_use_appdata) { - appCmdList << "-appdata"; - } - - if (enable) { - if (!QDir().exists(userAutoStartPath) && !QDir().mkpath(userAutoStartPath)) { - // qCWarning(lcUtility) << "Could not create autostart folder" - // << userAutoStartPath; - return; - } - - QFile iniFile(desktopFileLocation); - - if (!iniFile.open(QIODevice::WriteOnly)) { - // qCWarning(lcUtility) << "Could not write auto start entry" << - // desktopFileLocation; - return; - } - - QTextStream ts(&iniFile); -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) - ts.setCodec("UTF-8"); -#endif - ts << QLatin1String("[Desktop Entry]") << NEWLINE - << QLatin1String("Name=") << appName << NEWLINE - << QLatin1String("Exec=") << appCmdList.join(" ") << NEWLINE - << QLatin1String("Terminal=") << "false" << NEWLINE - << QLatin1String("Categories=") << "Network" << NEWLINE - << QLatin1String("Type=") << "Application" << NEWLINE - << QLatin1String("StartupNotify=") << "false" << NEWLINE - << QLatin1String("X-GNOME-Autostart-enabled=") << "true" << NEWLINE; - ts.flush(); - iniFile.close(); - } else { - QFile::remove(desktopFileLocation); - } -} - -bool AutoRun_IsEnabled() { - QString appName = QCoreApplication::applicationName(); - QString desktopFileLocation = getUserAutostartDir_private() + appName + QLatin1String(".desktop"); - return QFile::exists(desktopFileLocation); -} - -#endif diff --git a/sys/AutoRun.hpp b/sys/AutoRun.hpp deleted file mode 100644 index 7fd25a9..0000000 --- a/sys/AutoRun.hpp +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -void AutoRun_SetEnabled(bool enable); - -bool AutoRun_IsEnabled(); diff --git a/sys/ExternalProcess.cpp b/sys/ExternalProcess.cpp deleted file mode 100644 index 02770ec..0000000 --- a/sys/ExternalProcess.cpp +++ /dev/null @@ -1,158 +0,0 @@ -#include "ExternalProcess.hpp" -#include "main/NekoGui.hpp" - -#include -#include -#include -#include - -namespace NekoGui_sys { - - ExternalProcess::ExternalProcess() : QProcess() { - // qDebug() << "[Debug] ExternalProcess()" << this << running_ext; - this->env = QProcessEnvironment::systemEnvironment().toStringList(); - } - - ExternalProcess::~ExternalProcess() { - // qDebug() << "[Debug] ~ExternalProcess()" << this << running_ext; - } - - void ExternalProcess::Start() { - if (started) return; - started = true; - - if (managed) { - connect(this, &QProcess::readyReadStandardOutput, this, [&]() { - auto log = readAllStandardOutput(); - if (logCounter.fetchAndAddRelaxed(log.count("\n")) > NekoGui::dataStore->max_log_line) return; - MW_show_log_ext_vt100(log); - }); - connect(this, &QProcess::readyReadStandardError, this, [&]() { - MW_show_log_ext_vt100(readAllStandardError().trimmed()); - }); - connect(this, &QProcess::errorOccurred, this, [&](QProcess::ProcessError error) { - if (!killed) { - crashed = true; - MW_show_log_ext(tag, "errorOccurred:" + errorString()); - MW_dialog_message("ExternalProcess", "Crashed"); - } - }); - connect(this, &QProcess::stateChanged, this, [&](QProcess::ProcessState state) { - if (state == QProcess::NotRunning) { - if (killed) { // 用户命令退出 - MW_show_log_ext(tag, "External core stopped"); - } else if (!crashed) { // 异常退出 - crashed = true; - MW_show_log_ext(tag, "[Error] Program exited accidentally: " + errorString()); - Kill(); - MW_dialog_message("ExternalProcess", "Crashed"); - } - } - }); - MW_show_log_ext(tag, "External core starting: " + env.join(" ") + " " + program + " " + arguments.join(" ")); - } - - QProcess::setEnvironment(env); - QProcess::start(program, arguments); - } - - void ExternalProcess::Kill() { - if (killed) return; - killed = true; - - if (!crashed) { - QProcess::kill(); - QProcess::waitForFinished(500); - } - } - - // - - QElapsedTimer coreRestartTimer; - - CoreProcess::CoreProcess(const QString &core_path, const QStringList &args) : ExternalProcess() { - ExternalProcess::managed = false; - ExternalProcess::program = core_path; - ExternalProcess::arguments = args; - - connect(this, &QProcess::readyReadStandardOutput, this, [&]() { - auto log = readAllStandardOutput(); - if (!NekoGui::dataStore->core_running) { - if (log.contains("grpc server listening")) { - // The core really started - NekoGui::dataStore->core_running = true; - if (start_profile_when_core_is_up >= 0) { - MW_dialog_message("ExternalProcess", "CoreStarted," + Int2String(start_profile_when_core_is_up)); - start_profile_when_core_is_up = -1; - } - } else if (log.contains("failed to serve")) { - // The core failed to start - QProcess::kill(); - } - } - if (logCounter.fetchAndAddRelaxed(log.count("\n")) > NekoGui::dataStore->max_log_line) return; - MW_show_log(log); - }); - connect(this, &QProcess::readyReadStandardError, this, [&]() { - auto log = readAllStandardError().trimmed(); - if (show_stderr) { - MW_show_log(log); - return; - } - if (log.contains("token is set")) { - show_stderr = true; - } - }); - connect(this, &QProcess::errorOccurred, this, [&](QProcess::ProcessError error) { - if (error == QProcess::ProcessError::FailedToStart) { - failed_to_start = true; - MW_show_log("start core error occurred: " + errorString() + "\n"); - } - }); - connect(this, &QProcess::stateChanged, this, [&](QProcess::ProcessState state) { - if (state == QProcess::NotRunning) { - NekoGui::dataStore->core_running = false; - } - - if (!NekoGui::dataStore->prepare_exit && state == QProcess::NotRunning) { - if (failed_to_start) return; // no retry - if (restarting) return; - - MW_dialog_message("ExternalProcess", "CoreCrashed"); - - // Retry rate limit - if (coreRestartTimer.isValid()) { - if (coreRestartTimer.restart() < 10 * 1000) { - coreRestartTimer = QElapsedTimer(); - MW_show_log("[Error] " + QObject::tr("Core exits too frequently, stop automatic restart this profile.")); - return; - } - } else { - coreRestartTimer.start(); - } - - // Restart - start_profile_when_core_is_up = NekoGui::dataStore->started_id; - MW_show_log("[Error] " + QObject::tr("Core exited, restarting.")); - setTimeout([=] { Restart(); }, this, 1000); - } - }); - } - - void CoreProcess::Start() { - show_stderr = false; - // cwd: same as GUI, at ./config - ExternalProcess::Start(); - write((NekoGui::dataStore->core_token + "\n").toUtf8()); - } - - void CoreProcess::Restart() { - restarting = true; - QProcess::kill(); - QProcess::waitForFinished(500); - ExternalProcess::started = false; - Start(); - restarting = false; - } - -} // namespace NekoGui_sys diff --git a/sys/ExternalProcess.hpp b/sys/ExternalProcess.hpp deleted file mode 100644 index b70b64f..0000000 --- a/sys/ExternalProcess.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once - -#include -#include - -namespace NekoGui_sys { - class ExternalProcess : public QProcess { - public: - QString tag; - QString program; - QStringList arguments; - QStringList env; - - bool managed = true; // MW_dialog_message - - ExternalProcess(); - ~ExternalProcess(); - - // start & kill is one time - - virtual void Start(); - - void Kill(); - - protected: - bool started = false; - bool killed = false; - bool crashed = false; - }; - - class CoreProcess : public ExternalProcess { - public: - CoreProcess(const QString &core_path, const QStringList &args); - - void Start() override; - - void Restart(); - - int start_profile_when_core_is_up = -1; - - private: - bool show_stderr = false; - bool failed_to_start = false; - bool restarting = false; - }; - - // 手动管理 - inline std::list> running_ext; - - inline QAtomicInt logCounter; -} // namespace NekoGui_sys diff --git a/sys/linux/LinuxCap.cpp b/sys/linux/LinuxCap.cpp deleted file mode 100644 index 5e65311..0000000 --- a/sys/linux/LinuxCap.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "LinuxCap.h" - -#include -#include -#include - -#define EXIT_CODE(p) (p.exitStatus() == QProcess::NormalExit ? p.exitCode() : -1) - -QString Linux_GetCapString(const QString &path) { - QProcess p; - p.setProgram(Linux_FindCapProgsExec("getcap")); - p.setArguments({path}); - p.start(); - p.waitForFinished(500); - return p.readAllStandardOutput(); -} - -int Linux_Pkexec_SetCapString(const QString &path, const QString &cap) { - QProcess p; - p.setProgram("pkexec"); - p.setArguments({Linux_FindCapProgsExec("setcap"), cap, path}); - p.start(); - p.waitForFinished(-1); - return EXIT_CODE(p); -} - -bool Linux_HavePkexec() { - QProcess p; - p.setProgram("pkexec"); - p.setArguments({"--help"}); - p.setProcessChannelMode(QProcess::SeparateChannels); - p.start(); - p.waitForFinished(500); - return EXIT_CODE(p) == 0; -} - -QString Linux_FindCapProgsExec(const QString &name) { - QString exec = QStandardPaths::findExecutable(name); - if (exec.isEmpty()) - exec = QStandardPaths::findExecutable(name, {"/usr/sbin", "/sbin"}); - - if (exec.isEmpty()) - qDebug() << "Executable" << name << "could not be resolved"; - else - qDebug() << "Found exec" << name << "at" << exec; - - return exec.isEmpty() ? name : exec; -} diff --git a/sys/linux/LinuxCap.h b/sys/linux/LinuxCap.h deleted file mode 100644 index 64750e4..0000000 --- a/sys/linux/LinuxCap.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include - -QString Linux_GetCapString(const QString &path); - -int Linux_Pkexec_SetCapString(const QString &path, const QString &cap); - -bool Linux_HavePkexec(); - -QString Linux_FindCapProgsExec(const QString &name); diff --git a/sys/windows/MiniDump.cpp b/sys/windows/MiniDump.cpp deleted file mode 100644 index 798df6b..0000000 --- a/sys/windows/MiniDump.cpp +++ /dev/null @@ -1,75 +0,0 @@ -#include "MiniDump.h" - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#include -#include -#include - -#include -#include -#include -#include - -typedef BOOL(WINAPI *MINIDUMPWRITEDUMP)( - HANDLE hProcess, - DWORD dwPid, - HANDLE hFile, - MINIDUMP_TYPE DumpType, - CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, - CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, - CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam); - -LONG __stdcall CreateCrashHandler(EXCEPTION_POINTERS *pException) { - QDir::setCurrent(QApplication::applicationDirPath()); - - HMODULE DllHandle = NULL; - DllHandle = LoadLibrary(_T("DBGHELP.DLL")); - - if (DllHandle) { - MINIDUMPWRITEDUMP Dump = (MINIDUMPWRITEDUMP) GetProcAddress(DllHandle, "MiniDumpWriteDump"); - if (Dump) { - // 创建 Dump 文件 - QDateTime CurDTime = QDateTime::currentDateTime(); - QString current_date = CurDTime.toString("yyyy_MM_dd_hh_mm_ss"); - // dmp文件的命名 - QString dumpText = "Dump_" + current_date + ".dmp"; - EXCEPTION_RECORD *record = pException->ExceptionRecord; - QString errCode(QString::number(record->ExceptionCode, 16)); - QString errAddr(QString::number((uintptr_t) record->ExceptionAddress, 16)); - QString errFlag(QString::number(record->ExceptionFlags, 16)); - QString errPara(QString::number(record->NumberParameters, 16)); - HANDLE DumpHandle = CreateFile((LPCWSTR) dumpText.utf16(), - GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if (DumpHandle != INVALID_HANDLE_VALUE) { - MINIDUMP_EXCEPTION_INFORMATION dumpInfo; - dumpInfo.ExceptionPointers = pException; - dumpInfo.ThreadId = GetCurrentThreadId(); - dumpInfo.ClientPointers = TRUE; - // 将dump信息写入dmp文件 - Dump(GetCurrentProcess(), GetCurrentProcessId(), DumpHandle, MiniDumpNormal, &dumpInfo, - NULL, NULL); - CloseHandle(DumpHandle); - } else { - dumpText = ""; - } - // 创建消息提示 - QMessageBox::warning(NULL, "Application crashed", - QStringLiteral("ErrorCode: %1 ErrorAddr:%2 ErrorFlag: %3 ErrorPara: %4\nVersion: %5\nDump file at %6") - .arg(errCode) - .arg(errAddr) - .arg(errFlag) - .arg(errPara) - .arg(NKR_VERSION) - .arg(dumpText), - QMessageBox::Ok); - } - } - return EXCEPTION_EXECUTE_HANDLER; -} - -void Windows_SetCrashHandler() { - SetErrorMode(SEM_FAILCRITICALERRORS); - SetUnhandledExceptionFilter(CreateCrashHandler); -} diff --git a/sys/windows/MiniDump.h b/sys/windows/MiniDump.h deleted file mode 100644 index a8fb3ff..0000000 --- a/sys/windows/MiniDump.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -void Windows_SetCrashHandler(); diff --git a/sys/windows/guihelper.cpp b/sys/windows/guihelper.cpp deleted file mode 100644 index f29ebc1..0000000 --- a/sys/windows/guihelper.cpp +++ /dev/null @@ -1,24 +0,0 @@ - -#include "guihelper.h" - -#include - -#include -#include - -void Windows_QWidget_SetForegroundWindow(QWidget *w) { - HWND hForgroundWnd = GetForegroundWindow(); - DWORD dwForeID = ::GetWindowThreadProcessId(hForgroundWnd, NULL); - DWORD dwCurID = ::GetCurrentThreadId(); - ::AttachThreadInput(dwCurID, dwForeID, TRUE); - ::SetForegroundWindow((HWND) w->winId()); - ::AttachThreadInput(dwCurID, dwForeID, FALSE); -} - -int isThisAdmin = -1; // cached - -bool Windows_IsInAdmin() { - if (isThisAdmin >= 0) return isThisAdmin; - isThisAdmin = IsUserAnAdmin(); - return isThisAdmin; -} diff --git a/sys/windows/guihelper.h b/sys/windows/guihelper.h deleted file mode 100644 index 3969b4c..0000000 --- a/sys/windows/guihelper.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -class QWidget; - -void Windows_QWidget_SetForegroundWindow(QWidget* w); - -bool Windows_IsInAdmin(); diff --git a/test/test-qt512-sdk-build.sh b/test/test-qt512-sdk-build.sh deleted file mode 100644 index 9414691..0000000 --- a/test/test-qt512-sdk-build.sh +++ /dev/null @@ -1,7 +0,0 @@ -QT=$PWD/qtsdk/5.12.12/gcc_64 -BUILD=build-sdk-qt512 -rm -rf $BUILD -mkdir -p $BUILD -cd $BUILD -cmake -GNinja -DCMAKE_PREFIX_PATH=$QT .. -ninja diff --git a/test/test-qt6-build.sh b/test/test-qt6-build.sh deleted file mode 100644 index 7c1247b..0000000 --- a/test/test-qt6-build.sh +++ /dev/null @@ -1,5 +0,0 @@ -rm -rf build-qt6 -mkdir -p build-qt6 -cd build-qt6 -cmake -GNinja -DQT_VERSION_MAJOR=6 .. -ninja diff --git a/translations/fa_IR.ts b/translations/fa_IR.ts deleted file mode 100644 index 9fc28a3..0000000 --- a/translations/fa_IR.ts +++ /dev/null @@ -1,1651 +0,0 @@ - - - - - DialogBasicSettings - - Basic Settings - تنظیمات پایه - - - Enable - فعال کردن - - - Listen Address - آدرس درحال شنود - - - concurrency - همزمانی - - - User Agent - عامل کاربر - - - Common - متداول - - - Style - استایل - - - Theme - پوسته - - - System - سیستم - - - Subscription - اشتراک - - - Core - هسته - - - Extra Core - هسته اضافی - - - Select - برگزیدن - - - Edit - ویرایش - - - Custom Inbound - ورودی سفارشی - - - Concurrent - هم زمان - - - Use proxy when updating subscription - استفاده از پروکسی زمانی که اشتراک را بروزرسانی می کنید - - - Security - امنیت security - امنیت - - - Statistics refresh rate - نرخ تازه سازی آمار ترافیک - - - Off - خاموش - - - Add - اضافه کردن - - - Delete - حذف - حذف کردن - - - Please input the core name. - لطفا نام هسته را وارد کنید - - - Please select the core name. - لطفا نام هسته را انتخاب کنید - - - Connection statistics - آمار اتصال - - - Include Pre-release when checking update - هنگام بررسی به‌روزرسانی، نسخه پیش‌انتشار را نیز لحاظ شود - - - System proxy format - فرمت پروکسی سیستم - - - Set custom icon - تنظیم آیکون سفارشی - - - Hide dashboard at startup - مخفی کردن داشبورد هنگام راه‌اندازی - - - Clear servers before updating subscription - قبل از به‌روزرسانی اشتراک، سرورها را پاک شود - - - Ignore TLS errors when updating subscription - هنگام به‌روزرسانی اشتراک، خطاهای TLS را نادیده گرفته شود - - - Advanced system proxy settings. Please select a format. - تنظیمات پیشرفته پروکسی سیستم. لطفا یک قالب را انتخاب کنید. - - - Please select a PNG file. - لطفاً یک فایل PNG انتخاب کنید. - - - Reset - بازنشانی - - - Cancel - لغو کردن - - - Please select a valid square image. - لطفاً یک تصویر مربع معتبر انتخاب کنید. - - - Max log lines - حداکثر خطوط فایل لاگ - - - Inbound Auth - اعتبار ورودی - - - Username - نام کاربری - - - Password - رمز عبور - - - Skip TLS certificate authentication by default (allowInsecure) - رد شدن از احراز هویت گواهی TLS به طور پیش فرض (allowInsecure) - - - Default uTLS Fingerprint - اثرانگشت پیشفرض uTLS - - - Core Options - تنظیمات هسته - - - Override underlying DNS - لغو دی ان اس زیربنایی - - - Default On - به صورت پیشفرض فعال - - - Multiplex (mux) - Multiplex (mux) - - - Latency Test URL - آدرس تست تاخیر - - - Download Test URL - آدرس تست دانلود - - - Timeout (s) - تایم اوت (به ثانیه) - - - Automatic update - آپدیت اتوماتیک - - - Interval (minute, invalid if less than 30) - فاصله (به دقیقا ، اگر کمتر از ۳۰ باشد نادرست است) - - - Share VMess Link with v2rayN Format - - - - Old Share Link Format - - - - Mixed (SOCKS+HTTP) Listen Port - - - - - DialogEditGroup - - Edit Group - ویرایش گروه - - - Type - نوع - - - Name - نام - - - Basic - پایه - - - Subscription - اشتراک - - - Archive - بایگانی - - - URL - URL - - - Copy profile share links - لینک های اشتراک گذاری نمایه را کپی کنید - - - Copy profile share links (Neko Links) - لینک های اشتراک گذاری نمایه را کپی کنید (لینک های Neko) - - - Warning - هشدار - - - Please input URL - لطفا URL را وارد کنید - - - Copied - کپی شده است - - - Manually column width - عرض ستون به صورت دستی - - - Front Proxy - پروکسی front - - - None - هیچ یک - - - Clear - پاک کردن - - - Skip automatic update - لغو آپدیت اتوماتیک - - - Common - متداول - - - Share - اشتراک گذاری - - - - DialogEditProfile - - Edit - ویرایش کردن - - - Common - متداول - - - Type - نوع - - - Port - پورت - - - Address - آدرس - - - Name - اسم - - - Settings - تنظیمات - - - The underlying transport method. It must be consistent with the server, otherwise, the connection cannot be established. - روش انتقال باید با سرور سازگار باشد، در غیر این صورت، اتصال نمی تواند برقرار شود. - - - Network - شبکه - - - Transport Layer Security. It must be consistent with the server, otherwise, the connection cannot be established. - امنیت لایه انتقال باید با سرور سازگار باشد، در غیر این صورت، اتصال نمی تواند برقرار شود. - - - Security - امنیت - - - UDP FullCone Packet encoding for implementing features such as UDP FullCone. Server support is required, if the wrong selection is made, the connection cannot be made. Please leave it blank. - - - - Packet Encoding - رمزنگاری بسته ها - - - Network Settings (%1) - تنظیمات شبکه (1%) - - - When enabled, V2Ray will not check the validity of the TLS certificate provided by the remote host (the security is equivalent to plaintext) - - - - Allow insecure - اجازه ناامن بودن - - - Certificate - گواهی - - - Server name indication, clear text. - شناسه نام سرور ، متن صریح - - - Application layer protocol negotiation, clear text. Please separate them with commas. - - - - Custom (Extra Core) - سفارشی ( هسته اضافه) - - - Not set - تنظیم نشده - - - Already set - تنظیم شده - - - TLS Security Settings - تنظیمات امنیت TLS - - - TLS Camouflage Settings - تنظیمات استتار TLS - - - Reality public key. If not empty, turn TLS into REALITY. - - - - Custom (%1 outbound) - - - - Custom (%1 config) - - - - Custom Outbound Settings - - - - Custom Config Settings - - - - Apply settings to this group - تنظیمات به این گروه اعمال شود - - - Multiplex - - - - Keep Default - نگه داری مقدار پیشفرض - - - On - فعال - - - Off - خاموش - - - Confirm - تایید - - - Server support is required - نیازمند پشتیبانی در سمت سرور - - - Reality short id. Accept only one value. - - - - - DialogHotkey - - Hotkey - کلید میانبر - - - Show routes - مسیرها را نمایش بده - - - Show groups - نمایش گروه ها - - - Trigger main window - نمایش پنجره اصلی - - - System Proxy - پروکسی سیستم - - - - DialogManageGroups - - Groups - گروه هاگروه ها - - - New group - گروه جدید - - - Update all subscriptions - به روز رسانی تمام اشتراک ها - - - Confirmation - تاییدیه - - - Update all subscriptions? - آیا همه اشتراک ها بروزرسانی شوند؟ - - - - DialogManageRoutes - - Routes - مسیرها - - - Sniffing Mode - - - - Disable - غیرفعال کردن - - - Remote DNS - دی ان اس سمت-سرور - - - Direct DNS - دی ان اس مستقیم - - - Enable DNS Routing - فعال کردن مسیریابی DNS - - - Block - مسدود کردن - - - Direct - مستقیم - - - Domain - دامنه - - - Proxy - پروکسی - - - IP - آی پی - - - Preset - پیشفرض - - - Mange route set - مدیریت مسیرها - - - Bypass LAN and China - عبور ندادن ترافیک LAN و کشور چین - - - Global - همگانی - - - Load - بارگیری - - - Save - ذخیره کردن - - - Remove - حذف کردن - - - Cancel - لغو کردن - - - Load routing: %1 - بارگیری مسیر : 1% - - - Save routing: %1 - ذخیره مسیر : 1% - - - Remove routing: %1 - حذف مسیر : 1% - - - Default Outbound - - - - Domain Strategy - استراتژی دامنه - - - Server Address Strategy - استراتژی آدرس سرور - - - Sniff result for routing - - - - Sniff result for destination - - - - Common - متداول - - - DNS - دی ان اس - - - Simple DNS Settings - تنظیمات دی ان اس ساده - - - Use DNS Object - - - - DNS Object Settings - - - - Simple Route - مسیر ساده - - - Custom Route - مسیر سفارشی - - - Custom Route (global) - - - - Note: Other settings are independent for each route set. - - - - Route sets - - - - Query Strategy - - - - Document - اسناد - - - Format - فرمت - - - This is especially important and it is recommended to use the default value of "localhost". -If the default value does not work, try changing it to "223.5.5.5". -For more information, see the document "Configuration/DNS". - - - - Final DNS Out - - - - - DialogVPNSettings - - Tun Settings - تنظیمات vpn - - - Hide Console - مخفی کردن کنسول - - - Tun Enable IPv6 - - - - Bypass CIDR - - - - Bypass Process Name - - - - Whether blacklisted or whitelisted, your traffic will be handled by nekobox_core (sing-tun). This is NOT equal to "process mode" of some software. - - - - Whitelist mode - حالت لیست سفید - - - Proxy CIDR - - - - Proxy Process Name - نام پروسه پراکسی - - - Troubleshooting - عیب یابی - - - If you have trouble starting VPN, you can force reset nekobox_core process here. - -If still not working, see documentation for more information. -https://matsuridayo.github.io/n-configuration/#vpn-tun - - - - Reset - بازنشانی - - - Cancel - لغو کردن - - - Internal Tun - حالت تونل داخلی - - - Add a tun inbound to the profile startup, instead of using two processes. -This needs to be run NekoBox with administrator privileges. - - - - - EditChain - - Traffic order is from top to bottom - عبور ترافیک از بالا به پایین است - - - Select Profile - انتخاب کردن پروفایل - - - Name cannot be empty. - نام نمیتواند خالی باشد - - - - EditCustom - - Core - هسته - - - Json Editor - ویرایشگر Json - - - Command - فرمان - - - Config Suffix - پسوند کانفیگ - - - Outbound JSON, please read the documentation. - JSON خروجی، لطفاً مستندات را بخوانید. - - - Please pick a core. - لطفا یک هسته انتخاب کنید. - - - Random if it's empty or zero. - - - - Preview - پیش نمایش - - - Preview replace - - - - Preview config - - - - Please fill the complete config. - - - - Name cannot be empty. - نام نمیتواند خالی باشد - - - - EditNaive - - Protocol - پروتکل - - - Password - رمزعبور - - - Extra headers - - - - SNI - - - - Username - نام کاربری - - - Certificate - گواهی - - - Insecure concurrency - همزمانی ناامن - - - Disable logs - - - - Turn on this option if your connection is lost after a while - - - - - EditQUIC - - Certificate - گواهی - - - Download (Mbps) - دانلود (مگابیت بر ثانیه) - - - Disable MTU Discovery - - - - Hop Interval (s) - - - - Allow Insecure - اجازه ارتباطات ناامن داده شود - - - Hop Port - - - - Upload (Mbps) - آپلود (مگابیت بر ثانیه) - - - Obfs Password - - - - SNI - - - - Disable SNI - - - - Password - - - - Generate UUID - - - - Heartbeat - - - - Zero Rtt Handshake - - - - Congestion Control - - - - UDP Relay Mode - - - - Force use external core - - - - - EditShadowSocks - - Plugin Args - - - - Password - کلمه عبور - - - Encryption - رمزگذاری - - - Plugin - پلاگین - - - Version of UDP over TCP protocol, server support is required. - - - - Off - خاموش - - - - EditSocksHttp - - Version - نسخه - - - Username - نام کاربری - - - Password - کلمه عبور - - - - EditTrojanVLESS - - Password - کلمه عبور - - - - EditVMess - - Alter Id - - - - Security - امنیت - - - UUID - - - - Generate UUID - - - - - GroupItem - - Update Subscription - به روز رسانی اشتراک - - - Edit - ویرایش - - - Remove - حذف کردن - - - Basic - پایه - - - Subscription - اشتراک - - - Archive - آرشیو - - - Last update: %1 - آخرین آپدیت : %1 - - - Confirmation - تایید - - - Remove %1? - حذف %1? - - - - JsonEditor - - JSON Editor - ویرایشگر JSON - - - Format JSON - فرمت JSON - - - Remove All Comments - حذف همه کامنت ها - - - Json Editor - ویرایشگر Json - - - Structure Preview - پیش نمایش ساختار - - - OK - تایید - - - Json Contains Syntax Errors - - - - Original Json may contain syntax errors. Json tree is disabled. - - - - You must correct these errors before continuing. - شما باید این ایرادات را قبل از ادامه دادن اصلاح کنید - - - Syntax Errors - خطاهای نحوی - - - Please fix the JSON errors or remove the comments before continue - لطفا قبل از ادامه دادن ایرادات JSON را اصلاح کنید یا کامنت ها را حذف کنید - - - - MainWindow - - Program - برنامه - - - Preferences - تنظیمات - - - Server - سرور - - - Ads - تبلیغات - - - Document - اسناد - - - Update - بروزرسانی - - - Tun Mode - حالتvpn - - - System Proxy - پروکسی سیستمی - - - Type - نوع - - - Address - آدرس - - - Name - اسم - - - Test Result - نتیجه تست - - - Traffic - ترافیک - - - Log - ثبت رویدادها - - - Connection - اتصال - - - Status - وضعیت - - - Outbound - خروجی - - - Destination - مقصد - - - Active Server - سرور فعال - - - Active Routing - مسیریابی فعال - - - Share - اشتراک گذاری - - - Current Group - گروه فعلی - - - Exit - خروج - - - Basic Settings - تنظیمات پایه - - - New profile - پروفایل جدید - - - Groups - گروه ها - - - Start - آغازکردن - - - Stop - متوقف کردن - - - Routing Settings - تنظیمات مسیریابی - - - Add profile from clipboard - افزودن پروفایل از کلیپ بورد - - - Delete - از بین بردن - - - Debug Info - اطلاعات اشکال زدایی - - - QR Code and link - کد QR و پیوند - - - Copy Link - لینک را کپی کنید - - - Clear Test Result - نتایج تست پاک شود - - - Export %1 config - - - - Reset Traffic - بازنشانی ترافیک - - - Scan QR Code - کد QR را اسکن کنید - - - Enable System Proxy - پروکسی سیستم را فعال کنید - - - Disable - غیرفعال کردن - - - Remove Duplicates - موارد تکراری را حذف کردن - - - fake - جعلی - - - Move - جابجایی - - - Start with system - با سیستم شروع شود - - - Remember last profile - آخرین پروفایل را به خاطر بسپار - - - Allow other devices to connect - به دستگاه های دیگر اجازه اتصال دهید - - - Remove Unavailable - غیرقابل دستیابی پاک شود - - - Full Test - تست کامل - - - Hotkey Settings - تنظیمات کلید میانبر - - - Select All - انتخاب همه - - - Copy links of selected (Neko Links) - کپی لینک های انتخاب شده (پیوندهای Neko) - - - Copy links of selected - لینک های انتخاب شده را کپی کنید - - - Enable Tun - فعال کردن tun - - - Clone - همزادسازی - - - Update subscription - اشتراک را به روز کنید - - - Resolve domain - دامنه را حل کنید - - - Tun Settings - تنظیمات vpn - - - Restart Program - اجرا دوباره برنامه - - - Open Config Folder - پوشه Config باز شود - - - Load routing and apply: %1 - - - - Error - خطا - - - Tun Settings changed - تنظیمات Tun تغییر کرد - - - Restart Tun to take effect. - Tun را مجدداً راه اندازی کنید تا اعمال شود. - - - Confirmation - تائیدیه - - - Settings changed, restart proxy? - تنظیمات تغییر کرد، پراکسی راه اندازی مجدد شود؟ - - - Imported %1 profile(s) - - - - Current server is incompatible with Tun. Please stop the server first, enable Tun Mode, and then restart. - - - - Not Running - در حال اجرا نیست - - - Select - انتخاب - - - Clone %1 item(s) - - - - Move %1 item(s) - - - - Remove %1 item(s) ? - - - - Copied %1 item(s) - - - - Config copied - کانفیگ کپی شد - - - QR Code not found - کد QR یافت نشد - - - Resolving domain to IP, if support. - - - - Set ignore keyword - کلیدواژه نادیده گرفتن را تنظیم کنید - - - Set the following keywords to ignore? -Split by line. - - - - Save as route - ذخیره به عنوان مسیر - - - Edit - ویرایش کردن - - - Save "%1" as a routing rule? - - - - Clear - پاک کردن - - - Start: %1 -End: %2 - - - - Failed to stop Tun process - فرآیند Tun متوقف نشد - - - [%1] test error: %2 - - - - Testing - آزمایش کردن - - - Unavailable - غیرقایل دسترسی - - - Starting profile %1 - اغاز پروفایل %1 - - - Stopping profile %1 - متوقف کردن پروفایل %1 - - - Current Select - انتخاب فعلی - - - Show Window - نمایش پنجره برنامه - - - Settings changed - تنظیمات تغییر کرد - - - Please run NekoBox as admin - لطفا Nekobox را با مجوز ادمین اجرا کنید - - - Restart Proxy - راه اندازی مجدد پروکسی - - - If there is no response for a long time, it is recommended to restart the software. - اگر برای مدت زمان طولانی هیچ پاسخی دریافت نشد ، پیشنهاد میشود که نرم افزار را دوباره اجرا کنید - - - Failed to start profile %1 - - - - Failed to stop, please restart the program. - توقف ناموفق بود ، لطفا برنامه را دوباره اجرا کنید - - - Select mode, double-click or press Enter to select a profile, press ESC to exit. - - - - Latency - تاخیر - - - UDP latency - - - - Download speed - سرعت دانلود - - - In and Out IP - - - - Test Options - گزینه های تست - - - Restart the program to take effect. - برای مشاهده نتیجه برنامه را دوباره راه اندازی کنید - - - Stop Testing - - - - URL Test - - - - - ProxyItem - - Confirmation - تائیدیه - - - Remove %1? - حذف %1? - - - - QGuiApplication - - QT_LAYOUT_DIRECTION - RTL - - - - QObject - - Used: %1 Remain: %2 Expire: %3 - - - - Select - انتخاب کردن - - - Update - بروزرسانی - - - No update - بدون بروزرسانی جدید - - - Update found: %1 -Release note: -%2 - - - - Open in browser - در مرور گر باز شود - - - Close - بستن - - - Update is ready, restart to install? - به روز رسانی آماده است، برای نصب مجدد راه اندازی شود؟ - - - As link - به عنوان لینک - - - url detected - آدرس شناسایی شد - - - %1 -How to update? - چگونه بروزرسانی کنم ؟ - - - Requesting subscription: %1 - - - - Requesting subscription %1 error: %2 - - - - Clearing servers... - پاک کردن سرورها - - - Added %1 profiles: -%2 -Deleted %3 Profiles: -%4 - - - - Nothing - خالی - - - Change of %1: - - - - Chain Proxy - پروکسی زنجیره ای - - - Core not found: %1 - هسته برنامه یافت نشد : %1 - - - Proxy: %1 -Direct: %2 - - - - Unavailable - غیرقابل دسترس - - - Request with proxy but no profile started. - - - - Subscription request fininshed: %1 - - - - Core exited, restarting. - هسته برنامه متوقف شد ، در حال راه اندازی مجدد - - - Core exits too frequently, stop automatic restart this profile. - - - - As Subscription (create new group) - - - - As Subscription (add to this group) - - - - Default - پیش فرض - - - The last speed test did not exit completely, please wait. If it persists, please restart the program. - - - - - Qv2ray::ui::widgets::AutoCompleteTextEdit - - You can not input space characters here. - شما نمی توانید کاراکتر فضای خالی در اینجا استفاده کنید. - - - diff --git a/translations/ru_RU.ts b/translations/ru_RU.ts deleted file mode 100644 index 7abdd86..0000000 --- a/translations/ru_RU.ts +++ /dev/null @@ -1,1664 +0,0 @@ - - - - - DialogBasicSettings - - Basic Settings - Основные настройки - - - Common - Общие - - - Listen Address - Адрес входящих подключений - - - Custom Inbound - Кастомный inbound - - - Edit - Изменить - - - Enable - Вкл - - - Latency Test URL - URL теста задержки - - - Concurrent - Параллельно - - - Download Test URL - URL теста загрузки - - - Include Pre-release when checking update - Проверять пре-релизы при обновлениях - - - System proxy format - Формат строки системного прокси - - - Style - Стиль - - - Theme - Тема - - - System - Системная - - - Set custom icon - Задать иконку - - - Statistics refresh rate - Период обновления статистики - - - Off - Выкл - - - Connection statistics - Статистика подключений - - - Hide dashboard at startup - Спрятать окно при старте - - - Max log lines - Макс. строк в логе - - - Subscription - Подписка - - - User Agent - User Agent - - - Use proxy when updating subscription - Использовать прокси при обновлении подписок - - - Ignore TLS errors when updating subscription - Игнорировать ошибки TLS при обновлении подписок - - - Clear servers before updating subscription - Очищать список серверов при обновлении подписок - - - Core - Ядро - - - Select - Выбрать - - - Multiplex (mux) - Мультиплексирование (mux) - - - concurrency - многопоточность - - - Default On - Вкл. по умолчанию - - - Core Options - Параметры ядра - - - Extra Core - Дополнительные ядра - - - Add - Добавить - - - Delete - Удалить - - - Security - Безопасность - - - Skip TLS certificate authentication by default (allowInsecure) - Не проверять подлинность TLS сертификатов по умолчанию - - - Default uTLS Fingerprint - uTLS fingerprint по умолчанию - - - Advanced system proxy settings. Please select a format. - Дополнительные настройки системного прокси. Пожалуйста, выберите формат. - - - Please input the core name. - Введите имя ядра. - - - Please select the core name. - Выберите имя ядра. - - - Please select a PNG file. - Выберите PNG файл - - - Reset - Сброс - - - Cancel - Отмена - - - Please select a valid square image. - Пожалуйста, выберите корректное квадратное изображение. - - - Inbound Auth - Аутентификация inbound - - - Username - Имя пользователя - - - Password - Пароль - - - Override underlying DNS - Переопределить нижестоящий DNS - - - Timeout (s) - Таймаут (с) - - - Automatic update - Автоматическое обновление - - - Interval (minute, invalid if less than 30) - Интервал (в минутах, значение считается неправильным, если меньше 30) - - - Share VMess Link with v2rayN Format - Поделиться ссылкой VMess в формате v2rayN - - - Old Share Link Format - Поделиться ссылкой в старом формате - - - Mixed (SOCKS+HTTP) Listen Port - - - - - DialogEditGroup - - Edit Group - Изменить группу - - - Name - Имя - - - Manually column width - Уст. ширину колонок - - - Archive - Архив - - - Type - Тип - - - Basic - Простая - - - Subscription - Подписка (subscription) - - - Front Proxy - Фронт-прокси - - - Clear - Сбросить - - - URL - URL - - - Copy profile share links - Скопировать ссылки на профиль - - - Copy profile share links (Neko Links) - Скопировать ссылки на профиль (Neko links) - - - Copied - Скопировано - - - Warning - Предупреждение - - - Please input URL - Пожалуйста, введите URL - - - None - Нет - - - Skip automatic update - Пропустить автоматическое обновление - - - Common - Общие - - - Share - Поделиться - - - - DialogEditProfile - - Edit - Редактировать - - - Common - Общие - - - Type - Тип - - - Port - Порт - - - Address - Адрес - - - Name - Имя - - - Custom Outbound Settings - Доп. настройки outbound - - - Custom Config Settings - Доп. настройки конфига - - - Apply settings to this group - Применить настройки к этой группе - - - Settings - Настройки - - - The underlying transport method. It must be consistent with the server, otherwise, the connection cannot be established. - Нижележащий транспорт. Должен соответствовать конфигурации сервера, иначе подключение будет невозможно. - - - Network - Транспорт - - - Transport Layer Security. It must be consistent with the server, otherwise, the connection cannot be established. - TLS. Должно совпадать с параметрами сервера, иначе подключение будет невозможно. - - - Security - Безопасность - - - UDP FullCone Packet encoding for implementing features such as UDP FullCone. Server support is required, if the wrong selection is made, the connection cannot be made. Please leave it blank. - UDP FullCone кодирование пакетов для реализации функционала типа UDP FullCone. Необходима поддержка со стороны сервера, при неправильном выборе подключение не будет работать. Оставьте пустым, если вы не знаете что и зачем это. - - - Packet Encoding - Кодирование пакетов - - - Server support is required - Необходима поддержка со стороны сервера - - - Multiplex - Мультиплексирование - - - Keep Default - По умолчанию - - - On - Вкл - - - Off - Выкл - - - Network Settings (%1) - Настройки транспорта (%1) - - - TLS Security Settings - Настройки TLS - - - When enabled, V2Ray will not check the validity of the TLS certificate provided by the remote host (the security is equivalent to plaintext) - Если вкл., то клиент не будет проверять валидность TLS-сертификата, предоставленного сервером - - - Allow insecure - Разрешить небезопасн. - - - Certificate - Сертификат - - - Server name indication, clear text. - SNI (идентификатор сервера, передается в открытом виде). - - - Application layer protocol negotiation, clear text. Please separate them with commas. - ALPN, идентификатор протокола приложения, передается открытым текстом. Используйте запятую в качестве разделителя. - - - TLS Camouflage Settings - Настройки маскировки TLS - - - Reality public key. If not empty, turn TLS into REALITY. - Публичный ключ Reality. Если задано значение, то будет использован протокол Reality для TLS. - - - Reality short id. Accept only one value. - Короткий ID для Reality. Можно задать только одно значение. - - - Custom (%1 outbound) - Кастомный (%1 outbound) - - - Custom (%1 config) - Кастомный (%1 конфиг) - - - Custom (Extra Core) - Кастомный (доп. ядро) - - - Not set - Не задано - - - Already set - Уже задано - - - Confirm - Подтвердить - - - - DialogHotkey - - Hotkey - Горячие клавиши - - - Show routes - Показать маршруты - - - Show groups - Показать группы - - - Trigger main window - Показать главное окно - - - System Proxy - Режим системного прокси - - - - DialogManageGroups - - Groups - Группы - - - New group - Новая группа - - - Update all subscriptions - Обновить все подписки - - - Confirmation - Подтвердить - - - Update all subscriptions? - Обновить все подписки? - - - - DialogManageRoutes - - Routes - Маршруты - - - Common - Общие - - - Route sets - Набор маршрутов - - - Mange route set - Изменить набор маршрутов - - - Custom Route (global) - Кастомные маршруты (global) - - - Note: Other settings are independent for each route set. - Остальные настройки будут индивидуальны -для каждого набора маршрутов. - - - Domain Strategy - Стратегия доменов - - - Disable - Выкл - - - Sniff result for routing - Подслушивать для маршрутизации - - - Sniff result for destination - Подслушивать для точки назначения - - - Sniffing Mode - Режим подслушивания - - - Server Address Strategy - Стратегия выбора адреса сервера - - - DNS - DNS - - - Simple DNS Settings - Базовые настройки DNS - - - Direct DNS - DNS для "прямых" запросов - - - Query Strategy - Стратегия запросов - - - Remote DNS - Удаленный (remote) DNS - - - Enable DNS Routing - Вкл. DNS-маршрутизацию - - - DNS Object Settings - Специальные настройки DNS - - - Use DNS Object - Использовать DNS-объект - - - Format - Форматировать - - - Document - Помощь - - - Simple Route - Базовые маршруты - - - Block - Блок - - - Direct - Напрямую - - - Domain - Домен - - - Proxy - Прокси - - - IP - IP - - - Preset - Пресет - - - Custom Route - Кастомные маршруты - - - Default Outbound - Outbound по-умолчанию - - - Bypass LAN and China - Пропускать LAN и китайские ресурсы - - - Global - Глобально - - - Load - Загрузить - - - Save - Сохранить - - - Remove - Удалить - - - Cancel - Отменить - - - Load routing: %1 - Загрузить машруты: %1 - - - Save routing: %1 - Сохранить маршруты: %1 - - - Remove routing: %1 - Удалить маршруты: %1 - - - This is especially important and it is recommended to use the default value of "localhost". -If the default value does not work, try changing it to "223.5.5.5". -For more information, see the document "Configuration/DNS". - - - - Final DNS Out - - - - - DialogVPNSettings - - Tun Settings - Настройки Tun - - - Tun Enable IPv6 - Вкл. IPv6 в Tun - - - Add a tun inbound to the profile startup, instead of using two processes. -This needs to be run NekoBox with administrator privileges. - Добавить inbound c Tun в конфигурацию профиля вместо того, чтобы использовать два отдельных процесса. -Для этого необходимо запускать NekoBox c правами администратора. - - - Internal Tun - Встроен. Tun - - - Hide Console - Скрывать окно - - - Bypass CIDR - Пропускать CIDR - - - Bypass Process Name - Пропускать процессы - - - Whether blacklisted or whitelisted, your traffic will be handled by nekobox_core (sing-tun). This is NOT equal to "process mode" of some software. - При использовании белого или черного списка, ваш трафик будет обработан ядром nekobox (sign-tun). Это НЕ эквивалент "process mode" как в некотором ПО. - - - Whitelist mode - Режим белого списка - - - Troubleshooting - Исправление проблем - - - Proxy CIDR - Проксировать CIDR - - - Proxy Process Name - Проксировать процессы - - - If you have trouble starting VPN, you can force reset nekobox_core process here. - -If still not working, see documentation for more information. -https://matsuridayo.github.io/n-configuration/#vpn-tun - Если у вас проблемы с запуском VPN, можно принудительно перезапустить процесс nekobox-core. - -Если ничего по-прежнему не работает, ознакомьтесь с документацией: -https://matsuridayo.github.io/n-configuration/#vpn-tun - - - Reset - Перезапустить - - - Cancel - Отмена - - - - EditChain - - Traffic order is from top to bottom - Порядок трафика сверху вниз - - - Select Profile - Выбор профиля - - - Name cannot be empty. - Имя не может быть пустым. - - - - EditCustom - - Core - Ядро - - - Json Editor - Редактор JSON - - - Command - Команда - - - Config Suffix - Суффикс конфига - - - Random if it's empty or zero. - Если пусто или 0, то будет выбран случайным образом. - - - Preview - Предпросмотр - - - Outbound JSON, please read the documentation. - Outbound JSON, читайте документацию. - - - Please fill the complete config. - Пожалуйста, введите полную конфигурацию. - - - Preview replace - Предпросмотр замен - - - Preview config - Предпросмотр конфигурации - - - Name cannot be empty. - Имя не может быть пустым. - - - Please pick a core. - Пожалуйста, выберите ядро. - - - - EditNaive - - Protocol - Протокол - - - Password - Пароль - - - Extra headers - Дополнительные заголовки - - - SNI - SNI - - - Username - Имя пользователя - - - Certificate - Сертификат - - - Insecure concurrency - - - - Disable logs - - - - Turn on this option if your connection is lost after a while - - - - - EditQUIC - - Download (Mbps) - Скорость приема (Mbps) - - - Disable MTU Discovery - Выкл. MTU discovery - - - Hop Interval (s) - - - - Certificate - Сертификат - - - Allow Insecure - Разрешить небезопасные - - - Hop Port - - - - Upload (Mbps) - Скорость отдачи (Mbps) - - - Obfs Password - Пароль для обфускации - - - SNI - SNI - - - Disable SNI - Отключить SNI - - - Password - Пароль - - - Generate UUID - Сгенерировать UUID - - - Heartbeat - Сердцебиение (Hearbeat) - - - Zero Rtt Handshake - Без рукопожатия Rtt - - - Congestion Control - Управление перегрузкой - - - UDP Relay Mode - Режим UDP Relay - - - Force use external core - - - - - EditShadowSocks - - Encryption - Шифрование - - - Plugin - Плагин - - - Password - Пароль - - - Plugin Args - Аргументы - - - Version of UDP over TCP protocol, server support is required. - Версия протокола "UDP over TCP", требуется поддержка со стороны сервера. - - - Off - Выкл - - - - EditSocksHttp - - Version - Версия - - - Username - Имя пользователя - - - Password - Пароль - - - - EditTrojanVLESS - - Password - Пароль - - - - EditVMess - - Security - Шифрование - - - Alter Id - Альт. ID - - - UUID - UUID - - - Generate UUID - Сгенерировать UUID - - - - GroupItem - - Update Subscription - Обновить - - - Edit - Изменить - - - Remove - Удалить - - - Basic - Простая - - - Subscription - Подписка - - - Archive - Архив - - - Last update: %1 - Последнее обновление: %1 - - - Confirmation - Подтверждение - - - Remove %1? - Удалить %1? - - - - JsonEditor - - JSON Editor - Редактор JSON - - - Format JSON - Форматировать JSON - - - Remove All Comments - Удалить все комментарии - - - Json Editor - Редактор JSON - - - Structure Preview - Предпросмотр структуры - - - OK - OK - - - Json Contains Syntax Errors - JSON содержит синтаксические ошибки - - - Original Json may contain syntax errors. Json tree is disabled. - Кажется, оригинальный JSON содержит синтатсические ошибки. Дерево JSON отключено. - - - You must correct these errors before continuing. - Вы должны исправить эти ошибки чтобы продолжить. - - - Syntax Errors - Синтаксические ошибки - - - Please fix the JSON errors or remove the comments before continue - Пожалуйста, чтобы продолжить, исправьте ошибки в JSON или удалите комментарии - - - - MainWindow - - Program - Программа - - - Preferences - Настройки - - - Server - Сервер - - - Ads - Реклама - - - Document - Документация - - - Update - Обновление - - - Tun Mode - Режим TUN - - - System Proxy - Режим системного прокси - - - Type - Тип - - - Address - Адрес - - - Name - Имя - - - Test Result - Результат теста - - - Traffic - Трафик - - - Log - Журнал - - - Connection - Подключение - - - Status - Статус - - - Outbound - Outbound - - - Destination - Пункт назначения - - - Active Server - Активный сервер - - - Active Routing - Активное правило роутинга - - - Share - Поделиться - - - Current Group - Текущая группа - - - Current Select - Текущий выбор - - - Exit - Выход - - - Show Window - Показать окно - - - Basic Settings - Основные настройки - - - New profile - Новый профиль - - - Groups - Группы - - - Start - Запустить - - - Stop - Остановить - - - Routing Settings - Настройки маршрутов - - - Add profile from clipboard - Добавить профиль из буфера обмена - - - Delete - Удалить - - - Debug Info - Отладочная информация - - - QR Code and link - QR-код и ссылка - - - Copy Link - Скопировать ссылку - - - Clear Test Result - Очистить результат теста - - - Export %1 config - Экспортировать конфиг %1 - - - Reset Traffic - Сбросить трафик - - - Scan QR Code - Сканировать QR-код - - - Enable System Proxy - Активировать системный прокси - - - Disable - Отключить - - - Remove Duplicates - Удалить дубликаты - - - fake - фейк - - - Move - Переместить - - - Start with system - Запускаться вместе с системой - - - Remember last profile - Запомнить последний профиль - - - Allow other devices to connect - Разрешить подключаться другим устройствам - - - Remove Unavailable - Удалить недоступные - - - Full Test - Полный тест - - - Hotkey Settings - Настройки комбинаций клавиш - - - Select All - Выбрать всё - - - Copy links of selected (Neko Links) - Скопировать ссылки для выбранных (Neko links) - - - Copy links of selected - Скопировать ссылки для выбранных - - - Enable Tun - Включить TUN-режим - - - Clone - Клонировать - - - Update subscription - Обновить подписки - - - Resolve domain - Ну слово "разрешить" можно использоваться и в значении "разобраться" - Разрешить доменное имя - - - Tun Settings - Настройки TUN-режима - - - Restart Program - Перезапустить программу - - - Open Config Folder - Открыть папку с конфигами - - - Restart Proxy - Перезапустить прокси - - - Load routing and apply: %1 - Загрузить маршруты и активировать: %1 - - - Error - Ошибка - - - Tun Settings changed - Настройки TUN изменились - - - Restart Tun to take effect. - Перезапустите TUN чтобы применить изменения. - - - Confirmation - Подтверждение - - - Settings changed, restart proxy? - Настройки изменены, перезапустить прокси? - - - Settings changed - Настройки изменены - - - Restart the program to take effect. - Перезапустите программу чтобы новые настройки вступили в силу. - - - Imported %1 profile(s) - Импортирован(ы) %1 профиль(ей) - - - Please run NekoBox as admin - Пожалуйста, запустите NekoBox с правами администратора - - - Current server is incompatible with Tun. Please stop the server first, enable Tun Mode, and then restart. - Текущий сервер не совместим с TUN-режимом. Пожалуйста, сначала остановите подключение к серверу, активируйте TUN-режим, и потом перезапустите. - - - Not Running - Не запущен - - - Select - Выбор - - - Select mode, double-click or press Enter to select a profile, press ESC to exit. - Режим выбора, дважды кликните или нажмите Enter для выбора профиля, либо ESC чтобы выйти. - - - Clone %1 item(s) - Клонировать %1 записей - - - Move %1 item(s) - Переместить %1 записей - - - Remove %1 item(s) ? - Удалить %1 записей ? - - - Copied %1 item(s) - Скопировано %1 записей - - - Config copied - Конфиг скопирован - - - QR Code not found - QR-код не найден - - - Resolving domain to IP, if support. - Отрезолвить домен в IP-адрес, если поддерживается. - - - Set ignore keyword - Ключевые слова для игнорирования - - - Set the following keywords to ignore? -Split by line. - Задайте ключнвые слова для игнорирования, -каждое на отдельной строке. - - - Save as route - Сохранить как маршрут - - - Edit - Редактировать - - - Save "%1" as a routing rule? - Сохранить "%1" как профиль маршрутизации? - - - Clear - Очистить - - - Start: %1 -End: %2 - Начало %1 -Конец %2 - - - Failed to stop Tun process - Не удалось остановить TUN-процесс - - - Test Options - Параметры тестирования - - - Latency - Задержка - - - UDP latency - Задержка UDP - - - Download speed - Скорость загрузки - - - In and Out IP - Входящий и исходящий IP - - - [%1] test error: %2 - [%1] ошибка теста: %2 - - - Testing - Тестируем - - - Unavailable - Недоступен - - - If there is no response for a long time, it is recommended to restart the software. - Если нет ответа в течении долгого времени, рекомендуем перезапустить приложение. - - - Starting profile %1 - Запускаем профиль %1 - - - Failed to start profile %1 - Не удалось запустить профиль %1 - - - Stopping profile %1 - Останавливаем профиль %1 - - - Failed to stop, please restart the program. - Не удалось остановить, пожалуйста, перезапустите приложение. - - - Stop Testing - - - - URL Test - - - - - ProxyItem - - Confirmation - Подтверждение - - - Remove %1? - Удалить %1? - - - - QGuiApplication - - QT_LAYOUT_DIRECTION - - - - - QObject - - Core not found: %1 - Ядро не найдено: %1 - - - Unavailable - Недоступно - - - Proxy: %1 -Direct: %2 - Через прокси: %1 -Напрямую: %2 - - - Chain Proxy - Цепочка прокси - - - Request with proxy but no profile started. - Запрос через прокси, но профиль не запущен. - - - As Subscription (add to this group) - Как подписку (добавить в эту группу) - - - As Subscription (create new group) - Как подписку (создать новую группу) - - - As link - Как ссылку - - - url detected - Обнаружен URL - - - %1 -How to update? - %1 -Как обновить? - - - Requesting subscription: %1 - Запрашиваем подписку: %1 - - - Requesting subscription %1 error: %2 - Запрашиваем подписку %1 ошибка: %2 - - - Subscription request fininshed: %1 - Запрос подписки завершен: %1 - - - Clearing servers... - Очишаем серверы... - - - Added %1 profiles: -%2 -Deleted %3 Profiles: -%4 - Добавлено %1 профилей: -%2 -Удалено %3 профилей: -%4 - - - Nothing - Ничего - - - Change of %1: - Изменение %1: - - - Core exits too frequently, stop automatic restart this profile. - Ядро слишком часто прекращает свою работу, отмена автоматического перезапуска этого профиля. - - - Core exited, restarting. - Ядро прекратило свою работу, перезапуск. - - - Select - Выбор - - - Update - Обновление - - - No update - Нет обновлений - - - Update found: %1 -Release note: -%2 - Найдено обновление: %1 -Примечания к выпуску: -%2 - - - Open in browser - Открыть в браузере - - - Close - Закрыть - - - Update is ready, restart to install? - Обновление готово, перезапуститься для установки? - - - Used: %1 Remain: %2 Expire: %3 - Использовано: %1, осталось: %2, истекло: %3 - - - Default - По умолчанию - - - The last speed test did not exit completely, please wait. If it persists, please restart the program. - - - - - Qv2ray::ui::widgets::AutoCompleteTextEdit - - You can not input space characters here. - Сюда нельзя вводить пробелы. - - - diff --git a/translations/translations.qrc b/translations/translations.qrc deleted file mode 100644 index 44f03db..0000000 --- a/translations/translations.qrc +++ /dev/null @@ -1,7 +0,0 @@ - - - zh_CN.qm - fa_IR.qm - ru_RU.qm - - diff --git a/translations/zh_CN.ts b/translations/zh_CN.ts deleted file mode 100644 index 8a9f13a..0000000 --- a/translations/zh_CN.ts +++ /dev/null @@ -1,1664 +0,0 @@ - - - - - DialogBasicSettings - - Basic Settings - 基本设置 - - - Enable - 启用 - - - Listen Address - 监听地址 - - - concurrency - 并发 - - - User Agent - - - - Common - 通用 - - - Style - 样式 - - - Theme - 主题 - - - System - 系统 - - - Subscription - 订阅 - - - Core - 核心 - - - Extra Core - 其他核心 - - - Select - 选择 - - - Edit - 编辑 - - - Custom Inbound - 自定义入站 - - - Concurrent - 并发 - - - Use proxy when updating subscription - 更新订阅时使用代理 - - - Security - 安全 - - - Statistics refresh rate - 流量统计刷新率 - - - Off - 关闭 - - - Add - 添加 - - - Delete - 删除 - - - Please input the core name. - 请输入核心名. - - - Please select the core name. - 请选择核心名. - - - Connection statistics - 连接统计 - - - Include Pre-release when checking update - 检查更新时包括 Pre-release 版本 - - - Set custom icon - 自定义图标 - - - Please select a PNG file. - 请选择一个 PNG 文件。 - - - Reset - 重置 - - - Please select a valid square image. - 请选择有效的正方形图像。 - - - Cancel - 取消 - - - System proxy format - 系统代理格式 - - - Advanced system proxy settings. Please select a format. - 高级系统代理设置。请选择一种格式。 - - - Old Share Link Format - 旧分享链接格式 - - - Share VMess Link with v2rayN Format - 用 v2rayN 的格式分享 VMess 链接 - - - Clear servers before updating subscription - 更新订阅前清除服务器 - - - Ignore TLS errors when updating subscription - 更新订阅时忽略 TLS 错误 - - - Hide dashboard at startup - 启动时不显示仪表盘 - - - Max log lines - 日志最大行数限制 - - - Inbound Auth - 入站认证设置 - - - Username - 用户名 - - - Password - 密码 - - - Skip TLS certificate authentication by default (allowInsecure) - 默认跳过 TLS 证书验证 (allowInsecure) - - - Default uTLS Fingerprint - 默认 uTLS 指纹 - - - Core Options - 核心选项 - - - Override underlying DNS - 覆盖底层 DNS - - - Default On - 默认开启 - - - Multiplex (mux) - 多路复用 Mux - - - Latency Test URL - 延迟测试 URL - - - Download Test URL - 下载测试 URL - - - Timeout (s) - 超时(秒) - - - Automatic update - 自动更新订阅 - - - Interval (minute, invalid if less than 30) - 时间间隔(分钟,少于 30 分钟无效) - - - Mixed (SOCKS+HTTP) Listen Port - Mixed (SOCKS+HTTP) 监听端口 - - - - DialogEditGroup - - Edit Group - 编辑分组 - - - Type - 类型 - - - Name - 名称 - - - Basic - 基本 - - - Subscription - 订阅 - - - URL - - - - Archive - 归档 - - - Warning - 警告 - - - Please input URL - 请输入 URL - - - Copy profile share links - 复制分组内配置的分享链接 - - - Copied - 复制成功 - - - Copy profile share links (Neko Links) - 复制分组内配置的分享链接 (Neko Links) - - - Manually column width - 手动调节列宽 - - - Front Proxy - 前置代理 - - - None - - - - Clear - 清除 - - - Skip automatic update - 跳过自动更新 - - - Common - 通用 - - - Share - 分享 - - - - DialogEditProfile - - Edit - 编辑 - - - Common - 通用 - - - Type - 类型 - - - Port - 端口 - - - Address - 地址 - - - Name - 名称 - - - Network - 传输 - - - Security - 传输层安全 - - - Network Settings (%1) - 传输设置 (%1) - - - The underlying transport method. It must be consistent with the server, otherwise, the connection cannot be established. - 底层传输方式。必须与服务器一致,否则无法建立连接。 - - - Transport Layer Security. It must be consistent with the server, otherwise, the connection cannot be established. - 传输层安全。必须与服务器一致,否则无法建立连接。 - - - UDP FullCone Packet encoding for implementing features such as UDP FullCone. Server support is required, if the wrong selection is made, the connection cannot be made. Please leave it blank. - 包编码,用于实现 UDP FullCone 等特性。需要服务器支持,选错无法连接。不懂请留空。 - - - When enabled, V2Ray will not check the validity of the TLS certificate provided by the remote host (the security is equivalent to plaintext) - 开启后 V2Ray 不会检查远端主机所提供的 TLS 证书的有效性(安全性相当于明文) - - - Server name indication, clear text. - 服务器名称指示,明文。 - - - Application layer protocol negotiation, clear text. Please separate them with commas. - 应用层协议协商,明文。多个请以英文逗号分隔。 - - - Allow insecure - 不检查服务器证书 - - - Certificate - 证书 - - - Not set - 未设置 - - - Already set - 已设置 - - - Packet Encoding - 包编码 - - - Settings - 设置 - - - Custom (Extra Core) - 自定义 (其他核心) - - - TLS Security Settings - TLS 安全设置 - - - TLS Camouflage Settings - TLS 伪装设置 - - - Reality public key. If not empty, turn TLS into REALITY. - Reality public key. 如果不为空,则将 TLS 变为 REALITY。 - - - Custom (%1 outbound) - 自定义 (%1 出站) - - - Custom (%1 config) - 自定义 (%1 完整配置) - - - Custom Outbound Settings - 自定义出站 JSON 设置 - - - Custom Config Settings - 自定义配置 JSON 设置 - - - Apply settings to this group - 将设置应用于该组 - - - Multiplex - 多路复用 - - - Keep Default - 保持默认 - - - On - 开启 - - - Off - 关闭 - - - Confirm - 确认 - - - Server support is required - 需要服务器支持 - - - Reality short id. Accept only one value. - Reality short id. 只接受一个值。 - - - - DialogHotkey - - Hotkey - 热键 - - - Show groups - 显示分组 - - - Show routes - 显示路由 - - - Trigger main window - 显示/隐藏主窗口 - - - System Proxy - 系统代理 - - - - DialogManageGroups - - Groups - 分组 - - - New group - 新建分组 - - - Update all subscriptions - 更新所有订阅 - - - Confirmation - 确认 - - - Update all subscriptions? - 更新所有订阅? - - - - DialogManageRoutes - - Routes - 路由 - - - Disable - 禁用 - - - Sniffing Mode - 流量探测 - - - Sniff result for routing - 探测结果用于路由判断 - - - Sniff result for destination - 探测结果用于目标地址 - - - Direct DNS - 直连 DNS - - - Remote DNS - 远程 DNS - - - Enable DNS Routing - 启用 DNS 路由 - - - Block - 阻止 - - - Direct - 直连 - - - Domain - 域名 - - - Proxy - 代理 - - - Preset - 预设 - - - Bypass LAN and China - 绕过局域网和大陆 - - - Global - 全局 - - - IP - - - - Save - 保存 - - - Load - 加载 - - - Cancel - 取消 - - - Remove - 删除 - - - Save routing: %1 - 保存路由: %1 - - - Load routing: %1 - 加载路由: %1 - - - Remove routing: %1 - 删除路由: %1 - - - Mange route set - 管理路由规则 - - - Default Outbound - 默认出站 - - - Domain Strategy - 域名策略 - - - Server Address Strategy - 服务器地址策略 - - - Common - 通用 - - - DNS - - - - Simple DNS Settings - 简易 DNS 设置 - - - Use DNS Object - 使用 DNS Object - - - DNS Object Settings - DNS Object 设置 - - - Simple Route - 简易路由 - - - Custom Route - 自定义路由 - - - Custom Route (global) - 自定义路由(全局) - - - Note: Other settings are independent for each route set. - 注意:其他设置对于每个路由集都是独立的。 - - - Route sets - 路由集 - - - Query Strategy - 查询策略 - - - Document - 文档 - - - Format - 格式化 - - - This is especially important and it is recommended to use the default value of "localhost". -If the default value does not work, try changing it to "223.5.5.5". -For more information, see the document "Configuration/DNS". - 此项尤为重要,建议使用默认值 "localhost"。 -如果默认值不工作,可以尝试更改为 "223.5.5.5"。 -更多信息,请参阅文档 "配置/DNS"。 - - - Final DNS Out - 默认 DNS 出站 - - - - DialogVPNSettings - - Tun Settings - Tun 设置 - - - Hide Console - 隐藏控制台 - - - Tun Enable IPv6 - 启用 Tun IPv6 - - - Bypass CIDR - 绕过 CIDR - - - Bypass Process Name - 绕过进程名 - - - Whitelist mode - 白名单模式 - - - Proxy CIDR - 代理 CIDR - - - Proxy Process Name - 代理进程名 - - - Whether blacklisted or whitelisted, your traffic will be handled by nekobox_core (sing-tun). This is NOT equal to "process mode" of some software. - 无论是黑名单还是白名单,您的流量都将由 nekobox_core (sing-tun) 处理。这不等于某些软件的「进程模式」。 - - - Troubleshooting - 故障排除 - - - If you have trouble starting VPN, you can force reset nekobox_core process here. - -If still not working, see documentation for more information. -https://matsuridayo.github.io/n-configuration/#vpn-tun - 如果您在启动 Tun 时遇到问题,您可以在此处强制重置 nekobox_core 进程。 - -如果仍然无法正常工作,请参阅文档以获取更多信息。 -https://matsuridayo.github.io/n-configuration/#vpn-tun - - - Reset - 重置 - - - Cancel - 取消 - - - Internal Tun - 内部 Tun - - - Add a tun inbound to the profile startup, instead of using two processes. -This needs to be run NekoBox with administrator privileges. - 在配置文件启动时添加一个tun inbound,而不是使用两个进程。 -这需要以管理员权限运行NekoBox。 - - - - EditChain - - Select Profile - 选择配置 - - - Traffic order is from top to bottom - 流量顺序是从上到下(最后一个配置为流量的出口) - - - Name cannot be empty. - 名称 不能为空 - - - - EditCustom - - Core - 核心 - - - Command - 命令 - - - Json Editor - JSON 编辑器 - - - Please pick a core. - 请选择一个核心。 - - - Outbound JSON, please read the documentation. - 填写出站 JSON 对象,详细请看文档。 - - - Config Suffix - 配置文件后缀 - - - Random if it's empty or zero. - 如果为空或为零,则表示使用随机端口。 - - - Preview - 预览 - - - Preview replace - 预览替换串 - - - Preview config - 预览配置 - - - Please fill the complete config. - 请填写完整配置。 - - - Name cannot be empty. - 名称 不能为空 - - - - EditNaive - - Protocol - 协议 - - - Password - 密码 - - - Extra headers - 附加标头 - - - SNI - - - - Username - 用户名 - - - Certificate - 证书 - - - Insecure concurrency - 不安全并发 - - - Disable logs - 关闭日志 - - - Turn on this option if your connection is lost after a while - 如果连接一段时间后出现中断,请打开此选项 - - - - EditQUIC - - Certificate - 证书 - - - Download (Mbps) - 下载速度 (Mbps) - - - Disable MTU Discovery - 禁用 MTU 探测 - - - Hop Interval (s) - 端口跳跃间隔 (秒) - - - Allow Insecure - 不检查服务器证书 - - - Hop Port - 跳跃端口 - - - Upload (Mbps) - 上传速度 (Mbps) - - - Obfs Password - 混淆密码 - - - SNI - SNI - - - Generate UUID - 生成 UUID - - - Password - 密码 - - - Zero Rtt Handshake - 0-Rtt 握手 - - - UDP Relay Mode - UDP 中继模式 - - - Congestion Control - 拥塞控制 - - - Heartbeat - 心跳包发送间隔 - - - Disable SNI - 不发送服务器名称指示 - - - Force use external core - 强制使用外部核心 - - - - EditShadowSocks - - Plugin Args - 插件参数 - - - Password - 密码 - - - Encryption - 加密 - - - Plugin - 插件 - - - Version of UDP over TCP protocol, server support is required. - UDP over TCP 协议版本,需要服务器支持。 - - - Off - 关闭 - - - - EditSocksHttp - - Version - 版本 - - - Username - 用户名 - - - Password - 密码 - - - - EditTrojanVLESS - - Password - 密码 - - - - EditVMess - - Security - 加密 - - - Alter Id - - - - UUID - - - - Generate UUID - 生成 UUID - - - - GroupItem - - Update Subscription - 更新订阅 - - - Edit - 编辑 - - - Basic - 基本 - - - Subscription - 订阅 - - - Confirmation - 确认 - - - Remove - 删除 - - - Remove %1? - 删除 %1 ? - - - Archive - 归档 - - - Last update: %1 - 最后更新 %1 - - - - JsonEditor - - JSON Editor - - - - Format JSON - - - - Remove All Comments - - - - Json Editor - - - - Structure Preview - - - - OK - - - - Json Contains Syntax Errors - - - - Original Json may contain syntax errors. Json tree is disabled. - - - - You must correct these errors before continuing. - - - - Syntax Errors - - - - Please fix the JSON errors or remove the comments before continue - - - - - MainWindow - - Program - 程序 - - - Preferences - 首选项 - - - Server - 服务器 - - - Ads - 推广 - - - Type - 类型 - - - Address - 地址 - - - Name - 名称 - - - Test Result - 测试结果 - - - Traffic - 流量 - - - System Proxy - 系统代理 - - - Share - 分享 - - - Exit - 退出 - - - Basic Settings - 基本设置 - - - Groups - 分组 - - - Stop - 停止 - - - Add profile from clipboard - 从剪贴板添加 - - - Debug Info - 调试信息 - - - Copy Link - 复制链接 - - - Clear Test Result - 清理测试结果 - - - Scan QR Code - 扫描 QR Code - - - Disable - 禁用 - - - Error - 错误 - - - Confirmation - 确认 - - - Settings changed, restart proxy? - 设置已改变,是否重启代理? - - - Imported %1 profile(s) - 导入了 %1 个配置 - - - Unavailable - 不可用 - - - Remove %1 item(s) ? - 删除 %1 个项目? - - - Config copied - 配置已复制 - - - [%1] test error: %2 - [%1] 测试错误: %2 - - - Clear - 清除 - - - fake - - - - Testing - 正在测试 - - - Update - 更新 - - - Document - 文档 - - - Select - 选择 - - - QR Code not found - 未扫描到 QR Code - - - Move - 移动 - - - Log - 日志 - - - Connection - 连接 - - - Status - 状态 - - - Outbound - 出站 - - - Destination - 目标地址 - - - Start: %1 -End: %2 - 开始: %1 -结束: %2 - - - Starting profile %1 - 正在启动配置 %1 - - - Stopping profile %1 - 正在停止配置 %1 - - - Start with system - 跟随系统启动 - - - Remember last profile - 记住最后的配置 - - - Move %1 item(s) - 移动 %1 个项目 - - - Remove Unavailable - 删除不可用的配置 - - - New profile - 手动输入配置 - - - Hotkey Settings - 热键设置 - - - QR Code and link - 显示 QR Code 和分享链接 - - - Active Routing - 当前路由规则 - - - Active Server - 当前服务器 - - - Load routing and apply: %1 - 加载路由规则并应用: %1 - - - Copied %1 item(s) - 复制了 %1 个项目 - - - Full Test - 完整测试 - - - Current Group - 当前分组 - - - Reset Traffic - 重置流量 - - - Remove Duplicates - 删除重复的配置 - - - Select All - 全选 - - - Tun Mode - Tun 模式 - - - Failed to stop Tun process - 停止 Tun 失败 - - - Enable System Proxy - 启用系统代理 - - - Enable Tun - 启用 Tun - - - Tun Settings changed - Tun 设置改变 - - - Restart Tun to take effect. - 重启 Tun 生效。 - - - Start - 启动 - - - Delete - 删除 - - - Copy links of selected - 批量复制选中项目的分享链接 - - - Clone - 克隆 - - - Update subscription - 更新订阅 - - - Clone %1 item(s) - 克隆 %1 个项目 - - - Copy links of selected (Neko Links) - 批量复制选中项目的分享链接 (Neko Links) - - - Allow other devices to connect - 允许其他设备连接 - - - Resolve domain - 将服务器域名解析为 IP - - - Resolving domain to IP, if support. - 将服务器域名解析为 IP(如果支持)。 - - - Export %1 config - 导出 %1 配置 - - - Routing Settings - 路由设置 - - - Tun Settings - Tun 设置 - - - Restart Program - 重启程序 - - - Not Running - 未启动 - - - Current server is incompatible with Tun. Please stop the server first, enable Tun Mode, and then restart. - 当前服务器与 Tun 不兼容。请先停止服务器,打开 Tun 模式后再启动。 - - - Open Config Folder - 打开配置目录 - - - Set ignore keyword - 设置忽略关键字 - - - Set the following keywords to ignore? -Split by line. - 将以下关键字设置为忽略? -一行一个。 - - - Save as route - 保存为路由规则 - - - Save "%1" as a routing rule? - 将"%1"保存为一条路由规则? - - - Edit - 编辑 - - - Current Select - 当前选中 - - - Show Window - 显示主窗口 - - - Settings changed - 设置改变 - - - Restart the program to take effect. - 重启程序生效。 - - - Please run NekoBox as admin - 请以管理员权限运行 NekoBox - - - Restart Proxy - 重启代理 - - - Failed to start profile %1 - 启动配置失败: %1 - - - Failed to stop, please restart the program. - 停止失败,请重启程序。 - - - If there is no response for a long time, it is recommended to restart the software. - 如果长时间没有反应,建议重启软件。 - - - Select mode, double-click or press Enter to select a profile, press ESC to exit. - 选择模式,双击或按回车键选择一个配置文件,按ESC键退出。 - - - Latency - 延迟 - - - UDP latency - UDP 延迟 - - - Download speed - 下载速度 - - - In and Out IP - 入口出口 IP - - - Test Options - 测试选项 - - - Stop Testing - 停止测试 - - - URL Test - URL 测试 - - - - ProxyItem - - Confirmation - 确认 - - - Remove %1? - 删除 %1 ? - - - - QGuiApplication - - QT_LAYOUT_DIRECTION - LTR - - - - QObject - - As link - 作为链接 - - - url detected - 检测到 URL - - - %1 -How to update? - %1 -如何处理? - - - Added %1 profiles: -%2 -Deleted %3 Profiles: -%4 - 增加了 %1 个配置: -%2 -删除了 %3 个配置: -%4 - - - Proxy: %1 -Direct: %2 - 代理: %1 -直连: %2 - - - Used: %1 Remain: %2 Expire: %3 - 已用 %1 剩余 %2 过期 %3 - - - Core not found: %1 - 找不到 "%1" 核心。请前往设置 - - - Update - 更新 - - - No update - 无更新 - - - Open in browser - 浏览器打开 - - - Close - 关闭 - - - Update is ready, restart to install? - 更新已下载好,重启应用? - - - Update found: %1 -Release note: -%2 - 检测到更新: %1 -更新日志: -%2 - - - Unavailable - 不可用 - - - Request with proxy but no profile started. - 即将使用代理请求,但是代理未启动。 - - - Chain Proxy - 链式代理 - - - Requesting subscription: %1 - 正在请求订阅: %1 - - - Requesting subscription %1 error: %2 - 请求订阅 %1 错误: %2 - - - Nothing - - - - Change of %1: - %1 变化: - - - Select - 选择 - - - Clearing servers... - 正在清理服务器... - - - Subscription request fininshed: %1 - 订阅请求完成: %1 - - - Core exited, restarting. - Core 退出,正在重新启动。 - - - Core exits too frequently, stop automatic restart this profile. - Core 退出太频繁,停止自动重启。 - - - As Subscription (create new group) - 作为订阅(创建新组) - - - As Subscription (add to this group) - 作为订阅(添加到该组) - - - Default - 默认 - - - The last speed test did not exit completely, please wait. If it persists, please restart the program. - 上次速度测试未完全退出,请等待。如果问题仍然存在,请重新启动程序。 - - - - Qv2ray::ui::widgets::AutoCompleteTextEdit - - You can not input space characters here. - - - - diff --git a/ui/GroupSort.hpp b/ui/GroupSort.hpp deleted file mode 100644 index ca49eba..0000000 --- a/ui/GroupSort.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -// implement in mainwindow -namespace GroupSortMethod { - enum GroupSortMethod { - Raw, - ByType, - ByAddress, - ByName, - ByLatency, - ById, - }; -} - -struct GroupSortAction { - GroupSortMethod::GroupSortMethod method = GroupSortMethod::Raw; - bool save_sort = false; // 保存到文件 - bool descending = false; // 默认升序,开这个就是降序 - bool scroll_to_started = false; -}; diff --git a/ui/Icon.cpp b/ui/Icon.cpp deleted file mode 100644 index b248f3c..0000000 --- a/ui/Icon.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include "Icon.hpp" - -#include "main/NekoGui.hpp" - -#include - -QPixmap Icon::GetTrayIcon(Icon::TrayIconStatus status) { - QPixmap pixmap; - - // software embedded icon - auto pixmap_read = QPixmap(":/neko/" + software_name.toLower() + ".png"); - if (!pixmap_read.isNull()) pixmap = pixmap_read; - - // software pack icon - pixmap_read = QPixmap("../" + software_name.toLower() + ".png"); - if (!pixmap_read.isNull()) pixmap = pixmap_read; - - // user icon - pixmap_read = QPixmap("./" + software_name.toLower() + ".png"); - if (!pixmap_read.isNull()) pixmap = pixmap_read; - - if (status == TrayIconStatus::NONE) return pixmap; - - auto p = QPainter(&pixmap); - - auto side = pixmap.width(); - auto radius = side * 0.4; - auto d = side * 0.3; - auto margin = side * 0.05; - - if (status == TrayIconStatus::RUNNING) { - p.setBrush(QBrush(Qt::darkGreen)); - } else if (status == TrayIconStatus::SYSTEM_PROXY) { - p.setBrush(QBrush(Qt::blue)); - } else if (status == TrayIconStatus::VPN) { - p.setBrush(QBrush(Qt::red)); - } - p.drawRoundedRect( - QRect(side - d - margin, - side - d - margin, - d, - d), - radius, - radius); - p.end(); - - return pixmap; -} - -QPixmap Icon::GetMaterialIcon(const QString &name) { - QPixmap pixmap(":/icon/material/" + name + ".svg"); - return pixmap; -} diff --git a/ui/Icon.hpp b/ui/Icon.hpp deleted file mode 100644 index 4395344..0000000 --- a/ui/Icon.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include - -namespace Icon { - - enum TrayIconStatus { - NONE, - RUNNING, - SYSTEM_PROXY, - VPN, - }; - - QPixmap GetTrayIcon(TrayIconStatus status); - - QPixmap GetMaterialIcon(const QString &name); - -} // namespace Icon diff --git a/ui/ThemeManager.cpp b/ui/ThemeManager.cpp deleted file mode 100644 index 1c112aa..0000000 --- a/ui/ThemeManager.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#include -#include -#include - -#include "ThemeManager.hpp" - -ThemeManager *themeManager = new ThemeManager; - -extern QString ReadFileText(const QString &path); - -void ThemeManager::ApplyTheme(const QString &theme) { - auto internal = [=] { - if (this->system_style_name.isEmpty()) { - this->system_style_name = qApp->style()->objectName(); - } - if (this->current_theme == theme) { - return; - } - - bool ok; - auto themeId = theme.toInt(&ok); - - if (ok) { - // System & Built-in - QString qss; - - if (themeId != 0) { - QString path; - std::map replace; - switch (themeId) { - case 1: - path = ":/themes/feiyangqingyun/qss/flatgray.css"; - replace[":/qss/"] = ":/themes/feiyangqingyun/qss/"; - break; - case 2: - path = ":/themes/feiyangqingyun/qss/lightblue.css"; - replace[":/qss/"] = ":/themes/feiyangqingyun/qss/"; - break; - case 3: - path = ":/themes/feiyangqingyun/qss/blacksoft.css"; - replace[":/qss/"] = ":/themes/feiyangqingyun/qss/"; - break; - default: - return; - } - qss = ReadFileText(path); - for (auto const &[a, b]: replace) { - qss = qss.replace(a, b); - } - } - - auto system_style = QStyleFactory::create(this->system_style_name); - - if (themeId == 0) { - // system theme - qApp->setPalette(system_style->standardPalette()); - qApp->setStyle(system_style); - qApp->setStyleSheet(""); - } else { - if (themeId == 1 || themeId == 2 || themeId == 3) { - // feiyangqingyun theme - QString paletteColor = qss.mid(20, 7); - qApp->setPalette(QPalette(paletteColor)); - } else { - // other theme - qApp->setPalette(system_style->standardPalette()); - } - qApp->setStyleSheet(qss); - } - } else { - // QStyleFactory - const auto &_style = QStyleFactory::create(theme); - if (_style != nullptr) { - qApp->setPalette(_style->standardPalette()); - qApp->setStyle(_style); - qApp->setStyleSheet(""); - } - } - - current_theme = theme; - }; - internal(); - - auto nekoray_css = ReadFileText(":/neko/neko.css"); - qApp->setStyleSheet(qApp->styleSheet().append("\n").append(nekoray_css)); -} diff --git a/ui/ThemeManager.hpp b/ui/ThemeManager.hpp deleted file mode 100644 index 1514f23..0000000 --- a/ui/ThemeManager.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -class ThemeManager { -public: - QString system_style_name = ""; - QString current_theme = "0"; // int: 0:system 1+:builtin string: QStyleFactory - - void ApplyTheme(const QString &theme); -}; - -extern ThemeManager *themeManager; diff --git a/ui/dialog_basic_settings.cpp b/ui/dialog_basic_settings.cpp deleted file mode 100644 index 9d37a57..0000000 --- a/ui/dialog_basic_settings.cpp +++ /dev/null @@ -1,416 +0,0 @@ -#include "dialog_basic_settings.h" -#include "ui_dialog_basic_settings.h" - -#include "3rdparty/qv2ray/v2/ui/widgets/editors/w_JsonEditor.hpp" -#include "fmt/Preset.hpp" -#include "ui/ThemeManager.hpp" -#include "ui/Icon.hpp" -#include "main/GuiUtils.hpp" -#include "main/NekoGui.hpp" - -#include -#include -#include -#include -#include - -class ExtraCoreWidget : public QWidget { -public: - QString coreName; - - QLabel *label_name; - MyLineEdit *lineEdit_path; - QPushButton *pushButton_pick; - - explicit ExtraCoreWidget(QJsonObject *extraCore, const QString &coreName_, - QWidget *parent = nullptr) - : QWidget(parent) { - coreName = coreName_; - label_name = new QLabel; - label_name->setText(coreName); - lineEdit_path = new MyLineEdit; - lineEdit_path->setText(extraCore->value(coreName).toString()); - pushButton_pick = new QPushButton; - pushButton_pick->setText(QObject::tr("Select")); - auto layout = new QHBoxLayout; - layout->addWidget(label_name); - layout->addWidget(lineEdit_path); - layout->addWidget(pushButton_pick); - setLayout(layout); - setContentsMargins(0, 0, 0, 0); - // - connect(pushButton_pick, &QPushButton::clicked, this, [=] { - auto fn = QFileDialog::getOpenFileName(this, QObject::tr("Select"), QDir::currentPath(), - "", nullptr, QFileDialog::Option::ReadOnly); - if (!fn.isEmpty()) { - lineEdit_path->setText(fn); - } - }); - connect(lineEdit_path, &QLineEdit::textChanged, this, [=](const QString &newTxt) { - extraCore->insert(coreName, newTxt); - }); - } -}; - -DialogBasicSettings::DialogBasicSettings(QWidget *parent) - : QDialog(parent), ui(new Ui::DialogBasicSettings) { - ui->setupUi(this); - ADD_ASTERISK(this); - - // Common - - ui->log_level->addItems(QStringLiteral("trace debug info warn error fatal panic").split(" ")); - ui->mux_protocol->addItems({"h2mux", "smux", "yamux"}); - - refresh_auth(); - - D_LOAD_STRING(inbound_address) - D_LOAD_COMBO_STRING(log_level) - CACHE.custom_inbound = NekoGui::dataStore->custom_inbound; - D_LOAD_INT(inbound_socks_port) - D_LOAD_INT(test_concurrent) - D_LOAD_INT(test_download_timeout) - D_LOAD_STRING(test_latency_url) - D_LOAD_STRING(test_download_url) - D_LOAD_BOOL(old_share_link_format) - - connect(ui->custom_inbound_edit, &QPushButton::clicked, this, [=] { - C_EDIT_JSON_ALLOW_EMPTY(custom_inbound) - }); - -#ifdef Q_OS_WIN - connect(ui->sys_proxy_format, &QPushButton::clicked, this, [=] { - bool ok; - auto str = QInputDialog::getItem(this, ui->sys_proxy_format->text() + " (Windows)", - tr("Advanced system proxy settings. Please select a format."), - Preset::Windows::system_proxy_format, - Preset::Windows::system_proxy_format.indexOf(NekoGui::dataStore->system_proxy_format), - false, &ok); - if (ok) NekoGui::dataStore->system_proxy_format = str; - }); -#else - ui->sys_proxy_format->hide(); -#endif - - // Style - ui->connection_statistics_box->setDisabled(true); - // - D_LOAD_BOOL(check_include_pre) - D_LOAD_BOOL(connection_statistics) - D_LOAD_BOOL(start_minimal) - D_LOAD_INT(max_log_line) - // - if (NekoGui::dataStore->traffic_loop_interval == 500) { - ui->rfsh_r->setCurrentIndex(0); - } else if (NekoGui::dataStore->traffic_loop_interval == 1000) { - ui->rfsh_r->setCurrentIndex(1); - } else if (NekoGui::dataStore->traffic_loop_interval == 2000) { - ui->rfsh_r->setCurrentIndex(2); - } else if (NekoGui::dataStore->traffic_loop_interval == 3000) { - ui->rfsh_r->setCurrentIndex(3); - } else if (NekoGui::dataStore->traffic_loop_interval == 5000) { - ui->rfsh_r->setCurrentIndex(4); - } else { - ui->rfsh_r->setCurrentIndex(5); - } - // - ui->language->setCurrentIndex(NekoGui::dataStore->language); - connect(ui->language, static_cast(&QComboBox::currentIndexChanged), this, [=](int index) { - CACHE.needRestart = true; - }); - // - int built_in_len = ui->theme->count(); - ui->theme->addItems(QStyleFactory::keys()); - // - bool ok; - auto themeId = NekoGui::dataStore->theme.toInt(&ok); - if (ok) { - ui->theme->setCurrentIndex(themeId); - } else { - ui->theme->setCurrentText(NekoGui::dataStore->theme); - } - // - connect(ui->theme, static_cast(&QComboBox::currentIndexChanged), this, [=](int index) { - if (index + 1 <= built_in_len) { - themeManager->ApplyTheme(Int2String(index)); - NekoGui::dataStore->theme = Int2String(index); - } else { - themeManager->ApplyTheme(ui->theme->currentText()); - NekoGui::dataStore->theme = ui->theme->currentText(); - } - repaint(); - mainwindow->repaint(); - NekoGui::dataStore->Save(); - }); - - // Subscription - - ui->user_agent->setText(NekoGui::dataStore->user_agent); - ui->user_agent->setPlaceholderText(NekoGui::dataStore->GetUserAgent(true)); - D_LOAD_BOOL(sub_use_proxy) - D_LOAD_BOOL(sub_clear) - D_LOAD_BOOL(sub_insecure) - D_LOAD_INT_ENABLE(sub_auto_update, sub_auto_update_enable) - - // Core - - ui->groupBox_core->setTitle(software_core_name); - // - CACHE.extraCore = QString2QJsonObject(NekoGui::dataStore->extraCore->core_map); - if (!CACHE.extraCore.contains("naive")) CACHE.extraCore.insert("naive", ""); - if (!CACHE.extraCore.contains("hysteria2")) CACHE.extraCore.insert("hysteria2", ""); - if (!CACHE.extraCore.contains("tuic")) CACHE.extraCore.insert("tuic", ""); - // - auto extra_core_layout = ui->extra_core_box_scrollAreaWidgetContents->layout(); - for (const auto &s: CACHE.extraCore.keys()) { - extra_core_layout->addWidget(new ExtraCoreWidget(&CACHE.extraCore, s)); - } - // - connect(ui->extra_core_add, &QPushButton::clicked, this, [=] { - bool ok; - auto s = QInputDialog::getText(nullptr, tr("Add"), - tr("Please input the core name."), - QLineEdit::Normal, "", &ok) - .trimmed(); - if (s.isEmpty() || !ok) return; - if (CACHE.extraCore.contains(s)) return; - extra_core_layout->addWidget(new ExtraCoreWidget(&CACHE.extraCore, s)); - CACHE.extraCore.insert(s, ""); - }); - connect(ui->extra_core_del, &QPushButton::clicked, this, [=] { - bool ok; - auto s = QInputDialog::getItem(nullptr, tr("Delete"), - tr("Please select the core name."), - CACHE.extraCore.keys(), 0, false, &ok); - if (s.isEmpty() || !ok) return; - for (int i = 0; i < extra_core_layout->count(); i++) { - auto item = extra_core_layout->itemAt(i); - auto ecw = dynamic_cast(item->widget()); - if (ecw != nullptr && ecw->coreName == s) { - ecw->deleteLater(); - CACHE.extraCore.remove(s); - return; - } - } - }); - - // Mux - D_LOAD_INT(mux_concurrency) - D_LOAD_COMBO_STRING(mux_protocol) - D_LOAD_BOOL(mux_padding) - D_LOAD_BOOL(mux_default_on) - - // Security - - ui->utlsFingerprint->addItems(Preset::SingBox::UtlsFingerPrint); - - D_LOAD_BOOL(skip_cert) - ui->utlsFingerprint->setCurrentText(NekoGui::dataStore->utlsFingerprint); -} - -DialogBasicSettings::~DialogBasicSettings() { - delete ui; -} - -void DialogBasicSettings::accept() { - // Common - - D_SAVE_STRING(inbound_address) - D_SAVE_COMBO_STRING(log_level) - NekoGui::dataStore->custom_inbound = CACHE.custom_inbound; - D_SAVE_INT(inbound_socks_port) - D_SAVE_INT(test_concurrent) - D_SAVE_INT(test_download_timeout) - D_SAVE_STRING(test_latency_url) - D_SAVE_STRING(test_download_url) - D_SAVE_BOOL(old_share_link_format) - - // Style - - NekoGui::dataStore->language = ui->language->currentIndex(); - D_SAVE_BOOL(connection_statistics) - D_SAVE_BOOL(check_include_pre) - D_SAVE_BOOL(start_minimal) - D_SAVE_INT(max_log_line) - - if (NekoGui::dataStore->max_log_line <= 0) { - NekoGui::dataStore->max_log_line = 200; - } - - if (ui->rfsh_r->currentIndex() == 0) { - NekoGui::dataStore->traffic_loop_interval = 500; - } else if (ui->rfsh_r->currentIndex() == 1) { - NekoGui::dataStore->traffic_loop_interval = 1000; - } else if (ui->rfsh_r->currentIndex() == 2) { - NekoGui::dataStore->traffic_loop_interval = 2000; - } else if (ui->rfsh_r->currentIndex() == 3) { - NekoGui::dataStore->traffic_loop_interval = 3000; - } else if (ui->rfsh_r->currentIndex() == 4) { - NekoGui::dataStore->traffic_loop_interval = 5000; - } else { - NekoGui::dataStore->traffic_loop_interval = 0; - } - - // Subscription - - if (ui->sub_auto_update_enable->isChecked()) { - TM_auto_update_subsctiption_Reset_Minute(ui->sub_auto_update->text().toInt()); - } else { - TM_auto_update_subsctiption_Reset_Minute(0); - } - - NekoGui::dataStore->user_agent = ui->user_agent->text(); - D_SAVE_BOOL(sub_use_proxy) - D_SAVE_BOOL(sub_clear) - D_SAVE_BOOL(sub_insecure) - D_SAVE_INT_ENABLE(sub_auto_update, sub_auto_update_enable) - - // Core - - NekoGui::dataStore->extraCore->core_map = QJsonObject2QString(CACHE.extraCore, true); - - // Mux - D_SAVE_INT(mux_concurrency) - D_SAVE_COMBO_STRING(mux_protocol) - D_SAVE_BOOL(mux_padding) - D_SAVE_BOOL(mux_default_on) - - // Security - - D_SAVE_BOOL(skip_cert) - NekoGui::dataStore->utlsFingerprint = ui->utlsFingerprint->currentText(); - - // 关闭连接统计,停止刷新前清空记录。 - if (NekoGui::dataStore->traffic_loop_interval == 0 || !NekoGui::dataStore->connection_statistics) { - MW_dialog_message("", "ClearConnectionList"); - } - - QStringList str{"UpdateDataStore"}; - if (CACHE.needRestart) str << "NeedRestart"; - MW_dialog_message(Dialog_DialogBasicSettings, str.join(",")); - QDialog::accept(); -} - -// slots - -void DialogBasicSettings::refresh_auth() { - ui->inbound_auth->setText({}); - if (NekoGui::dataStore->inbound_auth->NeedAuth()) { - ui->inbound_auth->setIcon(Icon::GetMaterialIcon("lock-outline")); - } else { - ui->inbound_auth->setIcon(Icon::GetMaterialIcon("lock-open-outline")); - } -} - -void DialogBasicSettings::on_set_custom_icon_clicked() { - auto title = ui->set_custom_icon->text(); - QString user_icon_path = "./" + software_name.toLower() + ".png"; - auto c = QMessageBox::question(this, title, tr("Please select a PNG file."), - tr("Select"), tr("Reset"), tr("Cancel"), 2, 2); - if (c == 0) { - auto fn = QFileDialog::getOpenFileName(this, QObject::tr("Select"), QDir::currentPath(), - "*.png", nullptr, QFileDialog::Option::ReadOnly); - QImage img(fn); - if (img.isNull() || img.height() != img.width()) { - MessageBoxWarning(title, tr("Please select a valid square image.")); - return; - } - QFile::remove(user_icon_path); - QFile::copy(fn, user_icon_path); - } else if (c == 1) { - QFile::remove(user_icon_path); - } else { - return; - } - MW_dialog_message(Dialog_DialogBasicSettings, "UpdateIcon"); -} - -void DialogBasicSettings::on_inbound_auth_clicked() { - auto w = new QDialog(this); - w->setWindowTitle(tr("Inbound Auth")); - auto layout = new QGridLayout; - w->setLayout(layout); - // - auto user_l = new QLabel(tr("Username")); - auto pass_l = new QLabel(tr("Password")); - auto user = new MyLineEdit; - auto pass = new MyLineEdit; - user->setText(NekoGui::dataStore->inbound_auth->username); - pass->setText(NekoGui::dataStore->inbound_auth->password); - // - layout->addWidget(user_l, 0, 0); - layout->addWidget(user, 0, 1); - layout->addWidget(pass_l, 1, 0); - layout->addWidget(pass, 1, 1); - auto box = new QDialogButtonBox; - box->setOrientation(Qt::Horizontal); - box->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok); - connect(box, &QDialogButtonBox::accepted, w, [=] { - NekoGui::dataStore->inbound_auth->username = user->text(); - NekoGui::dataStore->inbound_auth->password = pass->text(); - MW_dialog_message(Dialog_DialogBasicSettings, "UpdateDataStore"); - w->accept(); - }); - connect(box, &QDialogButtonBox::rejected, w, &QDialog::reject); - layout->addWidget(box, 2, 1); - // - w->exec(); - w->deleteLater(); - refresh_auth(); -} - -void DialogBasicSettings::on_core_settings_clicked() { - auto w = new QDialog(this); - w->setWindowTitle(software_core_name + " Core Options"); - auto layout = new QGridLayout; - w->setLayout(layout); - // - auto line = -1; - QCheckBox *core_box_enable_clash_api; - MyLineEdit *core_box_clash_api; - MyLineEdit *core_box_clash_api_secret; - MyLineEdit *core_box_underlying_dns; - // - auto core_box_underlying_dns_l = new QLabel(tr("Override underlying DNS")); - core_box_underlying_dns = new MyLineEdit; - core_box_underlying_dns->setText(NekoGui::dataStore->core_box_underlying_dns); - core_box_underlying_dns->setMinimumWidth(300); - layout->addWidget(core_box_underlying_dns_l, ++line, 0); - layout->addWidget(core_box_underlying_dns, line, 1); - // - auto core_box_enable_clash_api_l = new QLabel("Enable Clash API"); - core_box_enable_clash_api = new QCheckBox; - core_box_enable_clash_api->setChecked(NekoGui::dataStore->core_box_clash_api > 0); - layout->addWidget(core_box_enable_clash_api_l, ++line, 0); - layout->addWidget(core_box_enable_clash_api, line, 1); - // - auto core_box_clash_api_l = new QLabel("Clash API Listen Port"); - core_box_clash_api = new MyLineEdit; - core_box_clash_api->setText(Int2String(std::abs(NekoGui::dataStore->core_box_clash_api))); - layout->addWidget(core_box_clash_api_l, ++line, 0); - layout->addWidget(core_box_clash_api, line, 1); - // - auto core_box_clash_api_secret_l = new QLabel("Clash API Secret"); - core_box_clash_api_secret = new MyLineEdit; - core_box_clash_api_secret->setText(NekoGui::dataStore->core_box_clash_api_secret); - layout->addWidget(core_box_clash_api_secret_l, ++line, 0); - layout->addWidget(core_box_clash_api_secret, line, 1); - // - auto box = new QDialogButtonBox; - box->setOrientation(Qt::Horizontal); - box->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok); - connect(box, &QDialogButtonBox::accepted, w, [=] { - NekoGui::dataStore->core_box_underlying_dns = core_box_underlying_dns->text(); - NekoGui::dataStore->core_box_clash_api = core_box_clash_api->text().toInt() * (core_box_enable_clash_api->isChecked() ? 1 : -1); - NekoGui::dataStore->core_box_clash_api_secret = core_box_clash_api_secret->text(); - MW_dialog_message(Dialog_DialogBasicSettings, "UpdateDataStore"); - w->accept(); - }); - connect(box, &QDialogButtonBox::rejected, w, &QDialog::reject); - layout->addWidget(box, ++line, 1); - // - ADD_ASTERISK(w) - w->exec(); - w->deleteLater(); - refresh_auth(); -} diff --git a/ui/dialog_basic_settings.h b/ui/dialog_basic_settings.h deleted file mode 100644 index 3a7ff19..0000000 --- a/ui/dialog_basic_settings.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef DIALOG_BASIC_SETTINGS_H -#define DIALOG_BASIC_SETTINGS_H - -#include -#include - -namespace Ui { - class DialogBasicSettings; -} - -class DialogBasicSettings : public QDialog { - Q_OBJECT - -public: - explicit DialogBasicSettings(QWidget *parent = nullptr); - - ~DialogBasicSettings(); - -public slots: - - void accept(); - -private: - Ui::DialogBasicSettings *ui; - - struct { - QJsonObject extraCore; - QString custom_inbound; - bool needRestart = false; - } CACHE; - -private slots: - - void refresh_auth(); - - void on_set_custom_icon_clicked(); - - void on_inbound_auth_clicked(); - - void on_core_settings_clicked(); -}; - -#endif // DIALOG_BASIC_SETTINGS_H diff --git a/ui/dialog_basic_settings.ui b/ui/dialog_basic_settings.ui deleted file mode 100644 index c17b62e..0000000 --- a/ui/dialog_basic_settings.ui +++ /dev/null @@ -1,780 +0,0 @@ - - - DialogBasicSettings - - - - 0 - 0 - 600 - 400 - - - - - 0 - 0 - - - - Basic Settings - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - 0 - - - - Common - - - - - - - - - - - Listen Address - - - - - - - - - - - - - - - - - - - - - - - Custom Inbound - - - - - - - Edit - - - - - - - - - - - - - - - - - Mixed (SOCKS+HTTP) Listen Port - - - - - - - - 0 - 0 - - - - - - - - - - - - - - - - Latency Test URL - - - - - - - - - - Concurrent - - - - - - - - - - - - - - - - Download Test URL - - - - - - - - - - Timeout (s) - - - - - - - - - - - - - - - - Include Pre-release when checking update - - - - - - - Qt::Vertical - - - - - - - Share VMess Link with v2rayN Format - - - Old Share Link Format - - - - - - - System proxy format - - - - - - - - - - - 0 - 0 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - - Style - - - - - - - - - - - - 0 - 0 - - - - Theme - - - - - - - - System - - - - - flatgray - - - - - lightblue - - - - - blacksoft - - - - - - - - - 0 - 0 - - - - Set custom icon - - - - - - - - - - - - - - 0 - 0 - - - - Language - - - - - - - - System - - - - - English - - - - - 简体中文 - - - - - فارسی - - - - - Русский - - - - - - - - - - - - - - - - - - Statistics refresh rate - - - - - - - - 500ms - - - - - 1s - - - - - 2s - - - - - 3s - - - - - 5s - - - - - Off - - - - - - - - - - - - - - Connection statistics - - - - - - - Enable - - - - - - - - - - - - - - - - - - 0 - 0 - - - - Hide dashboard at startup - - - - - - - - - - - - - Max log lines - - - - - - - - 0 - 0 - - - - - - - - - - - - - - Subscription - - - - - - - - - 0 - 0 - - - - Enable - - - - - - - Interval (minute, invalid if less than 30) - - - - - - - - 0 - 0 - - - - - - - - - - - - - Use proxy when updating subscription - - - - - - - Ignore TLS errors when updating subscription - - - - - - - Clear servers before updating subscription - - - - - - - - 0 - 0 - - - - Automatic update - - - - - - - User Agent - - - - - - - - Core - - - - - - - 0 - 0 - - - - core_name - - - - - - - - - - 0 - 0 - - - - - - - - Multiplex (mux) - - - - - - - Loglevel - - - - - - - - - - - - concurrency - - - - - - - - - - Padding - - - - - - - Default On - - - - - - - - - - - - Core Options - - - - - - - - - - - Extra Core - - - - - - QFrame::NoFrame - - - true - - - - - 0 - 0 - 632 - 299 - - - - - - - - 0 - 0 - - - - - - - Add - - - - - - - Delete - - - - - - - - - - - - - - - Security - - - - - - Skip TLS certificate authentication by default (allowInsecure) - - - - - - - - 0 - 0 - - - - - - - Default uTLS Fingerprint - - - - - - - true - - - - - - - - - - - - - - - MyLineEdit - QLineEdit -
ui/widget/MyLineEdit.h
-
-
- - - - buttonBox - accepted() - DialogBasicSettings - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - DialogBasicSettings - reject() - - - 316 - 260 - - - 286 - 274 - - - - -
diff --git a/ui/dialog_hotkey.cpp b/ui/dialog_hotkey.cpp deleted file mode 100644 index d53278d..0000000 --- a/ui/dialog_hotkey.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include "dialog_hotkey.h" -#include "ui_dialog_hotkey.h" - -#include "ui/mainwindow_interface.h" - -DialogHotkey::DialogHotkey(QWidget *parent) : QDialog(parent), ui(new Ui::DialogHotkey) { - ui->setupUi(this); - ui->show_mainwindow->setKeySequence(NekoGui::dataStore->hotkey_mainwindow); - ui->show_groups->setKeySequence(NekoGui::dataStore->hotkey_group); - ui->show_routes->setKeySequence(NekoGui::dataStore->hotkey_route); - ui->system_proxy->setKeySequence(NekoGui::dataStore->hotkey_system_proxy_menu); - GetMainWindow()->RegisterHotkey(true); -} - -DialogHotkey::~DialogHotkey() { - if (result() == QDialog::Accepted) { - NekoGui::dataStore->hotkey_mainwindow = ui->show_mainwindow->keySequence().toString(); - NekoGui::dataStore->hotkey_group = ui->show_groups->keySequence().toString(); - NekoGui::dataStore->hotkey_route = ui->show_routes->keySequence().toString(); - NekoGui::dataStore->hotkey_system_proxy_menu = ui->system_proxy->keySequence().toString(); - NekoGui::dataStore->Save(); - } - GetMainWindow()->RegisterHotkey(false); - delete ui; -} diff --git a/ui/dialog_hotkey.h b/ui/dialog_hotkey.h deleted file mode 100644 index 6e42508..0000000 --- a/ui/dialog_hotkey.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include -#include "main/NekoGui.hpp" - -QT_BEGIN_NAMESPACE -namespace Ui { - class DialogHotkey; -} -QT_END_NAMESPACE - -class DialogHotkey : public QDialog { - Q_OBJECT - -public: - explicit DialogHotkey(QWidget *parent = nullptr); - - ~DialogHotkey() override; - -private: - Ui::DialogHotkey *ui; -}; diff --git a/ui/dialog_hotkey.ui b/ui/dialog_hotkey.ui deleted file mode 100644 index 6cdda0f..0000000 --- a/ui/dialog_hotkey.ui +++ /dev/null @@ -1,118 +0,0 @@ - - - DialogHotkey - - - - 0 - 0 - 400 - 300 - - - - Hotkey - - - - - - - - - Show routes - - - - - - - - - - Qt::StrongFocus - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - - Show groups - - - - - - - Trigger main window - - - - - - - System Proxy - - - - - - - - - - - QtExtKeySequenceEdit - QKeySequenceEdit -
3rdparty/QtExtKeySequenceEdit.h
-
-
- - show_mainwindow - show_groups - show_routes - system_proxy - buttonBox - - - - - buttonBox - accepted() - DialogHotkey - accept() - - - 258 - 255 - - - 199 - 149 - - - - - buttonBox - rejected() - DialogHotkey - reject() - - - 258 - 255 - - - 199 - 149 - - - - -
diff --git a/ui/dialog_manage_groups.cpp b/ui/dialog_manage_groups.cpp deleted file mode 100644 index 0cf3c8b..0000000 --- a/ui/dialog_manage_groups.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include "dialog_manage_groups.h" -#include "ui_dialog_manage_groups.h" - -#include "db/Database.hpp" -#include "sub/GroupUpdater.hpp" -#include "main/GuiUtils.hpp" -#include "ui/widget/GroupItem.h" -#include "ui/edit/dialog_edit_group.h" - -#include -#include -#include - -#define AddGroupToListIfExist(_id) \ - auto __ent = NekoGui::profileManager->GetGroup(_id); \ - if (__ent != nullptr) { \ - auto wI = new QListWidgetItem(); \ - auto w = new GroupItem(this, __ent, wI); \ - wI->setData(114514, _id); \ - ui->listWidget->addItem(wI); \ - ui->listWidget->setItemWidget(wI, w); \ - } - -DialogManageGroups::DialogManageGroups(QWidget *parent) : QDialog(parent), ui(new Ui::DialogManageGroups) { - ui->setupUi(this); - - for (auto id: NekoGui::profileManager->groupsTabOrder) { - AddGroupToListIfExist(id) - } - - connect(ui->listWidget, &QListWidget::itemDoubleClicked, this, [=](QListWidgetItem *wI) { - auto w = dynamic_cast(ui->listWidget->itemWidget(wI)); - emit w->edit_clicked(); - }); -} - -DialogManageGroups::~DialogManageGroups() { - delete ui; -} - -void DialogManageGroups::on_add_clicked() { - auto ent = NekoGui::ProfileManager::NewGroup(); - auto dialog = new DialogEditGroup(ent, this); - int ret = dialog->exec(); - dialog->deleteLater(); - - if (ret == QDialog::Accepted) { - NekoGui::profileManager->AddGroup(ent); - AddGroupToListIfExist(ent->id); - MW_dialog_message(Dialog_DialogManageGroups, "refresh-1"); - } -} - -void DialogManageGroups::on_update_all_clicked() { - if (QMessageBox::question(this, tr("Confirmation"), tr("Update all subscriptions?")) == QMessageBox::StandardButton::Yes) { - UI_update_all_groups(); - } -} diff --git a/ui/dialog_manage_groups.h b/ui/dialog_manage_groups.h deleted file mode 100644 index 04e4412..0000000 --- a/ui/dialog_manage_groups.h +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -#include "db/Group.hpp" - -QT_BEGIN_NAMESPACE -namespace Ui { - class DialogManageGroups; -} -QT_END_NAMESPACE - -class DialogManageGroups : public QDialog { - Q_OBJECT - -public: - explicit DialogManageGroups(QWidget *parent = nullptr); - - ~DialogManageGroups() override; - -private: - Ui::DialogManageGroups *ui; - -private slots: - - void on_add_clicked(); - - void on_update_all_clicked(); -}; diff --git a/ui/dialog_manage_groups.ui b/ui/dialog_manage_groups.ui deleted file mode 100644 index dcba1ff..0000000 --- a/ui/dialog_manage_groups.ui +++ /dev/null @@ -1,55 +0,0 @@ - - - DialogManageGroups - - - - 0 - 0 - 640 - 480 - - - - Qt::TabFocus - - - Groups - - - - - - Qt::NoFocus - - - - - - - - - Qt::NoFocus - - - New group - - - - - - - Qt::NoFocus - - - Update all subscriptions - - - - - - - - - - diff --git a/ui/dialog_manage_routes.cpp b/ui/dialog_manage_routes.cpp deleted file mode 100644 index 98fde5b..0000000 --- a/ui/dialog_manage_routes.cpp +++ /dev/null @@ -1,251 +0,0 @@ -#include "dialog_manage_routes.h" -#include "ui_dialog_manage_routes.h" - -#include "3rdparty/qv2ray/v2/ui/widgets/editors/w_JsonEditor.hpp" -#include "3rdparty/qv2ray/v3/components/GeositeReader/GeositeReader.hpp" -#include "main/GuiUtils.hpp" -#include "fmt/Preset.hpp" - -#include -#include -#include -#include - -#define REFRESH_ACTIVE_ROUTING(name, obj) \ - this->active_routing = name; \ - setWindowTitle(title_base + " [" + name + "]"); \ - UpdateDisplayRouting(obj, false); - -DialogManageRoutes::DialogManageRoutes(QWidget *parent) : QDialog(parent), ui(new Ui::DialogManageRoutes) { - ui->setupUi(this); - title_base = windowTitle(); - - QStringList qsValue = {""}; - QString dnsHelpDocumentUrl; - // - ui->outbound_domain_strategy->addItems(Preset::SingBox::DomainStrategy); - ui->domainStrategyCombo->addItems(Preset::SingBox::DomainStrategy); - qsValue += QStringLiteral("prefer_ipv4 prefer_ipv6 ipv4_only ipv6_only").split(" "); - ui->dns_object->setPlaceholderText(DecodeB64IfValid("ewogICJzZXJ2ZXJzIjogW10sCiAgInJ1bGVzIjogW10sCiAgImZpbmFsIjogIiIsCiAgInN0cmF0ZWd5IjogIiIsCiAgImRpc2FibGVfY2FjaGUiOiBmYWxzZSwKICAiZGlzYWJsZV9leHBpcmUiOiBmYWxzZSwKICAiaW5kZXBlbmRlbnRfY2FjaGUiOiBmYWxzZSwKICAicmV2ZXJzZV9tYXBwaW5nIjogZmFsc2UsCiAgImZha2VpcCI6IHt9Cn0=")); - dnsHelpDocumentUrl = "https://sing-box.sagernet.org/configuration/dns/"; - // - ui->direct_dns_strategy->addItems(qsValue); - ui->remote_dns_strategy->addItems(qsValue); - // - D_C_LOAD_STRING(custom_route_global) - // - connect(ui->use_dns_object, &QCheckBox::stateChanged, this, [=](int state) { - auto useDNSObject = state == Qt::Checked; - ui->simple_dns_box->setDisabled(useDNSObject); - ui->dns_object->setDisabled(!useDNSObject); - }); - ui->use_dns_object->stateChanged(Qt::Unchecked); // uncheck to uncheck - connect(ui->dns_document, &QPushButton::clicked, this, [=] { - MessageBoxInfo("DNS", dnsHelpDocumentUrl); - }); - connect(ui->format_dns_object, &QPushButton::clicked, this, [=] { - auto obj = QString2QJsonObject(ui->dns_object->toPlainText()); - if (obj.isEmpty()) { - MessageBoxInfo("DNS", "invaild json"); - } else { - ui->dns_object->setPlainText(QJsonObject2QString(obj, false)); - } - }); - // - connect(ui->custom_route_edit, &QPushButton::clicked, this, [=] { - C_EDIT_JSON_ALLOW_EMPTY(custom_route) - }); - connect(ui->custom_route_global_edit, &QPushButton::clicked, this, [=] { - C_EDIT_JSON_ALLOW_EMPTY(custom_route_global) - }); - // - builtInSchemesMenu = new QMenu(this); - builtInSchemesMenu->addActions(this->getBuiltInSchemes()); - ui->preset->setMenu(builtInSchemesMenu); - - QString geoipFn = NekoGui::FindCoreAsset("geoip.dat"); - QString geositeFn = NekoGui::FindCoreAsset("geosite.dat"); - // - const auto sourceStringsDomain = Qv2ray::components::GeositeReader::ReadGeoSiteFromFile(geositeFn); - directDomainTxt = new AutoCompleteTextEdit("geosite", sourceStringsDomain, this); - proxyDomainTxt = new AutoCompleteTextEdit("geosite", sourceStringsDomain, this); - blockDomainTxt = new AutoCompleteTextEdit("geosite", sourceStringsDomain, this); - // - const auto sourceStringsIP = Qv2ray::components::GeositeReader::ReadGeoSiteFromFile(geoipFn); - directIPTxt = new AutoCompleteTextEdit("geoip", sourceStringsIP, this); - proxyIPTxt = new AutoCompleteTextEdit("geoip", sourceStringsIP, this); - blockIPTxt = new AutoCompleteTextEdit("geoip", sourceStringsIP, this); - // - ui->directTxtLayout->addWidget(directDomainTxt, 0, 0); - ui->proxyTxtLayout->addWidget(proxyDomainTxt, 0, 0); - ui->blockTxtLayout->addWidget(blockDomainTxt, 0, 0); - // - ui->directIPLayout->addWidget(directIPTxt, 0, 0); - ui->proxyIPLayout->addWidget(proxyIPTxt, 0, 0); - ui->blockIPLayout->addWidget(blockIPTxt, 0, 0); - // - REFRESH_ACTIVE_ROUTING(NekoGui::dataStore->active_routing, NekoGui::dataStore->routing.get()) - - ADD_ASTERISK(this) -} - -DialogManageRoutes::~DialogManageRoutes() { - delete ui; -} - -void DialogManageRoutes::accept() { - D_C_SAVE_STRING(custom_route_global) - bool routeChanged = false; - if (NekoGui::dataStore->active_routing != active_routing) routeChanged = true; - SaveDisplayRouting(NekoGui::dataStore->routing.get()); - NekoGui::dataStore->active_routing = active_routing; - NekoGui::dataStore->routing->fn = ROUTES_PREFIX + NekoGui::dataStore->active_routing; - if (NekoGui::dataStore->routing->Save()) routeChanged = true; - // - QString info = "UpdateDataStore"; - if (routeChanged) info += "RouteChanged"; - MW_dialog_message(Dialog_DialogManageRoutes, info); - QDialog::accept(); -} - -// built in settings - -QList DialogManageRoutes::getBuiltInSchemes() { - QList list; - list.append(this->schemeToAction(tr("Bypass LAN and China"), routing_cn_lan)); - list.append(this->schemeToAction(tr("Global"), routing_global)); - return list; -} - -QAction *DialogManageRoutes::schemeToAction(const QString &name, const NekoGui::Routing &scheme) { - auto *action = new QAction(name, this); - connect(action, &QAction::triggered, [this, &scheme] { this->UpdateDisplayRouting((NekoGui::Routing *) &scheme, true); }); - return action; -} - -void DialogManageRoutes::UpdateDisplayRouting(NekoGui::Routing *conf, bool qv) { - // - directDomainTxt->setPlainText(conf->direct_domain); - proxyDomainTxt->setPlainText(conf->proxy_domain); - blockDomainTxt->setPlainText(conf->block_domain); - // - blockIPTxt->setPlainText(conf->block_ip); - directIPTxt->setPlainText(conf->direct_ip); - proxyIPTxt->setPlainText(conf->proxy_ip); - // - CACHE.custom_route = conf->custom; - ui->def_outbound->setCurrentText(conf->def_outbound); - // - if (qv) return; - // - ui->sniffing_mode->setCurrentIndex(conf->sniffing_mode); - ui->outbound_domain_strategy->setCurrentText(conf->outbound_domain_strategy); - ui->domainStrategyCombo->setCurrentText(conf->domain_strategy); - ui->use_dns_object->setChecked(conf->use_dns_object); - ui->dns_object->setPlainText(conf->dns_object); - ui->dns_routing->setChecked(conf->dns_routing); - ui->remote_dns->setCurrentText(conf->remote_dns); - ui->remote_dns_strategy->setCurrentText(conf->remote_dns_strategy); - ui->direct_dns->setCurrentText(conf->direct_dns); - ui->direct_dns_strategy->setCurrentText(conf->direct_dns_strategy); - ui->dns_final_out->setCurrentText(conf->dns_final_out); -} - -void DialogManageRoutes::SaveDisplayRouting(NekoGui::Routing *conf) { - conf->direct_ip = directIPTxt->toPlainText(); - conf->direct_domain = directDomainTxt->toPlainText(); - conf->proxy_ip = proxyIPTxt->toPlainText(); - conf->proxy_domain = proxyDomainTxt->toPlainText(); - conf->block_ip = blockIPTxt->toPlainText(); - conf->block_domain = blockDomainTxt->toPlainText(); - conf->def_outbound = ui->def_outbound->currentText(); - conf->custom = CACHE.custom_route; - // - conf->sniffing_mode = ui->sniffing_mode->currentIndex(); - conf->domain_strategy = ui->domainStrategyCombo->currentText(); - conf->outbound_domain_strategy = ui->outbound_domain_strategy->currentText(); - conf->use_dns_object = ui->use_dns_object->isChecked(); - conf->dns_object = ui->dns_object->toPlainText(); - conf->dns_routing = ui->dns_routing->isChecked(); - conf->remote_dns = ui->remote_dns->currentText(); - conf->remote_dns_strategy = ui->remote_dns_strategy->currentText(); - conf->direct_dns = ui->direct_dns->currentText(); - conf->direct_dns_strategy = ui->direct_dns_strategy->currentText(); - conf->dns_final_out = ui->dns_final_out->currentText(); -} - -void DialogManageRoutes::on_load_save_clicked() { - auto w = new QDialog; - auto layout = new QVBoxLayout; - w->setLayout(layout); - auto lineEdit = new QLineEdit; - layout->addWidget(lineEdit); - auto list = new QListWidget; - layout->addWidget(list); - for (const auto &name: NekoGui::Routing::List()) { - list->addItem(name); - } - connect(list, &QListWidget::currentTextChanged, lineEdit, &QLineEdit::setText); - auto bottom = new QHBoxLayout; - layout->addLayout(bottom); - auto load = new QPushButton; - load->setText(tr("Load")); - bottom->addWidget(load); - auto save = new QPushButton; - save->setText(tr("Save")); - bottom->addWidget(save); - auto remove = new QPushButton; - remove->setText(tr("Remove")); - bottom->addWidget(remove); - auto cancel = new QPushButton; - cancel->setText(tr("Cancel")); - bottom->addWidget(cancel); - connect(load, &QPushButton::clicked, w, [=] { - auto fn = lineEdit->text(); - if (!fn.isEmpty()) { - auto r = std::make_unique(); - r->load_control_must = true; - r->fn = ROUTES_PREFIX + fn; - if (r->Load()) { - if (QMessageBox::question(nullptr, software_name, tr("Load routing: %1").arg(fn) + "\n" + r->DisplayRouting()) == QMessageBox::Yes) { - REFRESH_ACTIVE_ROUTING(fn, r.get()) // temp save to the window - w->accept(); - } - } - } - }); - connect(save, &QPushButton::clicked, w, [=] { - auto fn = lineEdit->text(); - if (!fn.isEmpty()) { - auto r = std::make_unique(); - SaveDisplayRouting(r.get()); - r->fn = ROUTES_PREFIX + fn; - if (QMessageBox::question(nullptr, software_name, tr("Save routing: %1").arg(fn) + "\n" + r->DisplayRouting()) == QMessageBox::Yes) { - r->Save(); - REFRESH_ACTIVE_ROUTING(fn, r.get()) - w->accept(); - } - } - }); - connect(remove, &QPushButton::clicked, w, [=] { - auto fn = lineEdit->text(); - if (!fn.isEmpty() && NekoGui::Routing::List().length() > 1) { - if (QMessageBox::question(nullptr, software_name, tr("Remove routing: %1").arg(fn)) == QMessageBox::Yes) { - QFile f(ROUTES_PREFIX + fn); - f.remove(); - if (NekoGui::dataStore->active_routing == fn) { - NekoGui::Routing::SetToActive(NekoGui::Routing::List().first()); - REFRESH_ACTIVE_ROUTING(NekoGui::dataStore->active_routing, NekoGui::dataStore->routing.get()) - } - w->accept(); - } - } - }); - connect(cancel, &QPushButton::clicked, w, &QDialog::accept); - connect(list, &QListWidget::itemDoubleClicked, this, [=](QListWidgetItem *item) { - lineEdit->setText(item->text()); - emit load->clicked(); - }); - w->exec(); - w->deleteLater(); -} diff --git a/ui/dialog_manage_routes.h b/ui/dialog_manage_routes.h deleted file mode 100644 index 0030622..0000000 --- a/ui/dialog_manage_routes.h +++ /dev/null @@ -1,59 +0,0 @@ -#pragma once - -#include -#include - -#include "3rdparty/qv2ray/v2/ui/QvAutoCompleteTextEdit.hpp" -#include "main/NekoGui.hpp" - -QT_BEGIN_NAMESPACE -namespace Ui { - class DialogManageRoutes; -} -QT_END_NAMESPACE - -class DialogManageRoutes : public QDialog { - Q_OBJECT - -public: - explicit DialogManageRoutes(QWidget *parent = nullptr); - - ~DialogManageRoutes() override; - -private: - Ui::DialogManageRoutes *ui; - - struct { - QString custom_route; - QString custom_route_global; - } CACHE; - - QMenu *builtInSchemesMenu; - Qv2ray::ui::widgets::AutoCompleteTextEdit *directDomainTxt; - Qv2ray::ui::widgets::AutoCompleteTextEdit *proxyDomainTxt; - Qv2ray::ui::widgets::AutoCompleteTextEdit *blockDomainTxt; - // - Qv2ray::ui::widgets::AutoCompleteTextEdit *directIPTxt; - Qv2ray::ui::widgets::AutoCompleteTextEdit *blockIPTxt; - Qv2ray::ui::widgets::AutoCompleteTextEdit *proxyIPTxt; - // - NekoGui::Routing routing_cn_lan = NekoGui::Routing(1); - NekoGui::Routing routing_global = NekoGui::Routing(0); - // - QString title_base; - QString active_routing; - -public slots: - - void accept() override; - - QList getBuiltInSchemes(); - - QAction *schemeToAction(const QString &name, const NekoGui::Routing &scheme); - - void UpdateDisplayRouting(NekoGui::Routing *conf, bool qv); - - void SaveDisplayRouting(NekoGui::Routing *conf); - - void on_load_save_clicked(); -}; diff --git a/ui/dialog_manage_routes.ui b/ui/dialog_manage_routes.ui deleted file mode 100644 index cfb846e..0000000 --- a/ui/dialog_manage_routes.ui +++ /dev/null @@ -1,687 +0,0 @@ - - - DialogManageRoutes - - - - 0 - 0 - 800 - 600 - - - - Routes - - - - - - 0 - - - - Common - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Route sets - - - - - - Mange route set - - - - - - - Custom Route (global) - - - - - - - Note: Other settings are independent for each route set. - - - - - - - - - - For V2Ray, it sets routing.domainStrategy -For sing-box, it sets inbound.domain_strategy - - - Domain Strategy - - - - - - - false - - - - - - - - Disable - - - - - Sniff result for routing - - - - - Sniff result for destination - - - - - - - - Sniffing Mode - - - - - - - Server Address Strategy - - - - - - - false - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - DNS - - - - - - Simple DNS Settings - - - - - - This is especially important and it is recommended to use the default value of "localhost". -If the default value does not work, try changing it to "223.5.5.5". -For more information, see the document "Configuration/DNS". - - - Direct DNS - - - - - - - - - - 0 - 0 - - - - true - - - - https://8.8.8.8/dns-query - - - - - https://1.0.0.1/dns-query - - - - - https://1.1.1.1/dns-query - - - - - https://dns.google/dns-query - - - - - https://one.one.one.one/dns-query - - - - - https://[2001:4860:4860::8888]/dns-query - - - - - https://[2606:4700:4700::1111]/dns-query - - - - - - - - Query Strategy - - - - - - - - - - - - Remote DNS - - - widget - - - - - - - - - Enable DNS Routing - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Final DNS Out - - - - - - - - proxy - - - - - bypass - - - - - - - - - - - - - 0 - 0 - - - - true - - - - local - - - - - tls://120.53.53.53 - - - - - https://223.5.5.5/dns-query - - - - - https://1.12.12.12/dns-query - - - - - https://dns.alidns.com/dns-query - - - - - https://doh.pub/dns-query - - - - - 223.5.5.5 - - - - - 119.29.29.29 - - - - - 2400:3200::1 - - - - - 2402:4e00:: - - - - - - - - Query Strategy - - - - - - - - - - - - - - - DNS Object Settings - - - - - - - - Use DNS Object - - - - - - - - 0 - 0 - - - - Format - - - - - - - - 0 - 0 - - - - Document - - - - - - - - - - - - - - - - Simple Route - - - - - - - - - - - Block - - - Qt::AlignCenter - - - - - - - - - - Direct - - - Qt::AlignCenter - - - - - - - Domain - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - Proxy - - - Qt::AlignCenter - - - - - - - - - - - - - IP - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - Preset - - - QToolButton::InstantPopup - - - Qt::ToolButtonTextBesideIcon - - - - - - - Custom Route - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Default Outbound - - - - - - - - proxy - - - - - bypass - - - - - block - - - - - - - - - - - - - - - - - - - - - - - 0 - 0 - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - tabWidget - sniffing_mode - domainStrategyCombo - outbound_domain_strategy - load_save - custom_route_global_edit - remote_dns - remote_dns_strategy - direct_dns - direct_dns_strategy - dns_routing - dns_final_out - use_dns_object - format_dns_object - dns_document - dns_object - preset - custom_route_edit - def_outbound - - - - - buttonBox - rejected() - DialogManageRoutes - reject() - - - 399 - 574 - - - 399 - 299 - - - - - buttonBox - accepted() - DialogManageRoutes - accept() - - - 399 - 574 - - - 399 - 299 - - - - - diff --git a/ui/dialog_vpn_settings.cpp b/ui/dialog_vpn_settings.cpp deleted file mode 100644 index 12096ee..0000000 --- a/ui/dialog_vpn_settings.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#include "dialog_vpn_settings.h" -#include "ui_dialog_vpn_settings.h" - -#include "main/GuiUtils.hpp" -#include "main/NekoGui.hpp" -#include "ui/mainwindow_interface.h" - -#include - -DialogVPNSettings::DialogVPNSettings(QWidget *parent) : QDialog(parent), ui(new Ui::DialogVPNSettings) { - ui->setupUi(this); - ADD_ASTERISK(this); - - ui->fake_dns->setChecked(NekoGui::dataStore->fake_dns); - ui->vpn_implementation->setCurrentIndex(NekoGui::dataStore->vpn_implementation); - ui->vpn_mtu->setCurrentText(Int2String(NekoGui::dataStore->vpn_mtu)); - ui->vpn_ipv6->setChecked(NekoGui::dataStore->vpn_ipv6); - ui->hide_console->setChecked(NekoGui::dataStore->vpn_hide_console); -#ifndef Q_OS_WIN - ui->hide_console->setVisible(false); -#endif - ui->strict_route->setChecked(NekoGui::dataStore->vpn_strict_route); - ui->single_core->setChecked(NekoGui::dataStore->vpn_internal_tun); - // - D_LOAD_STRING_PLAIN(vpn_rule_cidr) - D_LOAD_STRING_PLAIN(vpn_rule_process) - // - connect(ui->whitelist_mode, &QCheckBox::stateChanged, this, [=](int state) { - if (state == Qt::Checked) { - ui->gb_cidr->setTitle(tr("Proxy CIDR")); - ui->gb_process_name->setTitle(tr("Proxy Process Name")); - } else { - ui->gb_cidr->setTitle(tr("Bypass CIDR")); - ui->gb_process_name->setTitle(tr("Bypass Process Name")); - } - }); - ui->whitelist_mode->setChecked(NekoGui::dataStore->vpn_rule_white); -} - -DialogVPNSettings::~DialogVPNSettings() { - delete ui; -} - -void DialogVPNSettings::accept() { - // - auto mtu = ui->vpn_mtu->currentText().toInt(); - if (mtu > 10000 || mtu < 1000) mtu = 9000; - NekoGui::dataStore->vpn_implementation = ui->vpn_implementation->currentIndex(); - NekoGui::dataStore->fake_dns = ui->fake_dns->isChecked(); - NekoGui::dataStore->vpn_mtu = mtu; - NekoGui::dataStore->vpn_ipv6 = ui->vpn_ipv6->isChecked(); - NekoGui::dataStore->vpn_hide_console = ui->hide_console->isChecked(); - NekoGui::dataStore->vpn_strict_route = ui->strict_route->isChecked(); - NekoGui::dataStore->vpn_rule_white = ui->whitelist_mode->isChecked(); - bool isInternalChanged = NekoGui::dataStore->vpn_internal_tun != ui->single_core->isChecked(); - NekoGui::dataStore->vpn_internal_tun = ui->single_core->isChecked(); - // - D_SAVE_STRING_PLAIN(vpn_rule_cidr) - D_SAVE_STRING_PLAIN(vpn_rule_process) - // - QStringList msg{"UpdateDataStore"}; - if (isInternalChanged) { - msg << "NeedRestart"; - } else { - msg << "VPNChanged"; - } - MW_dialog_message("", msg.join(",")); - QDialog::accept(); -} - -void DialogVPNSettings::on_troubleshooting_clicked() { - auto r = QMessageBox::information(this, tr("Troubleshooting"), - tr("If you have trouble starting VPN, you can force reset nekobox_core process here.\n\n" - "If still not working, see documentation for more information.\n" - "https://matsuridayo.github.io/n-configuration/#vpn-tun"), - tr("Reset"), tr("Cancel"), "", - 1, 1); - if (r == 0) { - GetMainWindow()->StopVPNProcess(true); - } -} diff --git a/ui/dialog_vpn_settings.h b/ui/dialog_vpn_settings.h deleted file mode 100644 index 0b5b87d..0000000 --- a/ui/dialog_vpn_settings.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef NEKORAY_DIALOG_VPN_SETTINGS_H -#define NEKORAY_DIALOG_VPN_SETTINGS_H - -#include - -QT_BEGIN_NAMESPACE -namespace Ui { - class DialogVPNSettings; -} -QT_END_NAMESPACE - -class DialogVPNSettings : public QDialog { - Q_OBJECT - -public: - explicit DialogVPNSettings(QWidget *parent = nullptr); - - ~DialogVPNSettings() override; - -private: - Ui::DialogVPNSettings *ui; - -public slots: - - void accept() override; - - void on_troubleshooting_clicked(); -}; - -#endif // NEKORAY_DIALOG_VPN_SETTINGS_H diff --git a/ui/dialog_vpn_settings.ui b/ui/dialog_vpn_settings.ui deleted file mode 100644 index bbb5f69..0000000 --- a/ui/dialog_vpn_settings.ui +++ /dev/null @@ -1,262 +0,0 @@ - - - DialogVPNSettings - - - - 0 - 0 - 600 - 600 - - - - Tun Settings - - - - - - - 0 - 0 - - - - - - - - 0 - 0 - - - - Stack - - - - - - - - Mixed - - - - - gVisor - - - - - System - - - - - - - - - 0 - 0 - - - - MTU - - - - - - - true - - - - 9000 - - - - - 1500 - - - - - - - - - - - - - - Tun Enable IPv6 - - - - - - - Strict Route - - - - - - - FakeDNS - - - - - - - Qt::Vertical - - - - - - - Add a tun inbound to the profile startup, instead of using two processes. -This needs to be run NekoBox with administrator privileges. - - - Internal Tun - - - - - - - Hide Console - - - - - - - - - - - - Bypass CIDR - - - - - - - - - - - - Bypass Process Name - - - - - - - - - - - - - - - - Whether blacklisted or whitelisted, your traffic will be handled by nekobox_core (sing-tun). This is NOT equal to "process mode" of some software. - - - Whitelist mode - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Troubleshooting - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - vpn_implementation - vpn_mtu - vpn_ipv6 - strict_route - fake_dns - single_core - hide_console - vpn_rule_cidr - vpn_rule_process - whitelist_mode - troubleshooting - - - - - buttonBox - accepted() - DialogVPNSettings - accept() - - - 399 - 575 - - - 399 - 299 - - - - - buttonBox - rejected() - DialogVPNSettings - reject() - - - 399 - 575 - - - 399 - 299 - - - - - diff --git a/ui/edit/dialog_edit_group.cpp b/ui/edit/dialog_edit_group.cpp deleted file mode 100644 index 061f654..0000000 --- a/ui/edit/dialog_edit_group.cpp +++ /dev/null @@ -1,104 +0,0 @@ -#include "dialog_edit_group.h" -#include "ui_dialog_edit_group.h" - -#include "db/Database.hpp" -#include "ui/mainwindow_interface.h" - -#include - -#define ADJUST_SIZE runOnUiThread([=] { adjustSize(); adjustPosition(mainwindow); }, this); - -DialogEditGroup::DialogEditGroup(const std::shared_ptr &ent, QWidget *parent) : QDialog(parent), ui(new Ui::DialogEditGroup) { - ui->setupUi(this); - this->ent = ent; - - connect(ui->type, static_cast(&QComboBox::currentIndexChanged), this, [=](int index) { - ui->cat_sub->setHidden(index == 0); - ADJUST_SIZE - }); - - ui->name->setText(ent->name); - ui->archive->setChecked(ent->archive); - ui->skip_auto_update->setChecked(ent->skip_auto_update); - ui->url->setText(ent->url); - ui->type->setCurrentIndex(ent->url.isEmpty() ? 0 : 1); - ui->type->currentIndexChanged(ui->type->currentIndex()); - ui->manually_column_width->setChecked(ent->manually_column_width); - ui->cat_share->setVisible(false); - - if (ent->id >= 0) { // already a group - ui->type->setDisabled(true); - if (!ent->Profiles().isEmpty()) { - ui->cat_share->setVisible(true); - } - } else { // new group - ui->front_proxy->hide(); - ui->front_proxy_l->hide(); - ui->front_proxy_clear->hide(); - } - - CACHE.front_proxy = ent->front_proxy_id; - refresh_front_proxy(); - connect(ui->front_proxy_clear, &QPushButton::clicked, this, [=] { - CACHE.front_proxy = -1; - refresh_front_proxy(); - }); - - connect(ui->copy_links, &QPushButton::clicked, this, [=] { - QStringList links; - for (const auto &[_, profile]: NekoGui::profileManager->profiles) { - if (profile->gid != ent->id) continue; - links += profile->bean->ToShareLink(); - } - QApplication::clipboard()->setText(links.join("\n")); - MessageBoxInfo(software_name, tr("Copied")); - }); - connect(ui->copy_links_nkr, &QPushButton::clicked, this, [=] { - QStringList links; - for (const auto &[_, profile]: NekoGui::profileManager->profiles) { - if (profile->gid != ent->id) continue; - links += profile->bean->ToNekorayShareLink(profile->type); - } - QApplication::clipboard()->setText(links.join("\n")); - MessageBoxInfo(software_name, tr("Copied")); - }); - - ADJUST_SIZE -} - -DialogEditGroup::~DialogEditGroup() { - delete ui; -} - -void DialogEditGroup::accept() { - if (ent->id >= 0) { // already a group - if (!ent->url.isEmpty() && ui->url->text().isEmpty()) { - MessageBoxWarning(tr("Warning"), tr("Please input URL")); - return; - } - } - ent->name = ui->name->text(); - ent->url = ui->url->text(); - ent->archive = ui->archive->isChecked(); - ent->skip_auto_update = ui->skip_auto_update->isChecked(); - ent->manually_column_width = ui->manually_column_width->isChecked(); - ent->front_proxy_id = CACHE.front_proxy; - QDialog::accept(); -} - -void DialogEditGroup::refresh_front_proxy() { - auto fEnt = NekoGui::profileManager->GetProfile(CACHE.front_proxy); - ui->front_proxy->setText(fEnt == nullptr ? tr("None") : fEnt->bean->DisplayTypeAndName()); -} - -void DialogEditGroup::on_front_proxy_clicked() { - auto parent = dynamic_cast(this->parent()); - parent->hide(); - this->hide(); - GetMainWindow()->start_select_mode(this, [=](int id) { - CACHE.front_proxy = id; - refresh_front_proxy(); - parent->show(); - show(); - }); -} diff --git a/ui/edit/dialog_edit_group.h b/ui/edit/dialog_edit_group.h deleted file mode 100644 index 5aa3d9f..0000000 --- a/ui/edit/dialog_edit_group.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include -#include "db/Group.hpp" - -QT_BEGIN_NAMESPACE -namespace Ui { - class DialogEditGroup; -} -QT_END_NAMESPACE - -class DialogEditGroup : public QDialog { - Q_OBJECT - -public: - explicit DialogEditGroup(const std::shared_ptr &ent, QWidget *parent = nullptr); - - ~DialogEditGroup() override; - -private: - Ui::DialogEditGroup *ui; - - std::shared_ptr ent; - - struct { - int front_proxy; - } CACHE; - - void refresh_front_proxy(); - -private slots: - - void accept() override; - - void on_front_proxy_clicked(); -}; diff --git a/ui/edit/dialog_edit_group.ui b/ui/edit/dialog_edit_group.ui deleted file mode 100644 index e6556c7..0000000 --- a/ui/edit/dialog_edit_group.ui +++ /dev/null @@ -1,230 +0,0 @@ - - - DialogEditGroup - - - - 0 - 0 - 400 - 468 - - - - - 400 - 300 - - - - Edit Group - - - - - - - 0 - 0 - - - - Common - - - - - - - - - Type - - - - - - - - Basic - - - - - Subscription - - - - - - - - Front Proxy - - - - - - - - - Manually column width - - - - - - - Archive - - - - - - - - - Name - - - - - - - - - - - - - - - - - 0 - 0 - - - - Clear - - - - - - - - - - - - Subscription - - - - - - URL - - - - - - - - - - Skip automatic update - - - - - - - - - - Share - - - - - - Copy profile share links - - - - - - - Copy profile share links (Neko Links) - - - - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - MyLineEdit - QLineEdit -
ui/widget/MyLineEdit.h
-
-
- - name - type - front_proxy - front_proxy_clear - manually_column_width - archive - url - skip_auto_update - copy_links - copy_links_nkr - - - - - buttonBox - rejected() - DialogEditGroup - reject() - - - 199 - 275 - - - 199 - 149 - - - - - buttonBox - accepted() - DialogEditGroup - accept() - - - 199 - 291 - - - 199 - 157 - - - - -
diff --git a/ui/edit/dialog_edit_profile.cpp b/ui/edit/dialog_edit_profile.cpp deleted file mode 100644 index 47d3faf..0000000 --- a/ui/edit/dialog_edit_profile.cpp +++ /dev/null @@ -1,523 +0,0 @@ -#include "dialog_edit_profile.h" -#include "ui_dialog_edit_profile.h" - -#include "ui/edit/edit_socks_http.h" -#include "ui/edit/edit_shadowsocks.h" -#include "ui/edit/edit_chain.h" -#include "ui/edit/edit_vmess.h" -#include "ui/edit/edit_trojan_vless.h" -#include "ui/edit/edit_naive.h" -#include "ui/edit/edit_quic.h" -#include "ui/edit/edit_custom.h" - -#include "fmt/includes.h" -#include "fmt/Preset.hpp" - -#include "3rdparty/qv2ray/v2/ui/widgets/editors/w_JsonEditor.hpp" -#include "main/GuiUtils.hpp" - -#include - -#define ADJUST_SIZE runOnUiThread([=] { adjustSize(); adjustPosition(mainwindow); }, this); -#define LOAD_TYPE(a) ui->type->addItem(NekoGui::ProfileManager::NewProxyEntity(a)->bean->DisplayType(), a); - -DialogEditProfile::DialogEditProfile(const QString &_type, int profileOrGroupId, QWidget *parent) - : QDialog(parent), ui(new Ui::DialogEditProfile) { - // setup UI - ui->setupUi(this); - ui->dialog_layout->setAlignment(ui->left, Qt::AlignTop); - - // network changed - network_title_base = ui->network_box->title(); - connect(ui->network, &QComboBox::currentTextChanged, this, [=](const QString &txt) { - ui->network_box->setTitle(network_title_base.arg(txt)); - // 传输设置 - if (txt == "tcp") { - ui->header_type->setVisible(true); - ui->header_type_l->setVisible(true); - ui->path->setVisible(true); - ui->path_l->setVisible(true); - ui->host->setVisible(true); - ui->host_l->setVisible(true); - } else if (txt == "grpc") { - ui->header_type->setVisible(false); - ui->header_type_l->setVisible(false); - ui->path->setVisible(true); - ui->path_l->setVisible(true); - ui->host->setVisible(false); - ui->host_l->setVisible(false); - } else if (txt == "ws" || txt == "http" || txt == "httpupgrade") { - ui->header_type->setVisible(false); - ui->header_type_l->setVisible(false); - ui->path->setVisible(true); - ui->path_l->setVisible(true); - ui->host->setVisible(true); - ui->host_l->setVisible(true); - } else { - ui->header_type->setVisible(false); - ui->header_type_l->setVisible(false); - ui->path->setVisible(false); - ui->path_l->setVisible(false); - ui->host->setVisible(false); - ui->host_l->setVisible(false); - } - // 传输设置 ED - if (txt == "ws") { - ui->ws_early_data_length->setVisible(true); - ui->ws_early_data_length_l->setVisible(true); - ui->ws_early_data_name->setVisible(true); - ui->ws_early_data_name_l->setVisible(true); - } else { - ui->ws_early_data_length->setVisible(false); - ui->ws_early_data_length_l->setVisible(false); - ui->ws_early_data_name->setVisible(false); - ui->ws_early_data_name_l->setVisible(false); - } - // 传输设置 for NekoBox - if (!ui->utlsFingerprint->count()) ui->utlsFingerprint->addItems(Preset::SingBox::UtlsFingerPrint); - // 传输设置 是否可见 - int networkBoxVisible = 0; - for (auto label: ui->network_box->findChildren()) { - if (!label->isHidden()) networkBoxVisible++; - } - ui->network_box->setVisible(networkBoxVisible); - ADJUST_SIZE - }); - ui->network->removeItem(0); - - // security changed - connect(ui->security, &QComboBox::currentTextChanged, this, [=](const QString &txt) { - if (txt == "tls") { - ui->security_box->setVisible(true); - ui->tls_camouflage_box->setVisible(true); - ui->reality_spx->hide(); - ui->reality_spx_l->hide(); - } else { - ui->security_box->setVisible(false); - ui->tls_camouflage_box->setVisible(false); - } - ADJUST_SIZE - }); - emit ui->security->currentTextChanged(ui->security->currentText()); - - // 确定模式和 ent - newEnt = _type != ""; - if (newEnt) { - this->groupId = profileOrGroupId; - this->type = _type; - - // load type to combo box - LOAD_TYPE("socks") - LOAD_TYPE("http") - LOAD_TYPE("shadowsocks") - LOAD_TYPE("trojan") - LOAD_TYPE("vmess") - LOAD_TYPE("vless") - LOAD_TYPE("naive") - LOAD_TYPE("hysteria2") - LOAD_TYPE("tuic") - ui->type->addItem(tr("Custom (%1 outbound)").arg(software_core_name), "internal"); - ui->type->addItem(tr("Custom (%1 config)").arg(software_core_name), "internal-full"); - ui->type->addItem(tr("Custom (Extra Core)"), "custom"); - LOAD_TYPE("chain") - - // type changed - connect(ui->type, static_cast(&QComboBox::currentIndexChanged), this, [=](int index) { - typeSelected(ui->type->itemData(index).toString()); - }); - - ui->apply_to_group->hide(); - } else { - this->ent = NekoGui::profileManager->GetProfile(profileOrGroupId); - if (this->ent == nullptr) return; - this->type = ent->type; - ui->type->setVisible(false); - ui->type_l->setVisible(false); - } - - typeSelected(this->type); -} - -DialogEditProfile::~DialogEditProfile() { - delete ui; -} - -void DialogEditProfile::typeSelected(const QString &newType) { - QString customType; - type = newType; - bool validType = true; - - if (type == "socks" || type == "http") { - auto _innerWidget = new EditSocksHttp(this); - innerWidget = _innerWidget; - innerEditor = _innerWidget; - } else if (type == "shadowsocks") { - auto _innerWidget = new EditShadowSocks(this); - innerWidget = _innerWidget; - innerEditor = _innerWidget; - } else if (type == "chain") { - auto _innerWidget = new EditChain(this); - innerWidget = _innerWidget; - innerEditor = _innerWidget; - } else if (type == "vmess") { - auto _innerWidget = new EditVMess(this); - innerWidget = _innerWidget; - innerEditor = _innerWidget; - } else if (type == "trojan" || type == "vless") { - auto _innerWidget = new EditTrojanVLESS(this); - innerWidget = _innerWidget; - innerEditor = _innerWidget; - } else if (type == "naive") { - auto _innerWidget = new EditNaive(this); - innerWidget = _innerWidget; - innerEditor = _innerWidget; - } else if (type == "hysteria2" || type == "tuic") { - auto _innerWidget = new EditQUIC(this); - innerWidget = _innerWidget; - innerEditor = _innerWidget; - } else if (type == "custom" || type == "internal" || type == "internal-full") { - auto _innerWidget = new EditCustom(this); - innerWidget = _innerWidget; - innerEditor = _innerWidget; - customType = newEnt ? type : ent->CustomBean()->core; - if (customType != "custom") _innerWidget->preset_core = customType; - type = "custom"; - } else { - validType = false; - } - - if (!validType) { - MessageBoxWarning(newType, "Wrong type"); - return; - } - - if (newEnt) { - this->ent = NekoGui::ProfileManager::NewProxyEntity(type); - this->ent->gid = groupId; - } - - // hide some widget - auto showAddressPort = type != "chain" && customType != "internal" && customType != "internal-full"; - ui->address->setVisible(showAddressPort); - ui->address_l->setVisible(showAddressPort); - ui->port->setVisible(showAddressPort); - ui->port_l->setVisible(showAddressPort); - - // 右边 stream - auto stream = GetStreamSettings(ent->bean.get()); - if (stream != nullptr) { - ui->right_all_w->setVisible(true); - ui->network->setCurrentText(stream->network); - ui->security->setCurrentText(stream->security); - ui->packet_encoding->setCurrentText(stream->packet_encoding); - ui->path->setText(stream->path); - ui->host->setText(stream->host); - ui->sni->setText(stream->sni); - ui->alpn->setText(stream->alpn); - if (newEnt) { - ui->utlsFingerprint->setCurrentText(NekoGui::dataStore->utlsFingerprint); - } else { - ui->utlsFingerprint->setCurrentText(stream->utlsFingerprint); - } - ui->insecure->setChecked(stream->allow_insecure); - ui->header_type->setCurrentText(stream->header_type); - ui->ws_early_data_name->setText(stream->ws_early_data_name); - ui->ws_early_data_length->setText(Int2String(stream->ws_early_data_length)); - ui->reality_pbk->setText(stream->reality_pbk); - ui->reality_sid->setText(stream->reality_sid); - ui->multiplex->setCurrentIndex(stream->multiplex_status); - CACHE.certificate = stream->certificate; - } else { - ui->right_all_w->setVisible(false); - } - - // left: custom - CACHE.custom_config = ent->bean->custom_config; - CACHE.custom_outbound = ent->bean->custom_outbound; - bool show_custom_config = true; - bool show_custom_outbound = true; - if (type == "chain") { - show_custom_outbound = false; - } else if (type == "custom") { - if (customType == "internal") { - show_custom_outbound = false; - } else if (customType == "internal-full") { - show_custom_outbound = false; - show_custom_config = false; - } - } - ui->custom_box->setVisible(show_custom_outbound); - ui->custom_global_box->setVisible(show_custom_config); - - // 左边 bean - auto old = ui->bean->layout()->itemAt(0)->widget(); - ui->bean->layout()->removeWidget(old); - innerWidget->layout()->setContentsMargins(0, 0, 0, 0); - ui->bean->layout()->addWidget(innerWidget); - ui->bean->setTitle(ent->bean->DisplayType()); - delete old; - - // 左边 bean inner editor - innerEditor->get_edit_dialog = [&]() { return (QWidget *) this; }; - innerEditor->get_edit_text_name = [&]() { return ui->name->text(); }; - innerEditor->get_edit_text_serverAddress = [&]() { return ui->address->text(); }; - innerEditor->get_edit_text_serverPort = [&]() { return ui->port->text(); }; - innerEditor->editor_cache_updated = [=] { editor_cache_updated_impl(); }; - innerEditor->onStart(ent); - - // 左边 common - ui->name->setText(ent->bean->name); - ui->address->setText(ent->bean->serverAddress); - ui->port->setText(Int2String(ent->bean->serverPort)); - ui->port->setValidator(QRegExpValidator_Number); - - // 星号 - ADD_ASTERISK(this) - - // 设置 for NekoBox - if (type == "vmess" || type == "vless") { - ui->packet_encoding->setVisible(true); - ui->packet_encoding_l->setVisible(true); - } else { - ui->packet_encoding->setVisible(false); - ui->packet_encoding_l->setVisible(false); - } - if (type == "vmess" || type == "vless" || type == "trojan") { - ui->network_l->setVisible(true); - ui->network->setVisible(true); - ui->network_box->setVisible(true); - } else { - ui->network_l->setVisible(false); - ui->network->setVisible(false); - ui->network_box->setVisible(false); - } - if (type == "vmess" || type == "vless" || type == "trojan" || type == "http") { - ui->security->setVisible(true); - ui->security_l->setVisible(true); - } else { - ui->security->setVisible(false); - ui->security_l->setVisible(false); - } - if (type == "vmess" || type == "vless" || type == "trojan" || type == "shadowsocks") { - ui->multiplex->setVisible(true); - ui->multiplex_l->setVisible(true); - } else { - ui->multiplex->setVisible(false); - ui->multiplex_l->setVisible(false); - } - - // 设置 是否可见 - int streamBoxVisible = 0; - for (auto label: ui->stream_box->findChildren()) { - if (!label->isHidden()) streamBoxVisible++; - } - ui->stream_box->setVisible(streamBoxVisible); - - // 载入 type 之后,有些类型没有右边的设置 - auto rightNoBox = (ui->stream_box->isHidden() && ui->network_box->isHidden() && ui->security_box->isHidden()); - if (rightNoBox && !ui->right_all_w->isHidden()) { - ui->right_all_w->setVisible(false); - } - - editor_cache_updated_impl(); - ADJUST_SIZE - - // 第一次显示 - if (isHidden()) { - runOnUiThread([=] { show(); }, this); - } -} - -bool DialogEditProfile::onEnd() { - // bean - if (!innerEditor->onEnd()) { - return false; - } - - // 左边 - ent->bean->name = ui->name->text(); - ent->bean->serverAddress = ui->address->text().remove(' '); - ent->bean->serverPort = ui->port->text().toInt(); - - // 右边 stream - auto stream = GetStreamSettings(ent->bean.get()); - if (stream != nullptr) { - stream->network = ui->network->currentText(); - stream->security = ui->security->currentText(); - stream->packet_encoding = ui->packet_encoding->currentText(); - stream->path = ui->path->text(); - stream->host = ui->host->text(); - stream->sni = ui->sni->text(); - stream->alpn = ui->alpn->text(); - stream->utlsFingerprint = ui->utlsFingerprint->currentText(); - stream->allow_insecure = ui->insecure->isChecked(); - stream->header_type = ui->header_type->currentText(); - stream->ws_early_data_name = ui->ws_early_data_name->text(); - stream->ws_early_data_length = ui->ws_early_data_length->text().toInt(); - stream->reality_pbk = ui->reality_pbk->text(); - stream->reality_sid = ui->reality_sid->text(); - stream->multiplex_status = ui->multiplex->currentIndex(); - stream->certificate = CACHE.certificate; - } - - // cached custom - ent->bean->custom_outbound = CACHE.custom_outbound; - ent->bean->custom_config = CACHE.custom_config; - - return true; -} - -void DialogEditProfile::accept() { - // save to ent - if (!onEnd()) { - return; - } - - // finish - QStringList msg = {"accept"}; - - if (newEnt) { - auto ok = NekoGui::profileManager->AddProfile(ent); - if (!ok) { - MessageBoxWarning("???", "id exists"); - } - } else { - auto changed = ent->Save(); - if (changed && NekoGui::dataStore->started_id == ent->id) msg << "restart"; - } - - MW_dialog_message(Dialog_DialogEditProfile, msg.join(",")); - QDialog::accept(); -} - -// cached editor (dialog) - -void DialogEditProfile::editor_cache_updated_impl() { - if (CACHE.certificate.isEmpty()) { - ui->certificate_edit->setText(tr("Not set")); - } else { - ui->certificate_edit->setText(tr("Already set")); - } - if (CACHE.custom_outbound.isEmpty()) { - ui->custom_outbound_edit->setText(tr("Not set")); - } else { - ui->custom_outbound_edit->setText(tr("Already set")); - } - if (CACHE.custom_config.isEmpty()) { - ui->custom_config_edit->setText(tr("Not set")); - } else { - ui->custom_config_edit->setText(tr("Already set")); - } - - // CACHE macro - for (auto a: innerEditor->get_editor_cached()) { - if (a.second.isEmpty()) { - a.first->setText(tr("Not set")); - } else { - a.first->setText(tr("Already set")); - } - } -} - -void DialogEditProfile::on_custom_outbound_edit_clicked() { - C_EDIT_JSON_ALLOW_EMPTY(custom_outbound) - editor_cache_updated_impl(); -} - -void DialogEditProfile::on_custom_config_edit_clicked() { - C_EDIT_JSON_ALLOW_EMPTY(custom_config) - editor_cache_updated_impl(); -} - -void DialogEditProfile::on_certificate_edit_clicked() { - bool ok; - auto txt = QInputDialog::getMultiLineText(this, tr("Certificate"), "", CACHE.certificate, &ok); - if (ok) { - CACHE.certificate = txt; - editor_cache_updated_impl(); - } -} - -void DialogEditProfile::on_apply_to_group_clicked() { - if (apply_to_group_ui.empty()) { - apply_to_group_ui[ui->multiplex] = new FloatCheckBox(ui->multiplex, this); - apply_to_group_ui[ui->sni] = new FloatCheckBox(ui->sni, this); - apply_to_group_ui[ui->alpn] = new FloatCheckBox(ui->alpn, this); - apply_to_group_ui[ui->host] = new FloatCheckBox(ui->host, this); - apply_to_group_ui[ui->path] = new FloatCheckBox(ui->path, this); - apply_to_group_ui[ui->utlsFingerprint] = new FloatCheckBox(ui->utlsFingerprint, this); - apply_to_group_ui[ui->insecure] = new FloatCheckBox(ui->insecure, this); - apply_to_group_ui[ui->certificate_edit] = new FloatCheckBox(ui->certificate_edit, this); - apply_to_group_ui[ui->custom_config_edit] = new FloatCheckBox(ui->custom_config_edit, this); - apply_to_group_ui[ui->custom_outbound_edit] = new FloatCheckBox(ui->custom_outbound_edit, this); - ui->apply_to_group->setText(tr("Confirm")); - } else { - auto group = NekoGui::profileManager->GetGroup(ent->gid); - if (group == nullptr) { - MessageBoxWarning("failed", "unknown group"); - return; - } - // save this - if (onEnd()) { - ent->Save(); - } else { - MessageBoxWarning("failed", "failed to save"); - return; - } - // copy keys - for (const auto &pair: apply_to_group_ui) { - if (pair.second->isChecked()) { - do_apply_to_group(group, pair.first); - } - delete pair.second; - } - apply_to_group_ui.clear(); - ui->apply_to_group->setText(tr("Apply settings to this group")); - } -} - -void DialogEditProfile::do_apply_to_group(const std::shared_ptr &group, QWidget *key) { - auto stream = GetStreamSettings(ent->bean.get()); - - auto copyStream = [=](void *p) { - for (const auto &profile: group->Profiles()) { - auto newStream = GetStreamSettings(profile->bean.get()); - if (newStream == nullptr) continue; - if (stream == newStream) continue; - newStream->_setValue(stream->_name(p), p); - // qDebug() << newStream->ToJsonBytes(); - profile->Save(); - } - }; - - auto copyBean = [=](void *p) { - for (const auto &profile: group->Profiles()) { - if (profile == ent) continue; - profile->bean->_setValue(ent->bean->_name(p), p); - // qDebug() << profile->bean->ToJsonBytes(); - profile->Save(); - } - }; - - if (key == ui->multiplex) { - copyStream(&stream->multiplex_status); - } else if (key == ui->sni) { - copyStream(&stream->sni); - } else if (key == ui->alpn) { - copyStream(&stream->alpn); - } else if (key == ui->host) { - copyStream(&stream->host); - } else if (key == ui->path) { - copyStream(&stream->path); - } else if (key == ui->utlsFingerprint) { - copyStream(&stream->utlsFingerprint); - } else if (key == ui->insecure) { - copyStream(&stream->allow_insecure); - } else if (key == ui->certificate_edit) { - copyStream(&stream->certificate); - } else if (key == ui->custom_config_edit) { - copyBean(&ent->bean->custom_config); - } else if (key == ui->custom_outbound_edit) { - copyBean(&ent->bean->custom_outbound); - } -} diff --git a/ui/edit/dialog_edit_profile.h b/ui/edit/dialog_edit_profile.h deleted file mode 100644 index 3e8ae50..0000000 --- a/ui/edit/dialog_edit_profile.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef DIALOG_EDIT_PROFILE_H -#define DIALOG_EDIT_PROFILE_H - -#include -#include "db/Database.hpp" -#include "profile_editor.h" - -#include "ui/widget/FloatCheckBox.h" - -namespace Ui { - class DialogEditProfile; -} - -class DialogEditProfile : public QDialog { - Q_OBJECT - -public: - explicit DialogEditProfile(const QString &_type, int profileOrGroupId, QWidget *parent = nullptr); - - ~DialogEditProfile() override; - -public slots: - - void accept() override; - -private slots: - - void on_custom_outbound_edit_clicked(); - - void on_custom_config_edit_clicked(); - - void on_certificate_edit_clicked(); - - void on_apply_to_group_clicked(); - -private: - Ui::DialogEditProfile *ui; - - std::map apply_to_group_ui; - - QWidget *innerWidget{}; - ProfileEditor *innerEditor{}; - - QString type; - int groupId; - bool newEnt = false; - std::shared_ptr ent; - - QString network_title_base; - - struct { - QString custom_outbound; - QString custom_config; - QString certificate; - } CACHE; - - void typeSelected(const QString &newType); - - bool onEnd(); - - void editor_cache_updated_impl(); - - void do_apply_to_group(const std::shared_ptr &group, QWidget *key); -}; - -#endif // DIALOG_EDIT_PROFILE_H diff --git a/ui/edit/dialog_edit_profile.ui b/ui/edit/dialog_edit_profile.ui deleted file mode 100644 index a39379a..0000000 --- a/ui/edit/dialog_edit_profile.ui +++ /dev/null @@ -1,705 +0,0 @@ - - - DialogEditProfile - - - - 0 - 0 - 1000 - 802 - - - - - 0 - 0 - - - - Edit - - - - - - - 0 - 0 - - - - - 400 - 0 - - - - - QLayout::SetDefaultConstraint - - - - - - 0 - 0 - - - - Common - - - - - - - - - - - - - - - - - Type - - - - - - - Port - - - - - - - Address - - - - - - - Name - - - - - - - - - - - - - - - - 0 - 0 - - - - Bean - - - - - - - - - - - - - - - 0 - 0 - - - - Custom Outbound Settings - - - - - - Edit - - - - - - - - - - Custom Config Settings - - - - - - Edit - - - - - - - - - - - - - - Apply settings to this group - - - - - - - - 0 - 0 - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - - - - - 0 - 0 - - - - - 400 - 0 - - - - - - - - QLayout::SetDefaultConstraint - - - - - - 0 - 0 - - - - Settings - - - - - - - - - 0 - 0 - - - - - - - - - - tcp - - - - - ws - - - - - httpupgrade - - - - - http - - - - - grpc - - - - - quic - - - - - - - - - - - - - - packetaddr - - - - - xudp - - - - - - - - The underlying transport method. It must be consistent with the server, otherwise, the connection cannot be established. - - - Network - - - - - - - - - - - - - tls - - - - - - - - Transport Layer Security. It must be consistent with the server, otherwise, the connection cannot be established. - - - Security - - - - - - - UDP FullCone Packet encoding for implementing features such as UDP FullCone. Server support is required, if the wrong selection is made, the connection cannot be made. Please leave it blank. - - - Packet Encoding - - - - - - - Server support is required - - - Multiplex - - - - - - - - Keep Default - - - - - On - - - - - Off - - - - - - - - - - - - - - 0 - 0 - - - - Network Settings (%1) - - - - - - http path (ws/http/伪装http) -serviceName (gRPC) -key (QUIC) - - - Path - - - - - - - - - - http host (ws/http/伪装http) -security (QUIC) - - - Host - - - - - - - - 0 - 0 - - - - 伪装头部类型 (tcp/quic) - - - header - - - - - - - - - - - 0 - 0 - - - - true - - - - - - - - - http - - - - - - - - - - - EarlyData Length - - - - - - - - - - EarlyData Name - - - - - - - - - - - 0 - 0 - - - - TLS Security Settings - - - - - - - - - 0 - 0 - - - - When enabled, V2Ray will not check the validity of the TLS certificate provided by the remote host (the security is equivalent to plaintext) - - - Allow insecure - - - - - - - Qt::Vertical - - - - - - - - 0 - 0 - - - - - - - Certificate - - - - - - - Edit - - - - - - - - - - - - - - Server name indication, clear text. - - - SNI - - - - - - - Application layer protocol negotiation, clear text. Please separate them with commas. - - - ALPN - - - - - - - - - - - - - - - TLS Camouflage Settings - - - - - - true - - - - - - - - 0 - 0 - - - - Fingerprint - - - - - - - Reality public key. If not empty, turn TLS into REALITY. - - - Reality Pbk - - - - - - - Reality short id. Accept only one value. - - - Reality Sid - - - - - - - - - - - - - - - - SpiderX - - - - - - - - - - - - - - - - - MyLineEdit - QLineEdit -
ui/widget/MyLineEdit.h
-
-
- - type - name - address - port - custom_outbound_edit - custom_config_edit - apply_to_group - network - security - packet_encoding - multiplex - header_type - path - host - ws_early_data_length - ws_early_data_name - insecure - certificate_edit - sni - alpn - utlsFingerprint - reality_pbk - reality_sid - - - - - buttonBox - accepted() - DialogEditProfile - accept() - - - 151 - 500 - - - 299 - 299 - - - - - buttonBox - rejected() - DialogEditProfile - reject() - - - 151 - 500 - - - 299 - 299 - - - - -
diff --git a/ui/edit/edit_chain.cpp b/ui/edit/edit_chain.cpp deleted file mode 100644 index a84d365..0000000 --- a/ui/edit/edit_chain.cpp +++ /dev/null @@ -1,78 +0,0 @@ -#include "edit_chain.h" -#include "ui_edit_chain.h" - -#include "ui/mainwindow_interface.h" -#include "ui/widget/ProxyItem.h" - -#include "db/Database.hpp" -#include "fmt/ChainBean.hpp" - -EditChain::EditChain(QWidget *parent) : QWidget(parent), ui(new Ui::EditChain) { - ui->setupUi(this); -} - -EditChain::~EditChain() { - delete ui; -} - -void EditChain::onStart(std::shared_ptr _ent) { - this->ent = _ent; - auto bean = this->ent->ChainBean(); - - for (auto id: bean->list) { - AddProfileToListIfExist(id); - } -} - -bool EditChain::onEnd() { - if (get_edit_text_name().isEmpty()) { - MessageBoxWarning(software_name, tr("Name cannot be empty.")); - return false; - } - - auto bean = this->ent->ChainBean(); - - QList idList; - for (int i = 0; i < ui->listWidget->count(); i++) { - idList << ui->listWidget->item(i)->data(114514).toInt(); - } - bean->list = idList; - - return true; -} - -void EditChain::on_select_profile_clicked() { - get_edit_dialog()->hide(); - GetMainWindow()->start_select_mode(this, [=](int id) { - get_edit_dialog()->show(); - AddProfileToListIfExist(id); - }); -} - -void EditChain::AddProfileToListIfExist(int profileId) { - auto _ent = NekoGui::profileManager->GetProfile(profileId); - if (_ent != nullptr && _ent->type != "chain") { - auto wI = new QListWidgetItem(); - wI->setData(114514, profileId); - auto w = new ProxyItem(this, _ent, wI); - ui->listWidget->addItem(wI); - ui->listWidget->setItemWidget(wI, w); - // change button - connect(w->get_change_button(), &QPushButton::clicked, w, [=] { - get_edit_dialog()->hide(); - GetMainWindow()->start_select_mode(w, [=](int newId) { - get_edit_dialog()->show(); - ReplaceProfile(w, newId); - }); - }); - } -} - -void EditChain::ReplaceProfile(ProxyItem *w, int profileId) { - auto _ent = NekoGui::profileManager->GetProfile(profileId); - if (_ent != nullptr && _ent->type != "chain") { - w->item->setData(114514, profileId); - w->ent = _ent; - w->refresh_data(); - } -} diff --git a/ui/edit/edit_chain.h b/ui/edit/edit_chain.h deleted file mode 100644 index 61348d4..0000000 --- a/ui/edit/edit_chain.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -#include -#include "profile_editor.h" - -QT_BEGIN_NAMESPACE -namespace Ui { - class EditChain; -} -QT_END_NAMESPACE - -class ProxyItem; - -class EditChain : public QWidget, public ProfileEditor { - Q_OBJECT - -public: - explicit EditChain(QWidget *parent = nullptr); - - ~EditChain() override; - - void onStart(std::shared_ptr _ent) override; - - bool onEnd() override; - -private: - Ui::EditChain *ui; - std::shared_ptr ent; - - void AddProfileToListIfExist(int profileId); - - static void ReplaceProfile(ProxyItem *w, int profileId); - -private slots: - - void on_select_profile_clicked(); -}; diff --git a/ui/edit/edit_chain.ui b/ui/edit/edit_chain.ui deleted file mode 100644 index 13996bb..0000000 --- a/ui/edit/edit_chain.ui +++ /dev/null @@ -1,57 +0,0 @@ - - - EditChain - - - - 0 - 0 - 400 - 400 - - - - EditChain - - - - - - Traffic order is from top to bottom - - - - - - - - 0 - 300 - - - - Qt::ActionsContextMenu - - - QAbstractItemView::InternalMove - - - Qt::MoveAction - - - QListView::Free - - - - - - - Select Profile - - - - - - - - diff --git a/ui/edit/edit_custom.cpp b/ui/edit/edit_custom.cpp deleted file mode 100644 index e49a0c9..0000000 --- a/ui/edit/edit_custom.cpp +++ /dev/null @@ -1,153 +0,0 @@ -#include "edit_custom.h" -#include "ui_edit_custom.h" - -#include "3rdparty/qv2ray/v2/ui/widgets/editors/w_JsonEditor.hpp" -#include "fmt/CustomBean.hpp" -#include "fmt/Preset.hpp" -#include "db/ConfigBuilder.hpp" -#include "db/Database.hpp" - -#include -#include - -EditCustom::EditCustom(QWidget *parent) : QWidget(parent), ui(new Ui::EditCustom) { - ui->setupUi(this); - ui->config_simple->setPlaceholderText( - "example:\n" - " server-address: \"127.0.0.1:%mapping_port%\"\n" - " listen-address: \"127.0.0.1\"\n" - " listen-port: %socks_port%\n" - " host: your-domain.com\n" - " sni: your-domain.com\n"); -} - -EditCustom::~EditCustom() { - delete ui; -} - -#define SAVE_CUSTOM_BEAN \ - P_SAVE_COMBO_STRING(core) \ - bean->command = ui->command->text().split(" "); \ - P_SAVE_STRING_PLAIN(config_simple) \ - P_SAVE_COMBO_STRING(config_suffix) \ - P_SAVE_INT(mapping_port) \ - P_SAVE_INT(socks_port) - -void EditCustom::onStart(std::shared_ptr _ent) { - this->ent = _ent; - auto bean = this->ent->CustomBean(); - - // load known core - auto core_map = QString2QJsonObject(NekoGui::dataStore->extraCore->core_map); - for (const auto &key: core_map.keys()) { - ui->core->addItem(key); - } - if (preset_core == "internal") { - preset_command = preset_config = ""; - ui->config_simple->setPlaceholderText( - "{\n" - " \"type\": \"socks\",\n" - " // ...\n" - "}"); - } else if (preset_core == "internal-full") { - preset_command = preset_config = ""; - ui->config_simple->setPlaceholderText( - "{\n" - " \"inbounds\": [],\n" - " \"outbounds\": []\n" - "}"); - } - - // load core ui - P_LOAD_COMBO_STRING(core) - ui->command->setText(bean->command.join(" ")); - ui->config_simple->setPlainText(bean->config_simple); - P_LOAD_COMBO_STRING(config_suffix) - P_LOAD_INT(mapping_port) - P_LOAD_INT(socks_port) - - // custom external - if (!bean->core.isEmpty()) { - ui->core->setDisabled(true); - } else if (!preset_core.isEmpty()) { - bean->core = preset_core; - ui->core->setDisabled(true); - ui->core->setCurrentText(preset_core); - ui->command->setText(preset_command); - ui->config_simple->setPlainText(preset_config); - } - - // custom internal - if (preset_core == "internal" || preset_core == "internal-full") { - ui->core->hide(); - if (preset_core == "internal") { - ui->core_l->setText(tr("Outbound JSON, please read the documentation.")); - } else { - ui->core_l->setText(tr("Please fill the complete config.")); - } - ui->w_ext1->hide(); - ui->w_ext2->hide(); - } - - // Preview - connect(ui->preview, &QPushButton::clicked, this, [=] { - // CustomBean::BuildExternal - QStringList th; - auto mapping_port = ui->mapping_port->text().toInt(); - auto socks_port = ui->socks_port->text().toInt(); - th << "%mapping_port% => " + (mapping_port <= 0 ? "Random" : Int2String(mapping_port)); - th << "%socks_port% => " + (socks_port <= 0 ? "Random" : Int2String(socks_port)); - th << "%server_addr% => " + get_edit_text_serverAddress(); - th << "%server_port% => " + get_edit_text_serverPort(); - MessageBoxInfo(tr("Preview replace"), th.join("\n")); - // EditCustom::onEnd - auto tmpEnt = NekoGui::ProfileManager::NewProxyEntity("custom"); - auto bean = tmpEnt->CustomBean(); - SAVE_CUSTOM_BEAN - // 补充 - bean->serverAddress = get_edit_text_serverAddress(); - bean->serverPort = get_edit_text_serverPort().toInt(); - if (bean->core.isEmpty()) return; - // - auto result = NekoGui::BuildConfig(tmpEnt, false, false); - if (!result->error.isEmpty()) { - MessageBoxInfo(software_name, result->error); - return; - } - for (const auto &extR: result->extRs) { - auto command = QStringList{extR->program}; - command += extR->arguments; - auto btn = QMessageBox::information(this, tr("Preview config"), - QStringLiteral("Command: %1\n\n%2").arg(QStringList2Command(command), extR->config_export), - "OK", "Copy", "", 0, 0); - if (btn == 1) { - QApplication::clipboard()->setText(extR->config_export); - } - } - }); -} - -bool EditCustom::onEnd() { - if (get_edit_text_name().isEmpty()) { - MessageBoxWarning(software_name, tr("Name cannot be empty.")); - return false; - } - if (ui->core->currentText().isEmpty()) { - MessageBoxWarning(software_name, tr("Please pick a core.")); - return false; - } - - auto bean = this->ent->CustomBean(); - - SAVE_CUSTOM_BEAN - - return true; -} - -void EditCustom::on_as_json_clicked() { - auto editor = new JsonEditor(QString2QJsonObject(ui->config_simple->toPlainText()), this); - auto result = editor->OpenEditor(); - if (!result.isEmpty()) { - ui->config_simple->setPlainText(QJsonObject2QString(result, false)); - } -} diff --git a/ui/edit/edit_custom.h b/ui/edit/edit_custom.h deleted file mode 100644 index 9de5373..0000000 --- a/ui/edit/edit_custom.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include -#include "profile_editor.h" - -QT_BEGIN_NAMESPACE -namespace Ui { - class EditCustom; -} -QT_END_NAMESPACE - -class EditCustom : public QWidget, public ProfileEditor { - Q_OBJECT - -public: - QString preset_core; - QString preset_command; - QString preset_config; - - explicit EditCustom(QWidget *parent = nullptr); - - ~EditCustom() override; - - void onStart(std::shared_ptr _ent) override; - - bool onEnd() override; - -private: - Ui::EditCustom *ui; - std::shared_ptr ent; - -private slots: - - void on_as_json_clicked(); -}; diff --git a/ui/edit/edit_custom.ui b/ui/edit/edit_custom.ui deleted file mode 100644 index cb1fa41..0000000 --- a/ui/edit/edit_custom.ui +++ /dev/null @@ -1,209 +0,0 @@ - - - EditCustom - - - - 0 - 0 - 400 - 450 - - - - EditCustom - - - - - - - - - 0 - 0 - - - - Core - - - - - - - - 0 - 0 - - - - true - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - Json Editor - - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Command - - - - - - - %config% - - - - - - - Config Suffix - - - - - - - true - - - - - - - - - json - - - - - yml - - - - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Random if it's empty or zero. - - - Mapping Port - - - - - - - - - - Random if it's empty or zero. - - - Socks Port - - - - - - - - - - Preview - - - - - - - - - - - 0 - 300 - - - - - - - - core - as_json - command - config_suffix - mapping_port - socks_port - preview - config_simple - - - - diff --git a/ui/edit/edit_naive.cpp b/ui/edit/edit_naive.cpp deleted file mode 100644 index 7539251..0000000 --- a/ui/edit/edit_naive.cpp +++ /dev/null @@ -1,68 +0,0 @@ -#include "edit_naive.h" -#include "ui_edit_naive.h" - -#include "fmt/NaiveBean.hpp" - -#include - -EditNaive::EditNaive(QWidget *parent) : QWidget(parent), ui(new Ui::EditNaive) { - ui->setupUi(this); -} - -EditNaive::~EditNaive() { - delete ui; -} - -void EditNaive::onStart(std::shared_ptr _ent) { - this->ent = _ent; - auto bean = this->ent->NaiveBean(); - - P_LOAD_STRING(username); - P_LOAD_STRING(password); - P_LOAD_COMBO_STRING(protocol); - P_C_LOAD_STRING(extra_headers); - P_LOAD_STRING(sni); - P_C_LOAD_STRING(certificate); - P_LOAD_INT(insecure_concurrency); - P_LOAD_BOOL(disable_log); -} - -bool EditNaive::onEnd() { - auto bean = this->ent->NaiveBean(); - - P_SAVE_STRING(username); - P_SAVE_STRING(password); - P_SAVE_COMBO_STRING(protocol); - P_C_SAVE_STRING(extra_headers); - P_SAVE_STRING(sni); - P_C_SAVE_STRING(certificate); - P_SAVE_INT(insecure_concurrency); - P_SAVE_BOOL(disable_log); - - return true; -} - -QList> EditNaive::get_editor_cached() { - return { - {ui->certificate, CACHE.certificate}, - {ui->extra_headers, CACHE.extra_headers}, - }; -} - -void EditNaive::on_certificate_clicked() { - bool ok; - auto txt = QInputDialog::getMultiLineText(this, tr("Certificate"), "", CACHE.certificate, &ok); - if (ok) { - CACHE.certificate = txt; - editor_cache_updated(); - } -} - -void EditNaive::on_extra_headers_clicked() { - bool ok; - auto txt = QInputDialog::getMultiLineText(this, tr("Extra headers"), "", CACHE.extra_headers, &ok); - if (ok) { - CACHE.extra_headers = txt; - editor_cache_updated(); - } -} diff --git a/ui/edit/edit_naive.h b/ui/edit/edit_naive.h deleted file mode 100644 index f1334cf..0000000 --- a/ui/edit/edit_naive.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include -#include "profile_editor.h" - -QT_BEGIN_NAMESPACE -namespace Ui { - class EditNaive; -} -QT_END_NAMESPACE - -class EditNaive : public QWidget, public ProfileEditor { - Q_OBJECT - -public: - explicit EditNaive(QWidget *parent = nullptr); - - ~EditNaive() override; - - void onStart(std::shared_ptr _ent) override; - - bool onEnd() override; - - QList> get_editor_cached() override; - -private: - Ui::EditNaive *ui; - std::shared_ptr ent; - - struct { - QString certificate; - QString extra_headers; - } CACHE; - -private slots: - - void on_certificate_clicked(); - - void on_extra_headers_clicked(); -}; diff --git a/ui/edit/edit_naive.ui b/ui/edit/edit_naive.ui deleted file mode 100644 index 9063699..0000000 --- a/ui/edit/edit_naive.ui +++ /dev/null @@ -1,131 +0,0 @@ - - - EditNaive - - - - 0 - 0 - 525 - 304 - - - - EditNaive - - - - - - Username - - - - - - - - - - Password - - - - - - - - - - Protocol - - - - - - - - https - - - - - quic - - - - - - - - Extra headers - - - - - - - PushButton - - - - - - - SNI - - - - - - - - - - Certificate - - - - - - - PushButton - - - - - - - Insecure concurrency - - - - - - - - - - Disable logs - - - - - - - Turn on this option if your connection is lost after a while - - - - - - - - MyLineEdit - QLineEdit -
ui/widget/MyLineEdit.h
-
-
- - -
diff --git a/ui/edit/edit_quic.cpp b/ui/edit/edit_quic.cpp deleted file mode 100644 index aa869ea..0000000 --- a/ui/edit/edit_quic.cpp +++ /dev/null @@ -1,135 +0,0 @@ -#include "edit_quic.h" -#include "ui_edit_quic.h" - -#include "fmt/QUICBean.hpp" - -#include -#include - -EditQUIC::EditQUIC(QWidget *parent) : QWidget(parent), ui(new Ui::EditQUIC) { - ui->setupUi(this); - connect(ui->uuidgen, &QPushButton::clicked, this, [=] { ui->uuid->setText(QUuid::createUuid().toString().remove("{").remove("}")); }); -} - -EditQUIC::~EditQUIC() { - delete ui; -} - -void EditQUIC::onStart(std::shared_ptr _ent) { - this->ent = _ent; - auto bean = this->ent->QUICBean(); - - P_LOAD_STRING(hopPort); - P_LOAD_INT(hopInterval); - P_LOAD_INT(uploadMbps); - P_LOAD_INT(downloadMbps); - P_LOAD_BOOL(disableMtuDiscovery) - P_LOAD_STRING(obfsPassword); - P_LOAD_INT(streamReceiveWindow); - P_LOAD_INT(connectionReceiveWindow); - - P_LOAD_BOOL(forceExternal); - P_LOAD_STRING(uuid); - P_LOAD_STRING(password); - - P_LOAD_COMBO_STRING(congestionControl); - P_LOAD_COMBO_STRING(udpRelayMode); - P_LOAD_BOOL(zeroRttHandshake); - P_LOAD_STRING(heartbeat); - P_LOAD_BOOL(uos); - - // TLS - P_LOAD_STRING(sni); - P_LOAD_STRING(alpn); - P_C_LOAD_STRING(caText); - P_LOAD_BOOL(allowInsecure); - P_LOAD_BOOL(disableSni); - - if (bean->proxy_type == NekoGui_fmt::QUICBean::proxy_Hysteria2) { - ui->uuid->hide(); - ui->uuid_l->hide(); - ui->uuidgen->hide(); - ui->congestionControl->hide(); - ui->congestionControl_l->hide(); - ui->udpRelayMode->hide(); - ui->udpRelayMode_l->hide(); - ui->zeroRttHandshake->hide(); - ui->heartbeat->hide(); - ui->heartbeat_l->hide(); - ui->uos->hide(); - - ui->alpn->hide(); - ui->alpn_l->hide(); - ui->TLS->removeItem(ui->alpn_sp); - ui->disableMtuDiscovery->hide(); - ui->connectionReceiveWindow->hide(); - ui->connectionReceiveWindow_l->hide(); - ui->streamReceiveWindow->hide(); - ui->streamReceiveWindow_l->hide(); - } else if (bean->proxy_type == NekoGui_fmt::QUICBean::proxy_TUIC) { - ui->hopPort->hide(); - ui->hopPort_l->hide(); - ui->hopInterval->hide(); - ui->hopInterval_l->hide(); - ui->uploadMbps->hide(); - ui->uploadMbps_l->hide(); - ui->downloadMbps->hide(); - ui->downloadMbps_l->hide(); - ui->disableMtuDiscovery->hide(); - ui->obfsPassword->hide(); - ui->obfsPassword_l->hide(); - ui->streamReceiveWindow->hide(); - ui->streamReceiveWindow_l->hide(); - ui->connectionReceiveWindow->hide(); - ui->connectionReceiveWindow_l->hide(); - ui->uos->hide(); - } -} - -bool EditQUIC::onEnd() { - auto bean = this->ent->QUICBean(); - - P_SAVE_BOOL(forceExternal); - - // Hysteria 2 - P_SAVE_STRING(hopPort); - P_SAVE_INT(hopInterval); - P_SAVE_INT(uploadMbps); - P_SAVE_INT(downloadMbps); - P_SAVE_BOOL(disableMtuDiscovery) - P_SAVE_STRING(obfsPassword); - P_SAVE_INT(streamReceiveWindow); - P_SAVE_INT(connectionReceiveWindow); - - // TUIC - P_SAVE_STRING(uuid); - P_SAVE_STRING(password); - P_SAVE_COMBO_STRING(congestionControl); - P_SAVE_COMBO_STRING(udpRelayMode); - P_SAVE_BOOL(zeroRttHandshake); - P_SAVE_STRING(heartbeat); - P_SAVE_BOOL(uos); - - // TLS - P_SAVE_STRING(sni); - P_SAVE_STRING(alpn); - P_SAVE_BOOL(allowInsecure); - P_C_SAVE_STRING(caText); - P_SAVE_BOOL(disableSni); - return true; -} - -QList> EditQUIC::get_editor_cached() { - return { - {ui->certificate, CACHE.caText}, - }; -} - -void EditQUIC::on_certificate_clicked() { - bool ok; - auto txt = QInputDialog::getMultiLineText(this, tr("Certificate"), "", CACHE.caText, &ok); - if (ok) { - CACHE.caText = txt; - editor_cache_updated(); - } -} diff --git a/ui/edit/edit_quic.h b/ui/edit/edit_quic.h deleted file mode 100644 index 43996f9..0000000 --- a/ui/edit/edit_quic.h +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include -#include -#include -#include "profile_editor.h" - -QT_BEGIN_NAMESPACE -namespace Ui { - class EditQUIC; -} -QT_END_NAMESPACE - -class EditQUIC : public QWidget, public ProfileEditor { - Q_OBJECT - -public: - explicit EditQUIC(QWidget *parent = nullptr); - - ~EditQUIC() override; - - void onStart(std::shared_ptr _ent) override; - - bool onEnd() override; - - QList> get_editor_cached() override; - -private: - Ui::EditQUIC *ui; - std::shared_ptr ent; - - struct { - QString caText; - } CACHE; - -private slots: - - void on_certificate_clicked(); -}; diff --git a/ui/edit/edit_quic.ui b/ui/edit/edit_quic.ui deleted file mode 100644 index 3416d89..0000000 --- a/ui/edit/edit_quic.ui +++ /dev/null @@ -1,372 +0,0 @@ - - - EditQUIC - - - - 0 - 0 - 500 - 628 - - - - EditHysteria - - - - - - - - - - Download (Mbps) - - - - - - - - - - - - - - Hop Port - - - - - - - - - - - - - - Hop Interval (s) - - - - - - - - - - - - - - Heartbeat - - - - - - - - 0 - 0 - - - - - - - - - - - - Upload (Mbps) - - - - - - - - - - - - Zero Rtt Handshake - - - - - - - - - Congestion Control - - - - - - - - bbr - - - - - cubic - - - - - new_reno - - - - - - - - - - - - UDP Relay Mode - - - - - - - - native - - - - - quic - - - - - - - - - - - - - - Force use external core - - - - - - - Requires sing-box server - - - UDP over Stream - - - - - - - - 0 - 0 - - - - Disable MTU Discovery - - - - - - - - - - - - - - Obfs Password - - - - - - - - - - - Generate UUID - - - - - - - UUID - - - - - - - - - - - 0 - 0 - - - - Password - - - - - - - - - - - - - - Certificate - - - - - - - PushButton - - - - - - - - - - Disable SNI - - - - - - - - - - ALPN - - - - - - - SNI - - - - - - - Allow Insecure - - - - - - - Qt::Horizontal - - - QSizePolicy::Maximum - - - - 40 - 20 - - - - - - - - - - - - recv_window - - - - - - - - - - recv_window_conn - - - - - - - - - - - - - MyLineEdit - QLineEdit -
ui/widget/MyLineEdit.h
-
-
- - hopPort - hopInterval - uploadMbps - downloadMbps - congestionControl - udpRelayMode - heartbeat - zeroRttHandshake - forceExternal - uos - disableMtuDiscovery - obfsPassword - uuid - uuidgen - password - sni - disableSni - alpn - certificate - allowInsecure - streamReceiveWindow - connectionReceiveWindow - - - -
diff --git a/ui/edit/edit_shadowsocks.cpp b/ui/edit/edit_shadowsocks.cpp deleted file mode 100644 index e016e34..0000000 --- a/ui/edit/edit_shadowsocks.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include "edit_shadowsocks.h" -#include "ui_edit_shadowsocks.h" - -#include "fmt/ShadowSocksBean.hpp" -#include "fmt/Preset.hpp" - -EditShadowSocks::EditShadowSocks(QWidget *parent) : QWidget(parent), - ui(new Ui::EditShadowSocks) { - ui->setupUi(this); - ui->method->addItems(Preset::SingBox::ShadowsocksMethods); -} - -EditShadowSocks::~EditShadowSocks() { - delete ui; -} - -void EditShadowSocks::onStart(std::shared_ptr _ent) { - this->ent = _ent; - auto bean = this->ent->ShadowSocksBean(); - - ui->method->setCurrentText(bean->method); - ui->uot->setCurrentIndex(bean->uot); - ui->password->setText(bean->password); - auto ssPlugin = bean->plugin.split(";"); - if (!ssPlugin.empty()) { - ui->plugin->setCurrentText(ssPlugin[0]); - ui->plugin_opts->setText(SubStrAfter(bean->plugin, ";")); - } -} - -bool EditShadowSocks::onEnd() { - auto bean = this->ent->ShadowSocksBean(); - - bean->method = ui->method->currentText(); - bean->password = ui->password->text(); - bean->uot = ui->uot->currentIndex(); - bean->plugin = ui->plugin->currentText(); - if (!bean->plugin.isEmpty()) { - bean->plugin += ";" + ui->plugin_opts->text(); - } - - return true; -} diff --git a/ui/edit/edit_shadowsocks.h b/ui/edit/edit_shadowsocks.h deleted file mode 100644 index d1131b9..0000000 --- a/ui/edit/edit_shadowsocks.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef EDIT_SHADOWSOCKS_H -#define EDIT_SHADOWSOCKS_H - -#include -#include "profile_editor.h" - -namespace Ui { - class EditShadowSocks; -} - -class EditShadowSocks : public QWidget, public ProfileEditor { - Q_OBJECT - -public: - explicit EditShadowSocks(QWidget *parent = nullptr); - - ~EditShadowSocks() override; - - void onStart(std::shared_ptr _ent) override; - - bool onEnd() override; - -private: - Ui::EditShadowSocks *ui; - std::shared_ptr ent; -}; - -#endif // EDIT_SHADOWSOCKS_H diff --git a/ui/edit/edit_shadowsocks.ui b/ui/edit/edit_shadowsocks.ui deleted file mode 100644 index 2916b6e..0000000 --- a/ui/edit/edit_shadowsocks.ui +++ /dev/null @@ -1,126 +0,0 @@ - - - EditShadowSocks - - - - 0 - 0 - 400 - 300 - - - - Form - - - - - - true - - - - - - - - - - Plugin - - - - - - - Encryption - - - - - - - Plugin Args - - - - - - - - - - Password - - - - - - - - - - - - - obfs-local - - - - - v2ray-plugin - - - - - - - - Version of UDP over TCP protocol, server support is required. - - - - - - UoT - - - - - - - - Off - - - - - 1 - - - - - 2 - - - - - - - - - MyLineEdit - QLineEdit -
ui/widget/MyLineEdit.h
-
-
- - method - password - plugin - plugin_opts - - - -
diff --git a/ui/edit/edit_socks_http.cpp b/ui/edit/edit_socks_http.cpp deleted file mode 100644 index 1598c6e..0000000 --- a/ui/edit/edit_socks_http.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "edit_socks_http.h" -#include "ui_edit_socks_http.h" - -#include "fmt/SocksHttpBean.hpp" - -EditSocksHttp::EditSocksHttp(QWidget *parent) : QWidget(parent), - ui(new Ui::EditSocksHttp) { - ui->setupUi(this); -} - -EditSocksHttp::~EditSocksHttp() { - delete ui; -} - -void EditSocksHttp::onStart(std::shared_ptr _ent) { - this->ent = _ent; - auto bean = this->ent->SocksHTTPBean(); - - if (bean->socks_http_type == NekoGui_fmt::SocksHttpBean::type_Socks4) { - ui->version->setCurrentIndex(1); - } else { - ui->version->setCurrentIndex(0); - } - if (bean->socks_http_type == NekoGui_fmt::SocksHttpBean::type_HTTP) { - ui->version->setVisible(false); - ui->version_l->setVisible(false); - } - - ui->username->setText(bean->username); - ui->password->setText(bean->password); -} - -bool EditSocksHttp::onEnd() { - auto bean = this->ent->SocksHTTPBean(); - - if (ui->version->isVisible()) { - if (ui->version->currentIndex() == 1) { - bean->socks_http_type = NekoGui_fmt::SocksHttpBean::type_Socks4; - } else { - bean->socks_http_type = NekoGui_fmt::SocksHttpBean::type_Socks5; - } - } - - bean->username = ui->username->text(); - bean->password = ui->password->text(); - - return true; -} diff --git a/ui/edit/edit_socks_http.h b/ui/edit/edit_socks_http.h deleted file mode 100644 index ccc3801..0000000 --- a/ui/edit/edit_socks_http.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include -#include "profile_editor.h" - -namespace Ui { - class EditSocksHttp; -} - -class EditSocksHttp : public QWidget, public ProfileEditor { - Q_OBJECT - -public: - explicit EditSocksHttp(QWidget *parent = nullptr); - - ~EditSocksHttp() override; - - void onStart(std::shared_ptr _ent) override; - - bool onEnd() override; - -private: - Ui::EditSocksHttp *ui; - std::shared_ptr ent; -}; diff --git a/ui/edit/edit_socks_http.ui b/ui/edit/edit_socks_http.ui deleted file mode 100644 index c179709..0000000 --- a/ui/edit/edit_socks_http.ui +++ /dev/null @@ -1,67 +0,0 @@ - - - EditSocksHttp - - - - 0 - 0 - 400 - 300 - - - - Form - - - - - - Version - - - - - - - - - - - - - Username - - - - - - - - 5 - - - - - 4 - - - - - - - - Password - - - - - - - version - username - password - - - - diff --git a/ui/edit/edit_trojan_vless.cpp b/ui/edit/edit_trojan_vless.cpp deleted file mode 100644 index 4d29883..0000000 --- a/ui/edit/edit_trojan_vless.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include "edit_trojan_vless.h" -#include "ui_edit_trojan_vless.h" - -#include "fmt/TrojanVLESSBean.hpp" -#include "fmt/Preset.hpp" - -EditTrojanVLESS::EditTrojanVLESS(QWidget *parent) : QWidget(parent), ui(new Ui::EditTrojanVLESS) { - ui->setupUi(this); -} - -EditTrojanVLESS::~EditTrojanVLESS() { - delete ui; -} - -void EditTrojanVLESS::onStart(std::shared_ptr _ent) { - this->ent = _ent; - auto bean = this->ent->TrojanVLESSBean(); - if (bean->proxy_type == NekoGui_fmt::TrojanVLESSBean::proxy_VLESS) { - ui->label->setText("UUID"); - } - if (bean->proxy_type != NekoGui_fmt::TrojanVLESSBean::proxy_VLESS) { - ui->flow->hide(); - ui->flow_l->hide(); - } - ui->password->setText(bean->password); - ui->flow->addItems(Preset::SingBox::Flows); - ui->flow->setCurrentText(bean->flow); -} - -bool EditTrojanVLESS::onEnd() { - auto bean = this->ent->TrojanVLESSBean(); - bean->password = ui->password->text(); - bean->flow = ui->flow->currentText(); - return true; -} diff --git a/ui/edit/edit_trojan_vless.h b/ui/edit/edit_trojan_vless.h deleted file mode 100644 index d19b283..0000000 --- a/ui/edit/edit_trojan_vless.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include -#include "profile_editor.h" - -QT_BEGIN_NAMESPACE -namespace Ui { - class EditTrojanVLESS; -} -QT_END_NAMESPACE - -class EditTrojanVLESS : public QWidget, public ProfileEditor { - Q_OBJECT - -public: - explicit EditTrojanVLESS(QWidget *parent = nullptr); - - ~EditTrojanVLESS() override; - - void onStart(std::shared_ptr _ent) override; - - bool onEnd() override; - -private: - Ui::EditTrojanVLESS *ui; - std::shared_ptr ent; -}; diff --git a/ui/edit/edit_trojan_vless.ui b/ui/edit/edit_trojan_vless.ui deleted file mode 100644 index ae622b5..0000000 --- a/ui/edit/edit_trojan_vless.ui +++ /dev/null @@ -1,54 +0,0 @@ - - - EditTrojanVLESS - - - - 0 - 0 - 400 - 300 - - - - - - - - - - - - - Password - - - - - - - Flow - - - - - - - - - - - - - - - - - MyLineEdit - QLineEdit -
ui/widget/MyLineEdit.h
-
-
- - -
diff --git a/ui/edit/edit_vmess.cpp b/ui/edit/edit_vmess.cpp deleted file mode 100644 index 0fb05a7..0000000 --- a/ui/edit/edit_vmess.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include "edit_vmess.h" -#include "ui_edit_vmess.h" - -#include "fmt/VMessBean.hpp" - -#include - -EditVMess::EditVMess(QWidget *parent) : QWidget(parent), ui(new Ui::EditVMess) { - ui->setupUi(this); - connect(ui->uuidgen, &QPushButton::clicked, this, [=] { ui->uuid->setText(QUuid::createUuid().toString().remove("{").remove("}")); }); -} - -EditVMess::~EditVMess() { - delete ui; -} - -void EditVMess::onStart(std::shared_ptr _ent) { - this->ent = _ent; - auto bean = this->ent->VMessBean(); - - ui->uuid->setText(bean->uuid); - ui->aid->setText(Int2String(bean->aid)); - ui->security->setCurrentText(bean->security); -} - -bool EditVMess::onEnd() { - auto bean = this->ent->VMessBean(); - - bean->uuid = ui->uuid->text(); - bean->aid = ui->aid->text().toInt(); - bean->security = ui->security->currentText(); - - return true; -} diff --git a/ui/edit/edit_vmess.h b/ui/edit/edit_vmess.h deleted file mode 100644 index 38efa6c..0000000 --- a/ui/edit/edit_vmess.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include -#include "profile_editor.h" - -QT_BEGIN_NAMESPACE -namespace Ui { - class EditVMess; -} -QT_END_NAMESPACE - -class EditVMess : public QWidget, public ProfileEditor { - Q_OBJECT - -public: - explicit EditVMess(QWidget *parent = nullptr); - - ~EditVMess() override; - - void onStart(std::shared_ptr _ent) override; - - bool onEnd() override; - -private: - Ui::EditVMess *ui; - std::shared_ptr ent; -}; diff --git a/ui/edit/edit_vmess.ui b/ui/edit/edit_vmess.ui deleted file mode 100644 index b29dbee..0000000 --- a/ui/edit/edit_vmess.ui +++ /dev/null @@ -1,124 +0,0 @@ - - - EditVMess - - - - 0 - 0 - 400 - 300 - - - - EditVMess - - - - - - true - - - - auto - - - - - zero - - - - - none - - - - - chacha20-poly1305 - - - - - aes-128-gcm - - - - - - - - Security - - - - - - - Alter Id - - - - - - - UUID - - - - - - - - - - - 0 - 0 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - Generate UUID - - - - - - - - - - - MyLineEdit - QLineEdit -
ui/widget/MyLineEdit.h
-
-
- - uuid - aid - uuidgen - security - - - -
diff --git a/ui/edit/profile_editor.h b/ui/edit/profile_editor.h deleted file mode 100644 index cf43847..0000000 --- a/ui/edit/profile_editor.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include - -#include "db/ProxyEntity.hpp" -#include "main/GuiUtils.hpp" - -class ProfileEditor { -public: - virtual void onStart(std::shared_ptr ent) = 0; - - virtual bool onEnd() = 0; - - std::function get_edit_dialog; - std::function get_edit_text_name; - std::function get_edit_text_serverAddress; - std::function get_edit_text_serverPort; - - // cached editor - - std::function editor_cache_updated; - - virtual QList> get_editor_cached() { return {}; }; -}; diff --git a/ui/mainwindow.cpp b/ui/mainwindow.cpp deleted file mode 100644 index 9155f61..0000000 --- a/ui/mainwindow.cpp +++ /dev/null @@ -1,1844 +0,0 @@ -#include "./ui_mainwindow.h" -#include "mainwindow.h" - -#include "fmt/Preset.hpp" -#include "db/ProfileFilter.hpp" -#include "db/ConfigBuilder.hpp" -#include "sub/GroupUpdater.hpp" -#include "sys/ExternalProcess.hpp" -#include "sys/AutoRun.hpp" - -#include "ui/ThemeManager.hpp" -#include "ui/Icon.hpp" -#include "ui/edit/dialog_edit_profile.h" -#include "ui/dialog_basic_settings.h" -#include "ui/dialog_manage_groups.h" -#include "ui/dialog_manage_routes.h" -#include "ui/dialog_vpn_settings.h" -#include "ui/dialog_hotkey.h" - -#include "3rdparty/fix_old_qt.h" -#include "3rdparty/qrcodegen.hpp" -#include "3rdparty/VT100Parser.hpp" -#include "3rdparty/qv2ray/v2/components/proxy/QvProxyConfigurator.hpp" - -#ifndef NKR_NO_ZXING -#include "3rdparty/ZxingQtReader.hpp" -#endif - -#ifdef Q_OS_WIN -#include "3rdparty/WinCommander.hpp" -#else -#ifdef Q_OS_LINUX -#include "sys/linux/LinuxCap.h" -#endif -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -void UI_InitMainWindow() { - mainwindow = new MainWindow; -} - -MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { - mainwindow = this; - MW_dialog_message = [=](const QString &a, const QString &b) { - runOnUiThread([=] { dialog_message_impl(a, b); }); - }; - - // Load Manager - NekoGui::profileManager->LoadManager(); - - // Setup misc UI - themeManager->ApplyTheme(NekoGui::dataStore->theme); - ui->setupUi(this); - // - connect(ui->menu_start, &QAction::triggered, this, [=]() { neko_start(); }); - connect(ui->menu_stop, &QAction::triggered, this, [=]() { neko_stop(); }); - connect(ui->tabWidget->tabBar(), &QTabBar::tabMoved, this, [=](int from, int to) { - // use tabData to track tab & gid - NekoGui::profileManager->groupsTabOrder.clear(); - for (int i = 0; i < ui->tabWidget->tabBar()->count(); i++) { - NekoGui::profileManager->groupsTabOrder += ui->tabWidget->tabBar()->tabData(i).toInt(); - } - NekoGui::profileManager->SaveManager(); - }); - ui->label_running->installEventFilter(this); - ui->label_inbound->installEventFilter(this); - ui->splitter->installEventFilter(this); - // - RegisterHotkey(false); - // - auto last_size = NekoGui::dataStore->mw_size.split("x"); - if (last_size.length() == 2) { - auto w = last_size[0].toInt(); - auto h = last_size[1].toInt(); - if (w > 0 && h > 0) { - resize(w, h); - } - } - - if (QDir("dashboard").count() == 0) { - QDir().mkdir("dashboard"); - QFile::copy(":/neko/dashboard-notice.html", "dashboard/index.html"); - } - - // top bar - ui->toolButton_program->setMenu(ui->menu_program); - ui->toolButton_preferences->setMenu(ui->menu_preferences); - ui->toolButton_server->setMenu(ui->menu_server); - ui->menubar->setVisible(false); - connect(ui->toolButton_document, &QToolButton::clicked, this, [=] { QDesktopServices::openUrl(QUrl("https://matsuridayo.github.io/")); }); - connect(ui->toolButton_ads, &QToolButton::clicked, this, [=] { QDesktopServices::openUrl(QUrl("https://neko-box.pages.dev/喵")); }); - connect(ui->toolButton_update, &QToolButton::clicked, this, [=] { runOnNewThread([=] { CheckUpdate(); }); }); - connect(ui->toolButton_url_test, &QToolButton::clicked, this, [=] { speedtest_current_group(1, true); }); - - // Setup log UI - ui->splitter->restoreState(DecodeB64IfValid(NekoGui::dataStore->splitter_state)); - qvLogDocument->setUndoRedoEnabled(false); - ui->masterLogBrowser->setUndoRedoEnabled(false); - ui->masterLogBrowser->setDocument(qvLogDocument); - ui->masterLogBrowser->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); - { - auto font = ui->masterLogBrowser->font(); - font.setPointSize(9); - ui->masterLogBrowser->setFont(font); - qvLogDocument->setDefaultFont(font); - } - connect(ui->masterLogBrowser->verticalScrollBar(), &QSlider::valueChanged, this, [=](int value) { - if (ui->masterLogBrowser->verticalScrollBar()->maximum() == value) - qvLogAutoScoll = true; - else - qvLogAutoScoll = false; - }); - connect(ui->masterLogBrowser, &QTextBrowser::textChanged, this, [=]() { - if (!qvLogAutoScoll) - return; - auto bar = ui->masterLogBrowser->verticalScrollBar(); - bar->setValue(bar->maximum()); - }); - MW_show_log = [=](const QString &log) { - runOnUiThread([=] { show_log_impl(log); }); - }; - MW_show_log_ext = [=](const QString &tag, const QString &log) { - runOnUiThread([=] { show_log_impl("[" + tag + "] " + log); }); - }; - MW_show_log_ext_vt100 = [=](const QString &log) { - runOnUiThread([=] { show_log_impl(cleanVT100String(log)); }); - }; - - // table UI - ui->proxyListTable->callback_save_order = [=] { - auto group = NekoGui::profileManager->CurrentGroup(); - group->order = ui->proxyListTable->order; - group->Save(); - }; - ui->proxyListTable->refresh_data = [=](int id) { refresh_proxy_list_impl_refresh_data(id); }; - if (auto button = ui->proxyListTable->findChild(QString(), Qt::FindDirectChildrenOnly)) { - // Corner Button - connect(button, &QAbstractButton::clicked, this, [=] { refresh_proxy_list_impl(-1, {GroupSortMethod::ById}); }); - } - connect(ui->proxyListTable->horizontalHeader(), &QHeaderView::sectionClicked, this, [=](int logicalIndex) { - GroupSortAction action; - // 不正确的descending实现 - if (proxy_last_order == logicalIndex) { - action.descending = true; - proxy_last_order = -1; - } else { - proxy_last_order = logicalIndex; - } - action.save_sort = true; - // 表头 - if (logicalIndex == 0) { - action.method = GroupSortMethod::ByType; - } else if (logicalIndex == 1) { - action.method = GroupSortMethod::ByAddress; - } else if (logicalIndex == 2) { - action.method = GroupSortMethod::ByName; - } else if (logicalIndex == 3) { - action.method = GroupSortMethod::ByLatency; - } else { - return; - } - refresh_proxy_list_impl(-1, action); - }); - connect(ui->proxyListTable->horizontalHeader(), &QHeaderView::sectionResized, this, [=](int logicalIndex, int oldSize, int newSize) { - auto group = NekoGui::profileManager->CurrentGroup(); - if (NekoGui::dataStore->refreshing_group || group == nullptr || !group->manually_column_width) return; - // save manually column width - group->column_width.clear(); - for (int i = 0; i < ui->proxyListTable->horizontalHeader()->count(); i++) { - group->column_width.push_back(ui->proxyListTable->horizontalHeader()->sectionSize(i)); - } - group->column_width[logicalIndex] = newSize; - group->Save(); - }); - ui->tableWidget_conn->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents); - ui->tableWidget_conn->horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeToContents); - ui->tableWidget_conn->horizontalHeader()->setSectionResizeMode(2, QHeaderView::Stretch); - ui->proxyListTable->verticalHeader()->setDefaultSectionSize(24); - - // search box - ui->search->setVisible(false); - connect(shortcut_ctrl_f, &QShortcut::activated, this, [=] { - ui->search->setVisible(true); - ui->search->setFocus(); - }); - connect(shortcut_esc, &QShortcut::activated, this, [=] { - if (ui->search->isVisible()) { - ui->search->setText(""); - ui->search->textChanged(""); - ui->search->setVisible(false); - } - if (select_mode) { - emit profile_selected(-1); - select_mode = false; - refresh_status(); - } - }); - connect(ui->search, &QLineEdit::textChanged, this, [=](const QString &text) { - if (text.isEmpty()) { - for (int i = 0; i < ui->proxyListTable->rowCount(); i++) { - ui->proxyListTable->setRowHidden(i, false); - } - } else { - QList findItem = ui->proxyListTable->findItems(text, Qt::MatchContains); - for (int i = 0; i < ui->proxyListTable->rowCount(); i++) { - ui->proxyListTable->setRowHidden(i, true); - } - for (auto item: findItem) { - if (item != nullptr) ui->proxyListTable->setRowHidden(item->row(), false); - } - } - }); - - // refresh - this->refresh_groups(); - - // Setup Tray - tray = new QSystemTrayIcon(this); // 初始化托盘对象tray - tray->setIcon(Icon::GetTrayIcon(Icon::NONE)); - tray->setContextMenu(ui->menu_program); // 创建托盘菜单 - tray->show(); // 让托盘图标显示在系统托盘上 - connect(tray, &QSystemTrayIcon::activated, this, [=](QSystemTrayIcon::ActivationReason reason) { - if (reason == QSystemTrayIcon::Trigger) { - if (this->isVisible()) { - hide(); - } else { - ActivateWindow(this); - } - } - }); - - // Misc menu - connect(ui->menu_open_config_folder, &QAction::triggered, this, [=] { QDesktopServices::openUrl(QUrl::fromLocalFile(QDir::currentPath())); }); - ui->menu_program_preference->addActions(ui->menu_preferences->actions()); - connect(ui->menu_add_from_clipboard2, &QAction::triggered, ui->menu_add_from_clipboard, &QAction::trigger); - connect(ui->actionRestart_Proxy, &QAction::triggered, this, [=] { if (NekoGui::dataStore->started_id>=0) neko_start(NekoGui::dataStore->started_id); }); - connect(ui->actionRestart_Program, &QAction::triggered, this, [=] { MW_dialog_message("", "RestartProgram"); }); - connect(ui->actionShow_window, &QAction::triggered, this, [=] { tray->activated(QSystemTrayIcon::ActivationReason::Trigger); }); - // - connect(ui->menu_program, &QMenu::aboutToShow, this, [=]() { - ui->actionRemember_last_proxy->setChecked(NekoGui::dataStore->remember_enable); - ui->actionStart_with_system->setChecked(AutoRun_IsEnabled()); - ui->actionAllow_LAN->setChecked(QStringList{"::", "0.0.0.0"}.contains(NekoGui::dataStore->inbound_address)); - // active server - for (const auto &old: ui->menuActive_Server->actions()) { - ui->menuActive_Server->removeAction(old); - old->deleteLater(); - } - int active_server_item_count = 0; - for (const auto &pf: NekoGui::profileManager->CurrentGroup()->ProfilesWithOrder()) { - auto a = new QAction(pf->bean->DisplayTypeAndName(), this); - a->setProperty("id", pf->id); - a->setCheckable(true); - if (NekoGui::dataStore->started_id == pf->id) a->setChecked(true); - ui->menuActive_Server->addAction(a); - if (++active_server_item_count == 100) break; - } - // active routing - for (const auto &old: ui->menuActive_Routing->actions()) { - ui->menuActive_Routing->removeAction(old); - old->deleteLater(); - } - for (const auto &name: NekoGui::Routing::List()) { - auto a = new QAction(name, this); - a->setCheckable(true); - a->setChecked(name == NekoGui::dataStore->active_routing); - ui->menuActive_Routing->addAction(a); - } - }); - connect(ui->menuActive_Server, &QMenu::triggered, this, [=](QAction *a) { - bool ok; - auto id = a->property("id").toInt(&ok); - if (!ok) return; - if (NekoGui::dataStore->started_id == id) { - neko_stop(); - } else { - neko_start(id); - } - }); - connect(ui->menuActive_Routing, &QMenu::triggered, this, [=](QAction *a) { - auto fn = a->text(); - if (!fn.isEmpty()) { - NekoGui::Routing r; - r.load_control_must = true; - r.fn = ROUTES_PREFIX + fn; - if (r.Load()) { - if (QMessageBox::question(GetMessageBoxParent(), software_name, tr("Load routing and apply: %1").arg(fn) + "\n" + r.DisplayRouting()) == QMessageBox::Yes) { - NekoGui::Routing::SetToActive(fn); - if (NekoGui::dataStore->started_id >= 0) { - neko_start(NekoGui::dataStore->started_id); - } else { - refresh_status(); - } - } - } - } - }); - connect(ui->actionRemember_last_proxy, &QAction::triggered, this, [=](bool checked) { - NekoGui::dataStore->remember_enable = checked; - NekoGui::dataStore->Save(); - }); - connect(ui->actionStart_with_system, &QAction::triggered, this, [=](bool checked) { - AutoRun_SetEnabled(checked); - }); - connect(ui->actionAllow_LAN, &QAction::triggered, this, [=](bool checked) { - NekoGui::dataStore->inbound_address = checked ? "::" : "127.0.0.1"; - MW_dialog_message("", "UpdateDataStore"); - }); - // - connect(ui->checkBox_VPN, &QCheckBox::clicked, this, [=](bool checked) { neko_set_spmode_vpn(checked); }); - connect(ui->checkBox_SystemProxy, &QCheckBox::clicked, this, [=](bool checked) { neko_set_spmode_system_proxy(checked); }); - connect(ui->menu_spmode, &QMenu::aboutToShow, this, [=]() { - ui->menu_spmode_disabled->setChecked(!(NekoGui::dataStore->spmode_system_proxy || NekoGui::dataStore->spmode_vpn)); - ui->menu_spmode_system_proxy->setChecked(NekoGui::dataStore->spmode_system_proxy); - ui->menu_spmode_vpn->setChecked(NekoGui::dataStore->spmode_vpn); - }); - connect(ui->menu_spmode_system_proxy, &QAction::triggered, this, [=](bool checked) { neko_set_spmode_system_proxy(checked); }); - connect(ui->menu_spmode_vpn, &QAction::triggered, this, [=](bool checked) { neko_set_spmode_vpn(checked); }); - connect(ui->menu_spmode_disabled, &QAction::triggered, this, [=]() { - neko_set_spmode_system_proxy(false); - neko_set_spmode_vpn(false); - }); - connect(ui->menu_qr, &QAction::triggered, this, [=]() { display_qr_link(false); }); - connect(ui->menu_tcp_ping, &QAction::triggered, this, [=]() { speedtest_current_group(0, false); }); - connect(ui->menu_url_test, &QAction::triggered, this, [=]() { speedtest_current_group(1, false); }); - connect(ui->menu_full_test, &QAction::triggered, this, [=]() { speedtest_current_group(2, false); }); - connect(ui->menu_stop_testing, &QAction::triggered, this, [=]() { speedtest_current_group(114514, false); }); - // - auto set_selected_or_group = [=](int mode) { - // 0=group 1=select 2=unknown(menu is hide) - ui->menu_server->setProperty("selected_or_group", mode); - }; - auto move_tests_to_menu = [=](bool menuCurrent_Select) { - return [=] { - if (menuCurrent_Select) { - ui->menuCurrent_Select->insertAction(ui->actionfake_4, ui->menu_tcp_ping); - ui->menuCurrent_Select->insertAction(ui->actionfake_4, ui->menu_url_test); - ui->menuCurrent_Select->insertAction(ui->actionfake_4, ui->menu_full_test); - ui->menuCurrent_Select->insertAction(ui->actionfake_4, ui->menu_stop_testing); - ui->menuCurrent_Select->insertAction(ui->actionfake_4, ui->menu_clear_test_result); - ui->menuCurrent_Select->insertAction(ui->actionfake_4, ui->menu_resolve_domain); - } else { - ui->menuCurrent_Group->insertAction(ui->actionfake_5, ui->menu_tcp_ping); - ui->menuCurrent_Group->insertAction(ui->actionfake_5, ui->menu_url_test); - ui->menuCurrent_Group->insertAction(ui->actionfake_5, ui->menu_full_test); - ui->menuCurrent_Group->insertAction(ui->actionfake_5, ui->menu_stop_testing); - ui->menuCurrent_Group->insertAction(ui->actionfake_5, ui->menu_clear_test_result); - ui->menuCurrent_Group->insertAction(ui->actionfake_5, ui->menu_resolve_domain); - } - set_selected_or_group(menuCurrent_Select ? 1 : 0); - }; - }; - connect(ui->menuCurrent_Select, &QMenu::aboutToShow, this, move_tests_to_menu(true)); - connect(ui->menuCurrent_Group, &QMenu::aboutToShow, this, move_tests_to_menu(false)); - connect(ui->menu_server, &QMenu::aboutToHide, this, [=] { - setTimeout([=] { set_selected_or_group(2); }, this, 200); - }); - set_selected_or_group(2); - // - connect(ui->menu_share_item, &QMenu::aboutToShow, this, [=] { - QString name; - auto selected = get_now_selected_list(); - if (!selected.isEmpty()) { - auto ent = selected.first(); - name = ent->bean->DisplayCoreType(); - } - ui->menu_export_config->setVisible(name == software_core_name); - ui->menu_export_config->setText(tr("Export %1 config").arg(name)); - }); - refresh_status(); - - // Prepare core - NekoGui::dataStore->core_token = GetRandomString(32); - NekoGui::dataStore->core_port = MkPort(); - if (NekoGui::dataStore->core_port <= 0) NekoGui::dataStore->core_port = 19810; - - auto core_path = QApplication::applicationDirPath() + "/"; - core_path += "nekobox_core"; - - QStringList args; - args.push_back("nekobox"); - args.push_back("-port"); - args.push_back(Int2String(NekoGui::dataStore->core_port)); - if (NekoGui::dataStore->flag_debug) args.push_back("-debug"); - - // Start core - runOnUiThread( - [=] { - core_process = new NekoGui_sys::CoreProcess(core_path, args); - // Remember last started - if (NekoGui::dataStore->remember_enable && NekoGui::dataStore->remember_id >= 0) { - core_process->start_profile_when_core_is_up = NekoGui::dataStore->remember_id; - } - // Setup - core_process->Start(); - setup_grpc(); - }, - DS_cores); - - // Remember system proxy - if (NekoGui::dataStore->remember_enable || NekoGui::dataStore->flag_restart_tun_on) { - if (NekoGui::dataStore->remember_spmode.contains("system_proxy")) { - neko_set_spmode_system_proxy(true, false); - } - if (NekoGui::dataStore->remember_spmode.contains("vpn") || NekoGui::dataStore->flag_restart_tun_on) { - neko_set_spmode_vpn(true, false); - } - } - - connect(qApp, &QGuiApplication::commitDataRequest, this, &MainWindow::on_commitDataRequest); - - auto t = new QTimer; - connect(t, &QTimer::timeout, this, [=]() { refresh_status(); }); - t->start(2000); - - t = new QTimer; - connect(t, &QTimer::timeout, this, [&] { NekoGui_sys::logCounter.fetchAndStoreRelaxed(0); }); - t->start(1000); - - TM_auto_update_subsctiption = new QTimer; - TM_auto_update_subsctiption_Reset_Minute = [&](int m) { - TM_auto_update_subsctiption->stop(); - if (m >= 30) TM_auto_update_subsctiption->start(m * 60 * 1000); - }; - connect(TM_auto_update_subsctiption, &QTimer::timeout, this, [&] { UI_update_all_groups(true); }); - TM_auto_update_subsctiption_Reset_Minute(NekoGui::dataStore->sub_auto_update); - - if (!NekoGui::dataStore->flag_tray) show(); -} - -void MainWindow::closeEvent(QCloseEvent *event) { - if (tray->isVisible()) { - hide(); // 隐藏窗口 - event->ignore(); // 忽略事件 - } -} - -MainWindow::~MainWindow() { - delete ui; -} - -// Group tab manage - -inline int tabIndex2GroupId(int index) { - if (NekoGui::profileManager->groupsTabOrder.length() <= index) return -1; - return NekoGui::profileManager->groupsTabOrder[index]; -} - -inline int groupId2TabIndex(int gid) { - for (int key = 0; key < NekoGui::profileManager->groupsTabOrder.count(); key++) { - if (NekoGui::profileManager->groupsTabOrder[key] == gid) return key; - } - return 0; -} - -void MainWindow::on_tabWidget_currentChanged(int index) { - if (NekoGui::dataStore->refreshing_group_list) return; - if (tabIndex2GroupId(index) == NekoGui::dataStore->current_group) return; - show_group(tabIndex2GroupId(index)); -} - -void MainWindow::show_group(int gid) { - if (NekoGui::dataStore->refreshing_group) return; - NekoGui::dataStore->refreshing_group = true; - - auto group = NekoGui::profileManager->GetGroup(gid); - if (group == nullptr) { - MessageBoxWarning(tr("Error"), QStringLiteral("No such group: %1").arg(gid)); - NekoGui::dataStore->refreshing_group = false; - return; - } - - if (NekoGui::dataStore->current_group != gid) { - NekoGui::dataStore->current_group = gid; - NekoGui::dataStore->Save(); - } - ui->tabWidget->widget(groupId2TabIndex(gid))->layout()->addWidget(ui->proxyListTable); - - // 列宽是否可调 - if (group->manually_column_width) { - for (int i = 0; i <= 4; i++) { - ui->proxyListTable->horizontalHeader()->setSectionResizeMode(i, QHeaderView::Interactive); - auto size = group->column_width.value(i); - if (size <= 0) size = ui->proxyListTable->horizontalHeader()->defaultSectionSize(); - ui->proxyListTable->horizontalHeader()->resizeSection(i, size); - } - } else { - ui->proxyListTable->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents); - ui->proxyListTable->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch); - ui->proxyListTable->horizontalHeader()->setSectionResizeMode(2, QHeaderView::Stretch); - ui->proxyListTable->horizontalHeader()->setSectionResizeMode(3, QHeaderView::ResizeToContents); - ui->proxyListTable->horizontalHeader()->setSectionResizeMode(4, QHeaderView::ResizeToContents); - } - - // show proxies - GroupSortAction gsa; - gsa.scroll_to_started = true; - refresh_proxy_list_impl(-1, gsa); - - NekoGui::dataStore->refreshing_group = false; -} - -// callback - -void MainWindow::dialog_message_impl(const QString &sender, const QString &info) { - // info - if (info.contains("UpdateIcon")) { - icon_status = -1; - refresh_status(); - } - if (info.contains("UpdateDataStore")) { - auto suggestRestartProxy = NekoGui::dataStore->Save(); - if (info.contains("RouteChanged")) { - suggestRestartProxy = true; - } - if (info.contains("NeedRestart")) { - suggestRestartProxy = false; - } - refresh_proxy_list(); - if (info.contains("VPNChanged") && NekoGui::dataStore->spmode_vpn) { - MessageBoxWarning(tr("Tun Settings changed"), tr("Restart Tun to take effect.")); - } - if (suggestRestartProxy && NekoGui::dataStore->started_id >= 0 && - QMessageBox::question(GetMessageBoxParent(), tr("Confirmation"), tr("Settings changed, restart proxy?")) == QMessageBox::StandardButton::Yes) { - neko_start(NekoGui::dataStore->started_id); - } - refresh_status(); - } - if (info.contains("NeedRestart")) { - auto n = QMessageBox::warning(GetMessageBoxParent(), tr("Settings changed"), tr("Restart the program to take effect."), QMessageBox::Yes | QMessageBox::No); - if (n == QMessageBox::Yes) { - this->exit_reason = 2; - on_menu_exit_triggered(); - } - } - // - if (info == "RestartProgram") { - this->exit_reason = 2; - on_menu_exit_triggered(); - } else if (info == "Raise") { - ActivateWindow(this); - } else if (info == "ClearConnectionList") { - refresh_connection_list({}); - } - // sender - if (sender == Dialog_DialogEditProfile) { - auto msg = info.split(","); - if (msg.contains("accept")) { - refresh_proxy_list(); - if (msg.contains("restart")) { - if (QMessageBox::question(GetMessageBoxParent(), tr("Confirmation"), tr("Settings changed, restart proxy?")) == QMessageBox::StandardButton::Yes) { - neko_start(NekoGui::dataStore->started_id); - } - } - } - } else if (sender == Dialog_DialogManageGroups) { - if (info.startsWith("refresh")) { - this->refresh_groups(); - } - } else if (sender == "SubUpdater") { - if (info.startsWith("finish")) { - refresh_proxy_list(); - if (!info.contains("dingyue")) { - show_log_impl(tr("Imported %1 profile(s)").arg(NekoGui::dataStore->imported_count)); - } - } else if (info == "NewGroup") { - refresh_groups(); - } - } else if (sender == "ExternalProcess") { - if (info == "Crashed") { - neko_stop(); - } else if (info == "CoreCrashed") { - neko_stop(true); - } else if (info.startsWith("CoreStarted")) { - neko_start(info.split(",")[1].toInt()); - } - } -} - -// top bar & tray menu - -inline bool dialog_is_using = false; - -#define USE_DIALOG(a) \ - if (dialog_is_using) return; \ - dialog_is_using = true; \ - auto dialog = new a(this); \ - connect(dialog, &QDialog::finished, this, [=] { \ - dialog->deleteLater(); \ - dialog_is_using = false; \ - }); \ - dialog->show(); - -void MainWindow::on_menu_basic_settings_triggered() { - USE_DIALOG(DialogBasicSettings) -} - -void MainWindow::on_menu_manage_groups_triggered() { - USE_DIALOG(DialogManageGroups) -} - -void MainWindow::on_menu_routing_settings_triggered() { - USE_DIALOG(DialogManageRoutes) -} - -void MainWindow::on_menu_vpn_settings_triggered() { - USE_DIALOG(DialogVPNSettings) -} - -void MainWindow::on_menu_hotkey_settings_triggered() { - USE_DIALOG(DialogHotkey) -} - -void MainWindow::on_commitDataRequest() { - qDebug() << "Start of data save"; - // - if (!isMaximized()) { - auto olds = NekoGui::dataStore->mw_size; - auto news = QStringLiteral("%1x%2").arg(size().width()).arg(size().height()); - if (olds != news) { - NekoGui::dataStore->mw_size = news; - } - } - // - NekoGui::dataStore->splitter_state = ui->splitter->saveState().toBase64(); - // - auto last_id = NekoGui::dataStore->started_id; - if (NekoGui::dataStore->remember_enable && last_id >= 0) { - NekoGui::dataStore->remember_id = last_id; - } - // - NekoGui::dataStore->Save(); - NekoGui::profileManager->SaveManager(); - qDebug() << "End of data save"; -} - -void MainWindow::on_menu_exit_triggered() { - if (mu_exit.tryLock()) { - NekoGui::dataStore->prepare_exit = true; - // - neko_set_spmode_system_proxy(false, false); - neko_set_spmode_vpn(false, false); - if (NekoGui::dataStore->spmode_vpn) { - mu_exit.unlock(); // retry - return; - } - RegisterHotkey(true); - // - on_commitDataRequest(); - // - NekoGui::dataStore->save_control_no_save = true; // don't change datastore after this line - neko_stop(false, true); - // - hide(); - runOnNewThread([=] { - sem_stopped.acquire(); - stop_core_daemon(); - runOnUiThread([=] { - on_menu_exit_triggered(); // continue exit progress - }); - }); - return; - } - // - MF_release_runguard(); - if (exit_reason == 1) { - QDir::setCurrent(QApplication::applicationDirPath()); - QProcess::startDetached("./updater", QStringList{}); - } else if (exit_reason == 2 || exit_reason == 3) { - QDir::setCurrent(QApplication::applicationDirPath()); - - auto arguments = NekoGui::dataStore->argv; - if (arguments.length() > 0) { - arguments.removeFirst(); - arguments.removeAll("-tray"); - arguments.removeAll("-flag_restart_tun_on"); - arguments.removeAll("-flag_reorder"); - } - auto isLauncher = qEnvironmentVariable("NKR_FROM_LAUNCHER") == "1"; - if (isLauncher) arguments.prepend("--"); - auto program = isLauncher ? "./launcher" : QApplication::applicationFilePath(); - - if (exit_reason == 3) { - // Tun restart as admin - arguments << "-flag_restart_tun_on"; -#ifdef Q_OS_WIN - WinCommander::runProcessElevated(program, arguments, "", WinCommander::SW_NORMAL, false); -#else - QProcess::startDetached(program, arguments); -#endif - } else { - QProcess::startDetached(program, arguments); - } - } - tray->hide(); - QCoreApplication::quit(); -} - -#define neko_set_spmode_FAILED \ - refresh_status(); \ - return; - -void MainWindow::neko_set_spmode_system_proxy(bool enable, bool save) { - if (enable != NekoGui::dataStore->spmode_system_proxy) { - if (enable) { - auto socks_port = NekoGui::dataStore->inbound_socks_port; - auto http_port = NekoGui::dataStore->inbound_socks_port; - SetSystemProxy(http_port, socks_port); - } else { - ClearSystemProxy(); - } - } - - if (save) { - NekoGui::dataStore->remember_spmode.removeAll("system_proxy"); - if (enable && NekoGui::dataStore->remember_enable) { - NekoGui::dataStore->remember_spmode.append("system_proxy"); - } - NekoGui::dataStore->Save(); - } - - NekoGui::dataStore->spmode_system_proxy = enable; - refresh_status(); -} - -void MainWindow::neko_set_spmode_vpn(bool enable, bool save) { - if (enable != NekoGui::dataStore->spmode_vpn) { - if (enable) { - if (NekoGui::dataStore->vpn_internal_tun) { - bool requestPermission = !NekoGui::IsAdmin(); - if (requestPermission) { -#ifdef Q_OS_LINUX - if (!Linux_HavePkexec()) { - MessageBoxWarning(software_name, "Please install \"pkexec\" first."); - neko_set_spmode_FAILED - } - auto ret = Linux_Pkexec_SetCapString(NekoGui::FindNekoBoxCoreRealPath(), "cap_net_admin=ep"); - if (ret == 0) { - this->exit_reason = 3; - on_menu_exit_triggered(); - } else { - MessageBoxWarning(software_name, "Setcap for Tun mode failed.\n\n1. You may canceled the dialog.\n2. You may be using an incompatible environment like AppImage."); - if (QProcessEnvironment::systemEnvironment().contains("APPIMAGE")) { - MW_show_log("If you are using AppImage, it's impossible to start a Tun. Please use other package instead."); - } - } -#endif -#ifdef Q_OS_WIN - auto n = QMessageBox::warning(GetMessageBoxParent(), software_name, tr("Please run NekoBox as admin"), QMessageBox::Yes | QMessageBox::No); - if (n == QMessageBox::Yes) { - this->exit_reason = 3; - on_menu_exit_triggered(); - } -#endif - neko_set_spmode_FAILED - } - } else { - if (NekoGui::dataStore->need_keep_vpn_off) { - MessageBoxWarning(software_name, tr("Current server is incompatible with Tun. Please stop the server first, enable Tun Mode, and then restart.")); - neko_set_spmode_FAILED - } - if (!StartVPNProcess()) { - neko_set_spmode_FAILED - } - } - } else { - if (NekoGui::dataStore->vpn_internal_tun) { - // current core is sing-box - } else { - if (!StopVPNProcess()) { - neko_set_spmode_FAILED - } - } - } - } - - if (save) { - NekoGui::dataStore->remember_spmode.removeAll("vpn"); - if (enable && NekoGui::dataStore->remember_enable) { - NekoGui::dataStore->remember_spmode.append("vpn"); - } - NekoGui::dataStore->Save(); - } - - NekoGui::dataStore->spmode_vpn = enable; - refresh_status(); - - if (NekoGui::dataStore->vpn_internal_tun && NekoGui::dataStore->started_id >= 0) neko_start(NekoGui::dataStore->started_id); -} - -void MainWindow::refresh_status(const QString &traffic_update) { - auto refresh_speed_label = [=] { - if (traffic_update_cache == "") { - ui->label_speed->setText(QObject::tr("Proxy: %1\nDirect: %2").arg("", "")); - } else { - ui->label_speed->setText(traffic_update_cache); - } - }; - - // From TrafficLooper - if (!traffic_update.isEmpty()) { - traffic_update_cache = traffic_update; - if (traffic_update == "STOP") { - traffic_update_cache = ""; - } else { - refresh_speed_label(); - return; - } - } - - refresh_speed_label(); - - // From UI - QString group_name; - if (running != nullptr) { - auto group = NekoGui::profileManager->GetGroup(running->gid); - if (group != nullptr) group_name = group->name; - } - - if (last_test_time.addSecs(2) < QTime::currentTime()) { - auto txt = running == nullptr ? tr("Not Running") - : QStringLiteral("[%1] %2").arg(group_name, running->bean->DisplayName()).left(30); - ui->label_running->setText(txt); - } - // - auto display_socks = DisplayAddress(NekoGui::dataStore->inbound_address, NekoGui::dataStore->inbound_socks_port); - auto inbound_txt = QStringLiteral("Mixed: %1").arg(display_socks); - ui->label_inbound->setText(inbound_txt); - // - ui->checkBox_VPN->setChecked(NekoGui::dataStore->spmode_vpn); - ui->checkBox_SystemProxy->setChecked(NekoGui::dataStore->spmode_system_proxy); - if (select_mode) { - ui->label_running->setText(tr("Select") + " *"); - ui->label_running->setToolTip(tr("Select mode, double-click or press Enter to select a profile, press ESC to exit.")); - } else { - ui->label_running->setToolTip({}); - } - - auto make_title = [=](bool isTray) { - QStringList tt; - if (!isTray && NekoGui::IsAdmin()) tt << "[Admin]"; - if (select_mode) tt << "[" + tr("Select") + "]"; - if (!title_error.isEmpty()) tt << "[" + title_error + "]"; - if (NekoGui::dataStore->spmode_vpn && !NekoGui::dataStore->spmode_system_proxy) tt << "[Tun]"; - if (!NekoGui::dataStore->spmode_vpn && NekoGui::dataStore->spmode_system_proxy) tt << "[" + tr("System Proxy") + "]"; - if (NekoGui::dataStore->spmode_vpn && NekoGui::dataStore->spmode_system_proxy) tt << "[Tun+" + tr("System Proxy") + "]"; - tt << software_name; - if (!isTray) tt << "(" + QString(NKR_VERSION) + ")"; - if (!NekoGui::dataStore->active_routing.isEmpty() && NekoGui::dataStore->active_routing != "Default") { - tt << "[" + NekoGui::dataStore->active_routing + "]"; - } - if (running != nullptr) tt << running->bean->DisplayTypeAndName() + "@" + group_name; - return tt.join(isTray ? "\n" : " "); - }; - - auto icon_status_new = Icon::NONE; - - if (running != nullptr) { - if (NekoGui::dataStore->spmode_vpn) { - icon_status_new = Icon::VPN; - } else if (NekoGui::dataStore->spmode_system_proxy) { - icon_status_new = Icon::SYSTEM_PROXY; - } else { - icon_status_new = Icon::RUNNING; - } - } - - // refresh title & window icon - setWindowTitle(make_title(false)); - if (icon_status_new != icon_status) QApplication::setWindowIcon(Icon::GetTrayIcon(Icon::NONE)); - - // refresh tray - if (tray != nullptr) { - tray->setToolTip(make_title(true)); - if (icon_status_new != icon_status) tray->setIcon(Icon::GetTrayIcon(icon_status_new)); - } - - icon_status = icon_status_new; -} - -// table显示 - -// refresh_groups -> show_group -> refresh_proxy_list -void MainWindow::refresh_groups() { - NekoGui::dataStore->refreshing_group_list = true; - - // refresh group? - for (int i = ui->tabWidget->count() - 1; i > 0; i--) { - ui->tabWidget->removeTab(i); - } - - int index = 0; - for (const auto &gid: NekoGui::profileManager->groupsTabOrder) { - auto group = NekoGui::profileManager->GetGroup(gid); - if (index == 0) { - ui->tabWidget->setTabText(0, group->name); - } else { - auto widget2 = new QWidget(); - auto layout2 = new QVBoxLayout(); - layout2->setContentsMargins(QMargins()); - layout2->setSpacing(0); - widget2->setLayout(layout2); - ui->tabWidget->addTab(widget2, group->name); - } - ui->tabWidget->tabBar()->setTabData(index, gid); - index++; - } - - // show after group changed - if (NekoGui::profileManager->CurrentGroup() == nullptr) { - NekoGui::dataStore->current_group = -1; - ui->tabWidget->setCurrentIndex(groupId2TabIndex(0)); - show_group(NekoGui::profileManager->groupsTabOrder.count() > 0 ? NekoGui::profileManager->groupsTabOrder.first() : 0); - } else { - ui->tabWidget->setCurrentIndex(groupId2TabIndex(NekoGui::dataStore->current_group)); - show_group(NekoGui::dataStore->current_group); - } - - NekoGui::dataStore->refreshing_group_list = false; -} - -void MainWindow::refresh_proxy_list(const int &id) { - refresh_proxy_list_impl(id, {}); -} - -void MainWindow::refresh_proxy_list_impl(const int &id, GroupSortAction groupSortAction) { - // id < 0 重绘 - if (id < 0) { - // 清空数据 - ui->proxyListTable->row2Id.clear(); - ui->proxyListTable->setRowCount(0); - // 添加行 - int row = -1; - for (const auto &[id, profile]: NekoGui::profileManager->profiles) { - if (NekoGui::dataStore->current_group != profile->gid) continue; - row++; - ui->proxyListTable->insertRow(row); - ui->proxyListTable->row2Id += id; - } - } - - // 显示排序 - if (id < 0) { - switch (groupSortAction.method) { - case GroupSortMethod::Raw: { - auto group = NekoGui::profileManager->CurrentGroup(); - if (group == nullptr) return; - ui->proxyListTable->order = group->order; - break; - } - case GroupSortMethod::ById: { - // Clear Order - ui->proxyListTable->order.clear(); - ui->proxyListTable->callback_save_order(); - break; - } - case GroupSortMethod::ByAddress: - case GroupSortMethod::ByName: - case GroupSortMethod::ByLatency: - case GroupSortMethod::ByType: { - std::sort(ui->proxyListTable->order.begin(), ui->proxyListTable->order.end(), - [=](int a, int b) { - QString ms_a; - QString ms_b; - if (groupSortAction.method == GroupSortMethod::ByType) { - ms_a = NekoGui::profileManager->GetProfile(a)->bean->DisplayType(); - ms_b = NekoGui::profileManager->GetProfile(b)->bean->DisplayType(); - } else if (groupSortAction.method == GroupSortMethod::ByName) { - ms_a = NekoGui::profileManager->GetProfile(a)->bean->name; - ms_b = NekoGui::profileManager->GetProfile(b)->bean->name; - } else if (groupSortAction.method == GroupSortMethod::ByAddress) { - ms_a = NekoGui::profileManager->GetProfile(a)->bean->DisplayAddress(); - ms_b = NekoGui::profileManager->GetProfile(b)->bean->DisplayAddress(); - } else if (groupSortAction.method == GroupSortMethod::ByLatency) { - ms_a = NekoGui::profileManager->GetProfile(a)->full_test_report; - ms_b = NekoGui::profileManager->GetProfile(b)->full_test_report; - } - auto get_latency_for_sort = [](int id) { - auto i = NekoGui::profileManager->GetProfile(id)->latency; - if (i == 0) i = 100000; - if (i < 0) i = 99999; - return i; - }; - if (groupSortAction.descending) { - if (groupSortAction.method == GroupSortMethod::ByLatency) { - if (ms_a.isEmpty() && ms_b.isEmpty()) { - // compare latency if full_test_report is empty - return get_latency_for_sort(a) > get_latency_for_sort(b); - } - } - return ms_a > ms_b; - } else { - if (groupSortAction.method == GroupSortMethod::ByLatency) { - auto int_a = NekoGui::profileManager->GetProfile(a)->latency; - auto int_b = NekoGui::profileManager->GetProfile(b)->latency; - if (ms_a.isEmpty() && ms_b.isEmpty()) { - // compare latency if full_test_report is empty - return get_latency_for_sort(a) < get_latency_for_sort(b); - } - } - return ms_a < ms_b; - } - }); - break; - } - } - ui->proxyListTable->update_order(groupSortAction.save_sort); - } - - // refresh data - refresh_proxy_list_impl_refresh_data(id); -} - -void MainWindow::refresh_proxy_list_impl_refresh_data(const int &id) { - // 绘制或更新item(s) - for (int row = 0; row < ui->proxyListTable->rowCount(); row++) { - auto profileId = ui->proxyListTable->row2Id[row]; - if (id >= 0 && profileId != id) continue; // refresh ONE item - auto profile = NekoGui::profileManager->GetProfile(profileId); - if (profile == nullptr) continue; - - auto isRunning = profileId == NekoGui::dataStore->started_id; - auto f0 = std::make_unique(); - f0->setData(114514, profileId); - - // Check state - auto check = f0->clone(); - check->setText(isRunning ? "✓" : Int2String(row + 1)); - ui->proxyListTable->setVerticalHeaderItem(row, check); - - // C0: Type - auto f = f0->clone(); - f->setText(profile->bean->DisplayType()); - if (isRunning) f->setForeground(palette().link()); - ui->proxyListTable->setItem(row, 0, f); - - // C1: Address+Port - f = f0->clone(); - f->setText(profile->bean->DisplayAddress()); - if (isRunning) f->setForeground(palette().link()); - ui->proxyListTable->setItem(row, 1, f); - - // C2: Name - f = f0->clone(); - f->setText(profile->bean->name); - if (isRunning) f->setForeground(palette().link()); - ui->proxyListTable->setItem(row, 2, f); - - // C3: Test Result - f = f0->clone(); - if (profile->full_test_report.isEmpty()) { - auto color = profile->DisplayLatencyColor(); - if (color.isValid()) f->setForeground(color); - f->setText(profile->DisplayLatency()); - } else { - f->setText(profile->full_test_report); - } - ui->proxyListTable->setItem(row, 3, f); - - // C4: Traffic - f = f0->clone(); - f->setText(profile->traffic_data->DisplayTraffic()); - ui->proxyListTable->setItem(row, 4, f); - } -} - -// table菜单相关 - -void MainWindow::on_proxyListTable_itemDoubleClicked(QTableWidgetItem *item) { - auto id = item->data(114514).toInt(); - if (select_mode) { - emit profile_selected(id); - select_mode = false; - refresh_status(); - return; - } - auto dialog = new DialogEditProfile("", id, this); - connect(dialog, &QDialog::finished, dialog, &QDialog::deleteLater); -} - -void MainWindow::on_menu_add_from_input_triggered() { - auto dialog = new DialogEditProfile("socks", NekoGui::dataStore->current_group, this); - connect(dialog, &QDialog::finished, dialog, &QDialog::deleteLater); -} - -void MainWindow::on_menu_add_from_clipboard_triggered() { - auto clipboard = QApplication::clipboard()->text(); - NekoGui_sub::groupUpdater->AsyncUpdate(clipboard); -} - -void MainWindow::on_menu_clone_triggered() { - auto ents = get_now_selected_list(); - if (ents.isEmpty()) return; - - auto btn = QMessageBox::question(this, tr("Clone"), tr("Clone %1 item(s)").arg(ents.count())); - if (btn != QMessageBox::Yes) return; - - QStringList sls; - for (const auto &ent: ents) { - sls << ent->bean->ToNekorayShareLink(ent->type); - } - - NekoGui_sub::groupUpdater->AsyncUpdate(sls.join("\n")); -} - -void MainWindow::on_menu_move_triggered() { - auto ents = get_now_selected_list(); - if (ents.isEmpty()) return; - - auto items = QStringList{}; - for (auto gid: NekoGui::profileManager->groupsTabOrder) { - auto group = NekoGui::profileManager->GetGroup(gid); - if (group == nullptr) continue; - items += Int2String(gid) + " " + group->name; - } - - bool ok; - auto a = QInputDialog::getItem(nullptr, - tr("Move"), - tr("Move %1 item(s)").arg(ents.count()), - items, 0, false, &ok); - if (!ok) return; - auto gid = SubStrBefore(a, " ").toInt(); - for (const auto &ent: ents) { - NekoGui::profileManager->MoveProfile(ent, gid); - } - refresh_proxy_list(); -} - -void MainWindow::on_menu_delete_triggered() { - auto ents = get_now_selected_list(); - if (ents.count() == 0) return; - if (QMessageBox::question(this, tr("Confirmation"), QString(tr("Remove %1 item(s) ?")).arg(ents.count())) == - QMessageBox::StandardButton::Yes) { - for (const auto &ent: ents) { - NekoGui::profileManager->DeleteProfile(ent->id); - } - refresh_proxy_list(); - } -} - -void MainWindow::on_menu_reset_traffic_triggered() { - auto ents = get_now_selected_list(); - if (ents.count() == 0) return; - for (const auto &ent: ents) { - ent->traffic_data->Reset(); - ent->Save(); - refresh_proxy_list(ent->id); - } -} - -void MainWindow::on_menu_profile_debug_info_triggered() { - auto ents = get_now_selected_list(); - if (ents.count() != 1) return; - auto btn = QMessageBox::information(this, software_name, ents.first()->ToJsonBytes(), "OK", "Edit", "Reload", 0, 0); - if (btn == 1) { - QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(QStringLiteral("profiles/%1.json").arg(ents.first()->id)).absoluteFilePath())); - } else if (btn == 2) { - NekoGui::dataStore->Load(); - NekoGui::profileManager->LoadManager(); - refresh_proxy_list(); - } -} - -void MainWindow::on_menu_copy_links_triggered() { - if (ui->masterLogBrowser->hasFocus()) { - ui->masterLogBrowser->copy(); - return; - } - auto ents = get_now_selected_list(); - QStringList links; - for (const auto &ent: ents) { - links += ent->bean->ToShareLink(); - } - if (links.length() == 0) return; - QApplication::clipboard()->setText(links.join("\n")); - show_log_impl(tr("Copied %1 item(s)").arg(links.length())); -} - -void MainWindow::on_menu_copy_links_nkr_triggered() { - auto ents = get_now_selected_list(); - QStringList links; - for (const auto &ent: ents) { - links += ent->bean->ToNekorayShareLink(ent->type); - } - if (links.length() == 0) return; - QApplication::clipboard()->setText(links.join("\n")); - show_log_impl(tr("Copied %1 item(s)").arg(links.length())); -} - -void MainWindow::on_menu_export_config_triggered() { - auto ents = get_now_selected_list(); - if (ents.count() != 1) return; - auto ent = ents.first(); - if (ent->bean->DisplayCoreType() != software_core_name) return; - - auto result = BuildConfig(ent, false, true); - QString config_core = QJsonObject2QString(result->coreConfig, false); - QApplication::clipboard()->setText(config_core); - - QMessageBox msg(QMessageBox::Information, tr("Config copied"), tr("Config copied")); - msg.addButton("Copy core config", QMessageBox::YesRole); - msg.addButton("Copy test config", QMessageBox::NoRole); - msg.addButton(QMessageBox::Ok); - msg.setEscapeButton(QMessageBox::Ok); - msg.setDefaultButton(QMessageBox::Ok); - auto ret = msg.exec(); - if (ret == 2) { - result = BuildConfig(ent, false, false); - config_core = QJsonObject2QString(result->coreConfig, false); - QApplication::clipboard()->setText(config_core); - } else if (ret == 3) { - result = BuildConfig(ent, true, false); - config_core = QJsonObject2QString(result->coreConfig, false); - QApplication::clipboard()->setText(config_core); - } -} - -void MainWindow::display_qr_link(bool nkrFormat) { - auto ents = get_now_selected_list(); - if (ents.count() != 1) return; - - class W : public QDialog { - public: - QLabel *l = nullptr; - QCheckBox *cb = nullptr; - // - QPlainTextEdit *l2 = nullptr; - QImage im; - // - QString link; - QString link_nk; - - void show_qr(const QSize &size) const { - auto side = size.height() - 20 - l2->size().height() - cb->size().height(); - l->setPixmap(QPixmap::fromImage(im.scaled(side, side, Qt::KeepAspectRatio, Qt::FastTransformation), - Qt::MonoOnly)); - l->resize(side, side); - } - - void refresh(bool is_nk) { - auto link_display = is_nk ? link_nk : link; - l2->setPlainText(link_display); - constexpr qint32 qr_padding = 2; - // - try { - qrcodegen::QrCode qr = qrcodegen::QrCode::encodeText(link_display.toUtf8().data(), qrcodegen::QrCode::Ecc::MEDIUM); - qint32 sz = qr.getSize(); - im = QImage(sz + qr_padding * 2, sz + qr_padding * 2, QImage::Format_RGB32); - QRgb black = qRgb(0, 0, 0); - QRgb white = qRgb(255, 255, 255); - im.fill(white); - for (int y = 0; y < sz; y++) - for (int x = 0; x < sz; x++) - if (qr.getModule(x, y)) - im.setPixel(x + qr_padding, y + qr_padding, black); - show_qr(size()); - } catch (const std::exception &ex) { - QMessageBox::warning(nullptr, "error", ex.what()); - } - } - - W(const QString &link_, const QString &link_nk_) { - link = link_; - link_nk = link_nk_; - // - setLayout(new QVBoxLayout); - setMinimumSize(256, 256); - QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); - sizePolicy.setHeightForWidth(true); - setSizePolicy(sizePolicy); - // - l = new QLabel(); - l->setMinimumSize(256, 256); - l->setMargin(6); - l->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - l->setScaledContents(true); - layout()->addWidget(l); - cb = new QCheckBox; - cb->setText("Neko Links"); - layout()->addWidget(cb); - l2 = new QPlainTextEdit(); - l2->setReadOnly(true); - layout()->addWidget(l2); - // - connect(cb, &QCheckBox::toggled, this, &W::refresh); - refresh(false); - } - - void resizeEvent(QResizeEvent *resizeEvent) override { - show_qr(resizeEvent->size()); - } - }; - - auto link = ents.first()->bean->ToShareLink(); - auto link_nk = ents.first()->bean->ToNekorayShareLink(ents.first()->type); - auto w = new W(link, link_nk); - w->setWindowTitle(ents.first()->bean->DisplayTypeAndName()); - w->exec(); - w->deleteLater(); -} - -void MainWindow::on_menu_scan_qr_triggered() { -#ifndef NKR_NO_ZXING - using namespace ZXingQt; - - hide(); - QThread::sleep(1); - - auto screen = QGuiApplication::primaryScreen(); - auto geom = screen->geometry(); - auto qpx = screen->grabWindow(0, geom.x(), geom.y(), geom.width(), geom.height()); - - show(); - - auto hints = DecodeHints() - .setFormats(BarcodeFormat::QRCode) - .setTryRotate(false) - .setBinarizer(Binarizer::FixedThreshold); - - auto result = ReadBarcode(qpx.toImage(), hints); - const auto &text = result.text(); - if (text.isEmpty()) { - MessageBoxInfo(software_name, tr("QR Code not found")); - } else { - show_log_impl("QR Code Result:\n" + text); - NekoGui_sub::groupUpdater->AsyncUpdate(text); - } -#endif -} - -void MainWindow::on_menu_clear_test_result_triggered() { - for (const auto &profile: get_selected_or_group()) { - profile->latency = 0; - profile->full_test_report = ""; - profile->Save(); - } - refresh_proxy_list(); -} - -void MainWindow::on_menu_select_all_triggered() { - if (ui->masterLogBrowser->hasFocus()) { - ui->masterLogBrowser->selectAll(); - return; - } - ui->proxyListTable->selectAll(); -} - -void MainWindow::on_menu_delete_repeat_triggered() { - QList> out; - QList> out_del; - - NekoGui::ProfileFilter::Uniq(NekoGui::profileManager->CurrentGroup()->Profiles(), out, true, false); - NekoGui::ProfileFilter::OnlyInSrc_ByPointer(NekoGui::profileManager->CurrentGroup()->Profiles(), out, out_del); - - int remove_display_count = 0; - QString remove_display; - for (const auto &ent: out_del) { - remove_display += ent->bean->DisplayTypeAndName() + "\n"; - if (++remove_display_count == 20) { - remove_display += "..."; - break; - } - } - - if (out_del.length() > 0 && - QMessageBox::question(this, tr("Confirmation"), tr("Remove %1 item(s) ?").arg(out_del.length()) + "\n" + remove_display) == QMessageBox::StandardButton::Yes) { - for (const auto &ent: out_del) { - NekoGui::profileManager->DeleteProfile(ent->id); - } - refresh_proxy_list(); - } -} - -bool mw_sub_updating = false; - -void MainWindow::on_menu_update_subscription_triggered() { - auto group = NekoGui::profileManager->CurrentGroup(); - if (group->url.isEmpty()) return; - if (mw_sub_updating) return; - mw_sub_updating = true; - NekoGui_sub::groupUpdater->AsyncUpdate(group->url, group->id, [&] { mw_sub_updating = false; }); -} - -void MainWindow::on_menu_remove_unavailable_triggered() { - QList> out_del; - - for (const auto &[_, profile]: NekoGui::profileManager->profiles) { - if (NekoGui::dataStore->current_group != profile->gid) continue; - if (profile->latency < 0) out_del += profile; - } - - int remove_display_count = 0; - QString remove_display; - for (const auto &ent: out_del) { - remove_display += ent->bean->DisplayTypeAndName() + "\n"; - if (++remove_display_count == 20) { - remove_display += "..."; - break; - } - } - - if (out_del.length() > 0 && - QMessageBox::question(this, tr("Confirmation"), tr("Remove %1 item(s) ?").arg(out_del.length()) + "\n" + remove_display) == QMessageBox::StandardButton::Yes) { - for (const auto &ent: out_del) { - NekoGui::profileManager->DeleteProfile(ent->id); - } - refresh_proxy_list(); - } -} - -void MainWindow::on_menu_resolve_domain_triggered() { - auto profiles = get_selected_or_group(); - if (profiles.isEmpty()) return; - - if (QMessageBox::question(this, - tr("Confirmation"), - tr("Resolving domain to IP, if support.")) != QMessageBox::StandardButton::Yes) { - return; - } - if (mw_sub_updating) return; - mw_sub_updating = true; - NekoGui::dataStore->resolve_count = profiles.count(); - - for (const auto &profile: profiles) { - profile->bean->ResolveDomainToIP([=] { - profile->Save(); - if (--NekoGui::dataStore->resolve_count != 0) return; - refresh_proxy_list(); - mw_sub_updating = false; - }); - } -} - -void MainWindow::on_proxyListTable_customContextMenuRequested(const QPoint &pos) { - ui->menu_server->popup(ui->proxyListTable->viewport()->mapToGlobal(pos)); // 弹出菜单 -} - -QList> MainWindow::get_now_selected_list() { - auto items = ui->proxyListTable->selectedItems(); - QList> list; - for (auto item: items) { - auto id = item->data(114514).toInt(); - auto ent = NekoGui::profileManager->GetProfile(id); - if (ent != nullptr && !list.contains(ent)) list += ent; - } - return list; -} - -QList> MainWindow::get_selected_or_group() { - auto selected_or_group = ui->menu_server->property("selected_or_group").toInt(); - QList> profiles; - if (selected_or_group > 0) { - profiles = get_now_selected_list(); - if (profiles.isEmpty() && selected_or_group == 2) profiles = NekoGui::profileManager->CurrentGroup()->ProfilesWithOrder(); - } else { - profiles = NekoGui::profileManager->CurrentGroup()->ProfilesWithOrder(); - } - return profiles; -} - -void MainWindow::keyPressEvent(QKeyEvent *event) { - switch (event->key()) { - case Qt::Key_Escape: - // take over by shortcut_esc - break; - case Qt::Key_Enter: - neko_start(); - break; - default: - QMainWindow::keyPressEvent(event); - } -} - -// Log - -inline void FastAppendTextDocument(const QString &message, QTextDocument *doc) { - QTextCursor cursor(doc); - cursor.movePosition(QTextCursor::End); - cursor.beginEditBlock(); - cursor.insertBlock(); - cursor.insertText(message); - cursor.endEditBlock(); -} - -void MainWindow::show_log_impl(const QString &log) { - auto lines = SplitLines(log.trimmed()); - if (lines.isEmpty()) return; - - QStringList newLines; - auto log_ignore = NekoGui::dataStore->log_ignore; - for (const auto &line: lines) { - bool showThisLine = true; - for (const auto &str: log_ignore) { - if (line.contains(str)) { - showThisLine = false; - break; - } - } - if (showThisLine) newLines << line; - } - if (newLines.isEmpty()) return; - - FastAppendTextDocument(newLines.join("\n"), qvLogDocument); - // qvLogDocument->setPlainText(qvLogDocument->toPlainText() + log); - // From https://gist.github.com/jemyzhang/7130092 - auto block = qvLogDocument->begin(); - - while (block.isValid()) { - if (qvLogDocument->blockCount() > NekoGui::dataStore->max_log_line) { - QTextCursor cursor(block); - block = block.next(); - cursor.select(QTextCursor::BlockUnderCursor); - cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor); - cursor.removeSelectedText(); - continue; - } - break; - } -} - -#define ADD_TO_CURRENT_ROUTE(a, b) \ - NekoGui::dataStore->routing->a = (SplitLines(NekoGui::dataStore->routing->a) << (b)).join("\n"); \ - NekoGui::dataStore->routing->Save(); - -void MainWindow::on_masterLogBrowser_customContextMenuRequested(const QPoint &pos) { - QMenu *menu = ui->masterLogBrowser->createStandardContextMenu(); - - auto sep = new QAction(this); - sep->setSeparator(true); - menu->addAction(sep); - - auto action_add_ignore = new QAction(this); - action_add_ignore->setText(tr("Set ignore keyword")); - connect(action_add_ignore, &QAction::triggered, this, [=] { - auto list = NekoGui::dataStore->log_ignore; - auto newStr = ui->masterLogBrowser->textCursor().selectedText().trimmed(); - if (!newStr.isEmpty()) list << newStr; - bool ok; - newStr = QInputDialog::getMultiLineText(GetMessageBoxParent(), tr("Set ignore keyword"), tr("Set the following keywords to ignore?\nSplit by line."), list.join("\n"), &ok); - if (ok) { - NekoGui::dataStore->log_ignore = SplitLines(newStr); - NekoGui::dataStore->Save(); - } - }); - menu->addAction(action_add_ignore); - - auto action_add_route = new QAction(this); - action_add_route->setText(tr("Save as route")); - connect(action_add_route, &QAction::triggered, this, [=] { - auto newStr = ui->masterLogBrowser->textCursor().selectedText().trimmed(); - if (newStr.isEmpty()) return; - // - bool ok; - newStr = QInputDialog::getText(GetMessageBoxParent(), tr("Save as route"), tr("Edit"), {}, newStr, &ok).trimmed(); - if (!ok) return; - if (newStr.isEmpty()) return; - // - auto select = IsIpAddress(newStr) ? 0 : 3; - QStringList items = {"proxyIP", "bypassIP", "blockIP", "proxyDomain", "bypassDomain", "blockDomain"}; - auto item = QInputDialog::getItem(GetMessageBoxParent(), tr("Save as route"), - tr("Save \"%1\" as a routing rule?").arg(newStr), - items, select, false, &ok); - if (ok) { - auto index = items.indexOf(item); - switch (index) { - case 0: - ADD_TO_CURRENT_ROUTE(proxy_ip, newStr); - break; - case 1: - ADD_TO_CURRENT_ROUTE(direct_ip, newStr); - break; - case 2: - ADD_TO_CURRENT_ROUTE(block_ip, newStr); - break; - case 3: - ADD_TO_CURRENT_ROUTE(proxy_domain, newStr); - break; - case 4: - ADD_TO_CURRENT_ROUTE(direct_domain, newStr); - break; - case 5: - ADD_TO_CURRENT_ROUTE(block_domain, newStr); - break; - default: - break; - } - MW_dialog_message("", "UpdateDataStore,RouteChanged"); - } - }); - menu->addAction(action_add_route); - - auto action_clear = new QAction(this); - action_clear->setText(tr("Clear")); - connect(action_clear, &QAction::triggered, this, [=] { - qvLogDocument->clear(); - ui->masterLogBrowser->clear(); - }); - menu->addAction(action_clear); - - menu->exec(ui->masterLogBrowser->viewport()->mapToGlobal(pos)); // 弹出菜单 -} - -// eventFilter - -bool MainWindow::eventFilter(QObject *obj, QEvent *event) { - if (event->type() == QEvent::MouseButtonPress) { - auto mouseEvent = dynamic_cast(event); - if (obj == ui->label_running && mouseEvent->button() == Qt::LeftButton && running != nullptr) { - speedtest_current(); - return true; - } else if (obj == ui->label_inbound && mouseEvent->button() == Qt::LeftButton) { - on_menu_basic_settings_triggered(); - return true; - } - } else if (event->type() == QEvent::MouseButtonDblClick) { - if (obj == ui->splitter) { - auto size = ui->splitter->size(); - ui->splitter->setSizes({size.height() / 2, size.height() / 2}); - } - } - return QMainWindow::eventFilter(obj, event); -} - -// profile selector - -void MainWindow::start_select_mode(QObject *context, const std::function &callback) { - select_mode = true; - connectOnce(this, &MainWindow::profile_selected, context, callback); - refresh_status(); -} - -// 连接列表 - -inline QJsonArray last_arr; // format is nekoray_connections_json - -void MainWindow::refresh_connection_list(const QJsonArray &arr) { - if (last_arr == arr) { - return; - } - last_arr = arr; - - if (NekoGui::dataStore->flag_debug) qDebug() << arr; - - ui->tableWidget_conn->setRowCount(0); - - int row = -1; - for (const auto &_item: arr) { - auto item = _item.toObject(); - if (NekoGui::dataStore->ignoreConnTag.contains(item["Tag"].toString())) continue; - - row++; - ui->tableWidget_conn->insertRow(row); - - auto f0 = std::make_unique(); - f0->setData(114514, item["ID"].toInt()); - - // C0: Status - auto c0 = new QLabel; - auto start_t = item["Start"].toInt(); - auto end_t = item["End"].toInt(); - // icon - auto outboundTag = item["Tag"].toString(); - if (outboundTag == "block") { - c0->setPixmap(Icon::GetMaterialIcon("cancel")); - } else { - if (end_t > 0) { - c0->setPixmap(Icon::GetMaterialIcon("history")); - } else { - c0->setPixmap(Icon::GetMaterialIcon("swap-vertical")); - } - } - c0->setAlignment(Qt::AlignCenter); - c0->setToolTip(tr("Start: %1\nEnd: %2").arg(DisplayTime(start_t), end_t > 0 ? DisplayTime(end_t) : "")); - ui->tableWidget_conn->setCellWidget(row, 0, c0); - - // C1: Outbound - auto f = f0->clone(); - f->setToolTip(""); - f->setText(outboundTag); - ui->tableWidget_conn->setItem(row, 1, f); - - // C2: Destination - f = f0->clone(); - QString target1 = item["Dest"].toString(); - QString target2 = item["RDest"].toString(); - if (target2.isEmpty() || target1 == target2) { - target2 = ""; - } - f->setText("[" + target1 + "] " + target2); - ui->tableWidget_conn->setItem(row, 2, f); - } -} - -// Hotkey - -#ifndef NKR_NO_QHOTKEY - -#include - -inline QList> RegisteredHotkey; - -void MainWindow::RegisterHotkey(bool unregister) { - while (!RegisteredHotkey.isEmpty()) { - auto hk = RegisteredHotkey.takeFirst(); - hk->deleteLater(); - } - if (unregister) return; - - QStringList regstr{ - NekoGui::dataStore->hotkey_mainwindow, - NekoGui::dataStore->hotkey_group, - NekoGui::dataStore->hotkey_route, - NekoGui::dataStore->hotkey_system_proxy_menu, - }; - - for (const auto &key: regstr) { - if (key.isEmpty()) continue; - if (regstr.count(key) > 1) return; // Conflict hotkey - } - for (const auto &key: regstr) { - QKeySequence k(key); - if (k.isEmpty()) continue; - auto hk = std::make_shared(k, true); - if (hk->isRegistered()) { - RegisteredHotkey += hk; - connect(hk.get(), &QHotkey::activated, this, [=] { HotkeyEvent(key); }); - } else { - hk->deleteLater(); - } - } -} - -void MainWindow::HotkeyEvent(const QString &key) { - if (key.isEmpty()) return; - runOnUiThread([=] { - if (key == NekoGui::dataStore->hotkey_mainwindow) { - tray->activated(QSystemTrayIcon::ActivationReason::Trigger); - } else if (key == NekoGui::dataStore->hotkey_group) { - on_menu_manage_groups_triggered(); - } else if (key == NekoGui::dataStore->hotkey_route) { - on_menu_routing_settings_triggered(); - } else if (key == NekoGui::dataStore->hotkey_system_proxy_menu) { - ui->menu_spmode->popup(QCursor::pos()); - } - }); -} - -#else - -void MainWindow::RegisterHotkey(bool unregister) {} - -void MainWindow::HotkeyEvent(const QString &key) {} - -#endif - -// VPN Launcher - -bool MainWindow::StartVPNProcess() { - // - if (vpn_pid != 0) { - return true; - } - // - auto configPath = NekoGui::WriteVPNSingBoxConfig(); - auto scriptPath = NekoGui::WriteVPNLinuxScript(configPath); - // -#ifdef Q_OS_WIN - runOnNewThread([=] { - vpn_pid = 1; // TODO get pid? - WinCommander::runProcessElevated(QApplication::applicationDirPath() + "/nekobox_core.exe", - {"--disable-color", "run", "-c", configPath}, "", - NekoGui::dataStore->vpn_hide_console ? WinCommander::SW_HIDE : WinCommander::SW_SHOWMINIMIZED); // blocking - vpn_pid = 0; - runOnUiThread([=] { neko_set_spmode_vpn(false); }); - }); -#else - // - auto vpn_process = new QProcess; - QProcess::connect(vpn_process, &QProcess::stateChanged, this, [=](QProcess::ProcessState state) { - if (state == QProcess::NotRunning) { - vpn_pid = 0; - vpn_process->deleteLater(); - GetMainWindow()->neko_set_spmode_vpn(false); - } - }); - // - vpn_process->setProcessChannelMode(QProcess::ForwardedChannels); -#ifdef Q_OS_MACOS - vpn_process->start("osascript", {"-e", QStringLiteral("do shell script \"%1\" with administrator privileges") - .arg("bash " + scriptPath)}); -#else - vpn_process->start("pkexec", {"bash", scriptPath}); -#endif - vpn_process->waitForStarted(); - vpn_pid = vpn_process->processId(); // actually it's pkexec or bash PID -#endif - return true; -} - -bool MainWindow::StopVPNProcess(bool unconditional) { - if (unconditional || vpn_pid != 0) { - bool ok; - core_process->processId(); -#ifdef Q_OS_WIN - auto ret = WinCommander::runProcessElevated("taskkill", {"/IM", "nekobox_core.exe", - "/FI", - "PID ne " + Int2String(core_process->processId())}); - ok = ret == 0; -#else - QProcess p; -#ifdef Q_OS_MACOS - p.start("osascript", {"-e", QStringLiteral("do shell script \"%1\" with administrator privileges") - .arg("pkill -2 -U 0 nekobox_core")}); -#else - if (unconditional) { - p.start("pkexec", {"killall", "-2", "nekobox_core"}); - } else { - p.start("pkexec", {"pkill", "-2", "-P", Int2String(vpn_pid)}); - } -#endif - p.waitForFinished(); - ok = p.exitCode() == 0; -#endif - if (!unconditional) { - ok ? vpn_pid = 0 : MessageBoxWarning(tr("Error"), tr("Failed to stop Tun process")); - } - return ok; - } - return true; -} diff --git a/ui/mainwindow.h b/ui/mainwindow.h deleted file mode 100644 index 5ca492d..0000000 --- a/ui/mainwindow.h +++ /dev/null @@ -1,206 +0,0 @@ -#pragma once - -#include - -#include "main/NekoGui.hpp" - -#ifndef MW_INTERFACE - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "GroupSort.hpp" - -#include "db/ProxyEntity.hpp" -#include "main/GuiUtils.hpp" - -#endif - -namespace NekoGui_sys { - class CoreProcess; -} - -QT_BEGIN_NAMESPACE -namespace Ui { - class MainWindow; -} -QT_END_NAMESPACE - -class MainWindow : public QMainWindow { - Q_OBJECT - -public: - explicit MainWindow(QWidget *parent = nullptr); - - ~MainWindow() override; - - void refresh_proxy_list(const int &id = -1); - - void show_group(int gid); - - void refresh_groups(); - - void refresh_status(const QString &traffic_update = ""); - - void neko_start(int _id = -1); - - void neko_stop(bool crash = false, bool sem = false); - - void neko_set_spmode_system_proxy(bool enable, bool save = true); - - void neko_set_spmode_vpn(bool enable, bool save = true); - - void show_log_impl(const QString &log); - - void start_select_mode(QObject *context, const std::function &callback); - - void refresh_connection_list(const QJsonArray &arr); - - void RegisterHotkey(bool unregister); - - bool StopVPNProcess(bool unconditional = false); - -signals: - - void profile_selected(int id); - -public slots: - - void on_commitDataRequest(); - - void on_menu_exit_triggered(); - -#ifndef MW_INTERFACE - -private slots: - - void on_masterLogBrowser_customContextMenuRequested(const QPoint &pos); - - void on_menu_basic_settings_triggered(); - - void on_menu_routing_settings_triggered(); - - void on_menu_vpn_settings_triggered(); - - void on_menu_hotkey_settings_triggered(); - - void on_menu_add_from_input_triggered(); - - void on_menu_add_from_clipboard_triggered(); - - void on_menu_clone_triggered(); - - void on_menu_move_triggered(); - - void on_menu_delete_triggered(); - - void on_menu_reset_traffic_triggered(); - - void on_menu_profile_debug_info_triggered(); - - void on_menu_copy_links_triggered(); - - void on_menu_copy_links_nkr_triggered(); - - void on_menu_export_config_triggered(); - - void display_qr_link(bool nkrFormat = false); - - void on_menu_scan_qr_triggered(); - - void on_menu_clear_test_result_triggered(); - - void on_menu_manage_groups_triggered(); - - void on_menu_select_all_triggered(); - - void on_menu_delete_repeat_triggered(); - - void on_menu_remove_unavailable_triggered(); - - void on_menu_update_subscription_triggered(); - - void on_menu_resolve_domain_triggered(); - - void on_proxyListTable_itemDoubleClicked(QTableWidgetItem *item); - - void on_proxyListTable_customContextMenuRequested(const QPoint &pos); - - void on_tabWidget_currentChanged(int index); - -private: - Ui::MainWindow *ui; - QSystemTrayIcon *tray; - QShortcut *shortcut_ctrl_f = new QShortcut(QKeySequence("Ctrl+F"), this); - QShortcut *shortcut_esc = new QShortcut(QKeySequence("Esc"), this); - // - NekoGui_sys::CoreProcess *core_process; - qint64 vpn_pid = 0; - // - bool qvLogAutoScoll = true; - QTextDocument *qvLogDocument = new QTextDocument(this); - // - QString title_error; - int icon_status = -1; - std::shared_ptr running; - QString traffic_update_cache; - QTime last_test_time; - // - int proxy_last_order = -1; - bool select_mode = false; - QMutex mu_starting; - QMutex mu_stopping; - QMutex mu_exit; - QSemaphore sem_stopped; - int exit_reason = 0; - - QList> get_now_selected_list(); - - QList> get_selected_or_group(); - - void dialog_message_impl(const QString &sender, const QString &info); - - void refresh_proxy_list_impl(const int &id = -1, GroupSortAction groupSortAction = {}); - - void refresh_proxy_list_impl_refresh_data(const int &id = -1); - - void keyPressEvent(QKeyEvent *event) override; - - void closeEvent(QCloseEvent *event) override; - - // - - void HotkeyEvent(const QString &key); - - bool StartVPNProcess(); - - // grpc and ... - - static void setup_grpc(); - - void speedtest_current_group(int mode, bool test_group); - - void speedtest_current(); - - static void stop_core_daemon(); - - void CheckUpdate(); - -protected: - bool eventFilter(QObject *obj, QEvent *event) override; - -#endif // MW_INTERFACE -}; - -inline MainWindow *GetMainWindow() { - return (MainWindow *) mainwindow; -} - -void UI_InitMainWindow(); diff --git a/ui/mainwindow.ui b/ui/mainwindow.ui deleted file mode 100644 index 585577a..0000000 --- a/ui/mainwindow.ui +++ /dev/null @@ -1,932 +0,0 @@ - - - MainWindow - - - - 0 - 0 - 800 - 600 - - - - - 800 - 600 - - - - nya - - - - - - - - - Program - - - - .. - - - - 24 - 24 - - - - QToolButton::InstantPopup - - - Qt::ToolButtonTextUnderIcon - - - - - - - Preferences - - - - .. - - - - 24 - 24 - - - - QToolButton::InstantPopup - - - Qt::ToolButtonTextUnderIcon - - - - - - - Server - - - - .. - - - - 24 - 24 - - - - QToolButton::InstantPopup - - - Qt::ToolButtonTextUnderIcon - - - - - - - Ads - - - - .. - - - - 24 - 24 - - - - QToolButton::InstantPopup - - - Qt::ToolButtonTextUnderIcon - - - - - - - Document - - - - .. - - - - 24 - 24 - - - - QToolButton::InstantPopup - - - Qt::ToolButtonTextUnderIcon - - - - - - - Update - - - - .. - - - - 24 - 24 - - - - QToolButton::InstantPopup - - - Qt::ToolButtonTextUnderIcon - - - - - - - - - - 0 - 0 - - - - Tun Mode - - - - - - - System Proxy - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - true - - - - - - - URL Test - - - QToolButton::InstantPopup - - - Qt::ToolButtonTextUnderIcon - - - - - - - - - Qt::Vertical - - - - 0 - - - true - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Qt::CustomContextMenu - - - QAbstractItemView::NoEditTriggers - - - true - - - QAbstractItemView::SelectRows - - - QAbstractItemView::ScrollPerPixel - - - false - - - 16 - - - false - - - false - - - 30 - - - - Type - - - - - Address - - - - - Name - - - - - Test Result - - - - - Traffic - - - - - - - - - - - - - 0 - - - - Log - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Qt::CustomContextMenu - - - false - - - - - - - - Connection - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Qt::CustomContextMenu - - - QAbstractItemView::NoEditTriggers - - - QAbstractItemView::SelectRows - - - QAbstractItemView::ScrollPerPixel - - - QAbstractItemView::ScrollPerPixel - - - false - - - - Status - - - - - Outbound - - - - - Destination - - - - - - - - - - - - - - - - - - - - - - - - - Qt::Horizontal - - - QSizePolicy::Maximum - - - - 0 - 20 - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - 0 - 800 - 32 - - - - - Program - - - - System Proxy - - - - - - - - Preferences - - - - - - Active Server - - - - - - Active Routing - - - - - - - - - - - - - - - - - - - - - - Preferences - - - - - - - - - - - Server - - - - Share - - - - - - - - - - Current Group - - - - - - - - - - - - - - - - - Current Select - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Exit - - - - - Show Window - - - - - Basic Settings - - - - - New profile - - - - - Groups - - - - - Start - - - Return - - - - - Stop - - - Ctrl+S - - - - - Routing Settings - - - - - Add profile from clipboard - - - Ctrl+V - - - - - Delete - - - Del - - - - - Add profile from clipboard - - - - - Debug Info - - - - - QR Code and link - - - Ctrl+Q - - - - - Copy Link - - - - - Tcp Ping - - - Ctrl+Alt+T - - - - - Url Test - - - Ctrl+Alt+U - - - - - Clear Test Result - - - Ctrl+Alt+C - - - - - Export %1 config - - - Ctrl+E - - - - - Reset Traffic - - - Ctrl+R - - - - - Scan QR Code - - - - - true - - - Enable System Proxy - - - - - true - - - Disable - - - - - Remove Duplicates - - - Ctrl+Alt+D - - - - - fake - - - false - - - - - Move - - - Ctrl+M - - - - - true - - - Start with system - - - - - true - - - Remember last profile - - - - - true - - - Allow other devices to connect - - - - - Remove Unavailable - - - Ctrl+Alt+R - - - - - Full Test - - - Ctrl+Alt+F - - - - - Hotkey Settings - - - - - Select All - - - Ctrl+A - - - - - Copy links of selected (Neko Links) - - - Ctrl+N - - - - - fake - - - false - - - - - fake - - - false - - - - - Copy links of selected - - - Ctrl+C - - - - - true - - - Enable Tun - - - - - Clone - - - Ctrl+D - - - - - Update subscription - - - Ctrl+U - - - - - Resolve domain - - - Ctrl+Alt+I - - - - - Tun Settings - - - - - Restart Program - - - - - Open Config Folder - - - - - fake - - - false - - - - - fake - - - false - - - - - Restart Proxy - - - - - Stop Testing - - - Ctrl+Alt+S - - - - - - MyTableWidget - QTableWidget -
ui/widget/MyTableWidget.h
-
-
- - -
diff --git a/ui/mainwindow_grpc.cpp b/ui/mainwindow_grpc.cpp deleted file mode 100644 index f9123ee..0000000 --- a/ui/mainwindow_grpc.cpp +++ /dev/null @@ -1,554 +0,0 @@ -#include "./ui_mainwindow.h" -#include "mainwindow.h" - -#include "db/Database.hpp" -#include "db/ConfigBuilder.hpp" -#include "db/traffic/TrafficLooper.hpp" -#include "rpc/gRPC.h" -#include "ui/widget/MessageBoxTimer.h" - -#include -#include -#include -#include -#include -#include -#include - -// ext core - -std::list> CreateExtCFromExtR(const std::list> &extRs, bool start) { - // plz run and start in same thread - std::list> l; - for (const auto &extR: extRs) { - std::shared_ptr extC(new NekoGui_sys::ExternalProcess()); - extC->tag = extR->tag; - extC->program = extR->program; - extC->arguments = extR->arguments; - extC->env = extR->env; - l.emplace_back(extC); - // - if (start) extC->Start(); - } - return l; -} - -// grpc - -#ifndef NKR_NO_GRPC -using namespace NekoGui_rpc; -#endif - -void MainWindow::setup_grpc() { -#ifndef NKR_NO_GRPC - // Setup Connection - defaultClient = new Client( - [=](const QString &errStr) { - MW_show_log("[Error] gRPC: " + errStr); - }, - "127.0.0.1:" + Int2String(NekoGui::dataStore->core_port), NekoGui::dataStore->core_token); - - // Looper - runOnNewThread([=] { NekoGui_traffic::trafficLooper->Loop(); }); -#endif -} - -// 测速 - -inline bool speedtesting = false; -inline QList speedtesting_threads = {}; - -void MainWindow::speedtest_current_group(int mode, bool test_group) { - if (speedtesting) { - MessageBoxWarning(software_name, QObject::tr("The last speed test did not exit completely, please wait. If it persists, please restart the program.")); - return; - } - - auto profiles = get_selected_or_group(); - if (test_group) profiles = NekoGui::profileManager->CurrentGroup()->ProfilesWithOrder(); - if (profiles.isEmpty()) return; - auto group = NekoGui::profileManager->CurrentGroup(); - if (group->archive) return; - - // menu_stop_testing - if (mode == 114514) { - while (!speedtesting_threads.isEmpty()) { - auto t = speedtesting_threads.takeFirst(); - if (t != nullptr) t->exit(); - } - speedtesting = false; - return; - } - -#ifndef NKR_NO_GRPC - QStringList full_test_flags; - if (mode == libcore::FullTest) { - auto w = new QDialog(this); - auto layout = new QVBoxLayout(w); - w->setWindowTitle(tr("Test Options")); - // - auto l1 = new QCheckBox(tr("Latency")); - auto l2 = new QCheckBox(tr("UDP latency")); - auto l3 = new QCheckBox(tr("Download speed")); - auto l4 = new QCheckBox(tr("In and Out IP")); - // - auto box = new QDialogButtonBox; - box->setOrientation(Qt::Horizontal); - box->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok); - connect(box, &QDialogButtonBox::accepted, w, &QDialog::accept); - connect(box, &QDialogButtonBox::rejected, w, &QDialog::reject); - // - layout->addWidget(l1); - layout->addWidget(l2); - layout->addWidget(l3); - layout->addWidget(l4); - layout->addWidget(box); - if (w->exec() != QDialog::Accepted) { - w->deleteLater(); - return; - } - // - if (l1->isChecked()) full_test_flags << "1"; - if (l2->isChecked()) full_test_flags << "2"; - if (l3->isChecked()) full_test_flags << "3"; - if (l4->isChecked()) full_test_flags << "4"; - // - w->deleteLater(); - if (full_test_flags.isEmpty()) return; - } - speedtesting = true; - - runOnNewThread([this, profiles, mode, full_test_flags]() { - QMutex lock_write; - QMutex lock_return; - int threadN = NekoGui::dataStore->test_concurrent; - int threadN_finished = 0; - auto profiles_test = profiles; // copy - - // Threads - lock_return.lock(); - for (int i = 0; i < threadN; i++) { - runOnNewThread([&] { - speedtesting_threads << QObject::thread(); - - forever { - // - lock_write.lock(); - if (profiles_test.isEmpty()) { - threadN_finished++; - if (threadN == threadN_finished) { - // quit control thread - lock_return.unlock(); - } - lock_write.unlock(); - // quit of this thread - speedtesting_threads.removeAll(QObject::thread()); - return; - } - auto profile = profiles_test.takeFirst(); - lock_write.unlock(); - - // - libcore::TestReq req; - req.set_mode((libcore::TestMode) mode); - req.set_timeout(10 * 1000); - req.set_url(NekoGui::dataStore->test_latency_url.toStdString()); - - // - std::list> extCs; - QSemaphore extSem; - - if (mode == libcore::TestMode::UrlTest || mode == libcore::FullTest) { - auto c = BuildConfig(profile, true, false); - if (!c->error.isEmpty()) { - profile->full_test_report = c->error; - profile->Save(); - auto profileId = profile->id; - runOnUiThread([this, profileId] { - refresh_proxy_list(profileId); - }); - continue; - } - // - if (!c->extRs.empty()) { - runOnUiThread( - [&] { - extCs = CreateExtCFromExtR(c->extRs, true); - QThread::msleep(500); - extSem.release(); - }, - DS_cores); - extSem.acquire(); - } - // - auto config = new libcore::LoadConfigReq; - config->set_core_config(QJsonObject2QString(c->coreConfig, false).toStdString()); - req.set_allocated_config(config); - req.set_in_address(profile->bean->serverAddress.toStdString()); - - req.set_full_latency(full_test_flags.contains("1")); - req.set_full_udp_latency(full_test_flags.contains("2")); - req.set_full_speed(full_test_flags.contains("3")); - req.set_full_in_out(full_test_flags.contains("4")); - - req.set_full_speed_url(NekoGui::dataStore->test_download_url.toStdString()); - req.set_full_speed_timeout(NekoGui::dataStore->test_download_timeout); - } else if (mode == libcore::TcpPing) { - req.set_address(profile->bean->DisplayAddress().toStdString()); - } - - bool rpcOK; - auto result = defaultClient->Test(&rpcOK, req); - // - if (!extCs.empty()) { - runOnUiThread( - [&] { - for (const auto &extC: extCs) { - extC->Kill(); - } - extSem.release(); - }, - DS_cores); - extSem.acquire(); - } - // - if (!rpcOK) return; - - if (result.error().empty()) { - profile->latency = result.ms(); - if (profile->latency == 0) profile->latency = 1; // nekoray use 0 to represents not tested - } else { - profile->latency = -1; - } - profile->full_test_report = result.full_report().c_str(); // higher priority - profile->Save(); - - if (!result.error().empty()) { - MW_show_log(tr("[%1] test error: %2").arg(profile->bean->DisplayTypeAndName(), result.error().c_str())); - } - - auto profileId = profile->id; - runOnUiThread([this, profileId] { - refresh_proxy_list(profileId); - }); - } - }); - } - - // Control - lock_return.lock(); - lock_return.unlock(); - speedtesting = false; - MW_show_log(QObject::tr("Speedtest finished.")); - }); -#endif -} - -void MainWindow::speedtest_current() { -#ifndef NKR_NO_GRPC - last_test_time = QTime::currentTime(); - ui->label_running->setText(tr("Testing")); - - runOnNewThread([=] { - libcore::TestReq req; - req.set_mode(libcore::UrlTest); - req.set_timeout(10 * 1000); - req.set_url(NekoGui::dataStore->test_latency_url.toStdString()); - - bool rpcOK; - auto result = defaultClient->Test(&rpcOK, req); - if (!rpcOK) return; - - auto latency = result.ms(); - last_test_time = QTime::currentTime(); - - runOnUiThread([=] { - if (!result.error().empty()) { - MW_show_log(QStringLiteral("UrlTest error: %1").arg(result.error().c_str())); - } - if (latency <= 0) { - ui->label_running->setText(tr("Test Result") + ": " + tr("Unavailable")); - } else if (latency > 0) { - ui->label_running->setText(tr("Test Result") + ": " + QStringLiteral("%1 ms").arg(latency)); - } - }); - }); -#endif -} - -void MainWindow::stop_core_daemon() { -#ifndef NKR_NO_GRPC - NekoGui_rpc::defaultClient->Exit(); -#endif -} - -void MainWindow::neko_start(int _id) { - if (NekoGui::dataStore->prepare_exit) return; - - auto ents = get_now_selected_list(); - auto ent = (_id < 0 && !ents.isEmpty()) ? ents.first() : NekoGui::profileManager->GetProfile(_id); - if (ent == nullptr) return; - - if (select_mode) { - emit profile_selected(ent->id); - select_mode = false; - refresh_status(); - return; - } - - auto group = NekoGui::profileManager->GetGroup(ent->gid); - if (group == nullptr || group->archive) return; - - auto result = BuildConfig(ent, false, false); - if (!result->error.isEmpty()) { - MessageBoxWarning("BuildConfig return error", result->error); - return; - } - - auto neko_start_stage2 = [=] { -#ifndef NKR_NO_GRPC - libcore::LoadConfigReq req; - req.set_core_config(QJsonObject2QString(result->coreConfig, false).toStdString()); - req.set_enable_nekoray_connections(NekoGui::dataStore->connection_statistics); - if (NekoGui::dataStore->traffic_loop_interval > 0) { - req.add_stats_outbounds("proxy"); - req.add_stats_outbounds("bypass"); - } - // - bool rpcOK; - QString error = defaultClient->Start(&rpcOK, req); - if (rpcOK && !error.isEmpty()) { - runOnUiThread([=] { MessageBoxWarning("LoadConfig return error", error); }); - return false; - } else if (!rpcOK) { - return false; - } - // - NekoGui_traffic::trafficLooper->proxy = result->outboundStat.get(); - NekoGui_traffic::trafficLooper->items = result->outboundStats; - NekoGui::dataStore->ignoreConnTag = result->ignoreConnTag; - NekoGui_traffic::trafficLooper->loop_enabled = true; -#endif - - runOnUiThread( - [=] { - auto extCs = CreateExtCFromExtR(result->extRs, true); - NekoGui_sys::running_ext.splice(NekoGui_sys::running_ext.end(), extCs); - }, - DS_cores); - - NekoGui::dataStore->UpdateStartedId(ent->id); - running = ent; - - runOnUiThread([=] { - refresh_status(); - refresh_proxy_list(ent->id); - }); - - return true; - }; - - if (!mu_starting.tryLock()) { - MessageBoxWarning(software_name, "Another profile is starting..."); - return; - } - if (!mu_stopping.tryLock()) { - MessageBoxWarning(software_name, "Another profile is stopping..."); - mu_starting.unlock(); - return; - } - mu_stopping.unlock(); - - // check core state - if (!NekoGui::dataStore->core_running) { - runOnUiThread( - [=] { - MW_show_log("Try to start the config, but the core has not listened to the grpc port, so restart it..."); - core_process->start_profile_when_core_is_up = ent->id; - core_process->Restart(); - }, - DS_cores); - mu_starting.unlock(); - return; // let CoreProcess call neko_start when core is up - } - - // timeout message - auto restartMsgbox = new QMessageBox(QMessageBox::Question, software_name, tr("If there is no response for a long time, it is recommended to restart the software."), - QMessageBox::Yes | QMessageBox::No, this); - connect(restartMsgbox, &QMessageBox::accepted, this, [=] { MW_dialog_message("", "RestartProgram"); }); - auto restartMsgboxTimer = new MessageBoxTimer(this, restartMsgbox, 5000); - - runOnNewThread([=] { - // stop current running - if (NekoGui::dataStore->started_id >= 0) { - runOnUiThread([=] { neko_stop(false, true); }); - sem_stopped.acquire(); - } - // do start - MW_show_log(">>>>>>>> " + tr("Starting profile %1").arg(ent->bean->DisplayTypeAndName())); - if (!neko_start_stage2()) { - MW_show_log("<<<<<<<< " + tr("Failed to start profile %1").arg(ent->bean->DisplayTypeAndName())); - } - mu_starting.unlock(); - // cancel timeout - runOnUiThread([=] { - restartMsgboxTimer->cancel(); - restartMsgboxTimer->deleteLater(); - restartMsgbox->deleteLater(); -#ifdef Q_OS_LINUX - // Check systemd-resolved - if (NekoGui::dataStore->spmode_vpn && NekoGui::dataStore->routing->direct_dns.startsWith("local") && ReadFileText("/etc/resolv.conf").contains("systemd-resolved")) { - MW_show_log("[Warning] The default Direct DNS may not works with systemd-resolved, you may consider change your DNS settings."); - } -#endif - }); - }); -} - -void MainWindow::neko_stop(bool crash, bool sem) { - auto id = NekoGui::dataStore->started_id; - if (id < 0) { - if (sem) sem_stopped.release(); - return; - } - - auto neko_stop_stage2 = [=] { - runOnUiThread( - [=] { - while (!NekoGui_sys::running_ext.empty()) { - auto extC = NekoGui_sys::running_ext.front(); - extC->Kill(); - NekoGui_sys::running_ext.pop_front(); - } - }, - DS_cores); - -#ifndef NKR_NO_GRPC - NekoGui_traffic::trafficLooper->loop_enabled = false; - NekoGui_traffic::trafficLooper->loop_mutex.lock(); - if (NekoGui::dataStore->traffic_loop_interval != 0) { - NekoGui_traffic::trafficLooper->UpdateAll(); - for (const auto &item: NekoGui_traffic::trafficLooper->items) { - NekoGui::profileManager->GetProfile(item->id)->Save(); - runOnUiThread([=] { refresh_proxy_list(item->id); }); - } - } - NekoGui_traffic::trafficLooper->loop_mutex.unlock(); - - if (!crash) { - bool rpcOK; - QString error = defaultClient->Stop(&rpcOK); - if (rpcOK && !error.isEmpty()) { - runOnUiThread([=] { MessageBoxWarning("Stop return error", error); }); - return false; - } else if (!rpcOK) { - return false; - } - } -#endif - - NekoGui::dataStore->UpdateStartedId(-1919); - NekoGui::dataStore->need_keep_vpn_off = false; - running = nullptr; - - runOnUiThread([=] { - refresh_status(); - refresh_proxy_list(id); - }); - - return true; - }; - - if (!mu_stopping.tryLock()) { - if (sem) sem_stopped.release(); - return; - } - - // timeout message - auto restartMsgbox = new QMessageBox(QMessageBox::Question, software_name, tr("If there is no response for a long time, it is recommended to restart the software."), - QMessageBox::Yes | QMessageBox::No, this); - connect(restartMsgbox, &QMessageBox::accepted, this, [=] { MW_dialog_message("", "RestartProgram"); }); - auto restartMsgboxTimer = new MessageBoxTimer(this, restartMsgbox, 5000); - - runOnNewThread([=] { - // do stop - MW_show_log(">>>>>>>> " + tr("Stopping profile %1").arg(running->bean->DisplayTypeAndName())); - if (!neko_stop_stage2()) { - MW_show_log("<<<<<<<< " + tr("Failed to stop, please restart the program.")); - } - mu_stopping.unlock(); - if (sem) sem_stopped.release(); - // cancel timeout - runOnUiThread([=] { - restartMsgboxTimer->cancel(); - restartMsgboxTimer->deleteLater(); - restartMsgbox->deleteLater(); - }); - }); -} - -void MainWindow::CheckUpdate() { - // on new thread... -#ifndef NKR_NO_GRPC - bool ok; - libcore::UpdateReq request; - request.set_action(libcore::UpdateAction::Check); - request.set_check_pre_release(NekoGui::dataStore->check_include_pre); - auto response = NekoGui_rpc::defaultClient->Update(&ok, request); - if (!ok) return; - - auto err = response.error(); - if (!err.empty()) { - runOnUiThread([=] { - MessageBoxWarning(QObject::tr("Update"), err.c_str()); - }); - return; - } - - if (response.release_download_url() == nullptr) { - runOnUiThread([=] { - MessageBoxInfo(QObject::tr("Update"), QObject::tr("No update")); - }); - return; - } - - runOnUiThread([=] { - auto allow_updater = !NekoGui::dataStore->flag_use_appdata; - auto note_pre_release = response.is_pre_release() ? " (Pre-release)" : ""; - QMessageBox box(QMessageBox::Question, QObject::tr("Update") + note_pre_release, - QObject::tr("Update found: %1\nRelease note:\n%2").arg(response.assets_name().c_str(), response.release_note().c_str())); - // - QAbstractButton *btn1 = nullptr; - if (allow_updater) { - btn1 = box.addButton(QObject::tr("Update"), QMessageBox::AcceptRole); - } - QAbstractButton *btn2 = box.addButton(QObject::tr("Open in browser"), QMessageBox::AcceptRole); - box.addButton(QObject::tr("Close"), QMessageBox::RejectRole); - box.exec(); - // - if (btn1 == box.clickedButton() && allow_updater) { - // Download Update - runOnNewThread([=] { - bool ok2; - libcore::UpdateReq request2; - request2.set_action(libcore::UpdateAction::Download); - auto response2 = NekoGui_rpc::defaultClient->Update(&ok2, request2); - runOnUiThread([=] { - if (response2.error().empty()) { - auto q = QMessageBox::question(nullptr, QObject::tr("Update"), - QObject::tr("Update is ready, restart to install?")); - if (q == QMessageBox::StandardButton::Yes) { - this->exit_reason = 1; - on_menu_exit_triggered(); - } - } else { - MessageBoxWarning(QObject::tr("Update"), response2.error().c_str()); - } - }); - }); - } else if (btn2 == box.clickedButton()) { - QDesktopServices::openUrl(QUrl(response.release_url().c_str())); - } - }); -#endif -} diff --git a/ui/mainwindow_interface.h b/ui/mainwindow_interface.h deleted file mode 100644 index 27157de..0000000 --- a/ui/mainwindow_interface.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#define MW_INTERFACE - -#include "mainwindow.h" diff --git a/ui/widget/FloatCheckBox.h b/ui/widget/FloatCheckBox.h deleted file mode 100644 index 98ca3bd..0000000 --- a/ui/widget/FloatCheckBox.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include -#include - -class FloatCheckBox : public QCheckBox { -public: - QWidget *parent; - QWidget *window; - - void refresh() { - setFixedSize(24, 24); - auto pos = parent->rect().topRight(); - pos = parent->mapTo(window, pos); - pos.setX(pos.x() - 48); // ? - move(pos); - raise(); - setVisible(parent->isVisible()); - }; - - bool eventFilter(QObject *obj, QEvent *e) override { - if (obj != window || e->type() != QEvent::Resize) return false; - refresh(); - return false; - }; - - explicit FloatCheckBox(QWidget *parent, QWidget *window) : QCheckBox(window) { - this->parent = parent; - this->window = window; - window->installEventFilter(this); - refresh(); - }; -}; diff --git a/ui/widget/GroupItem.cpp b/ui/widget/GroupItem.cpp deleted file mode 100644 index d3ff39d..0000000 --- a/ui/widget/GroupItem.cpp +++ /dev/null @@ -1,126 +0,0 @@ -#include "GroupItem.h" -#include "ui_GroupItem.h" - -#include "ui/edit/dialog_edit_group.h" -#include "main/GuiUtils.hpp" -#include "sub/GroupUpdater.hpp" - -#include - -QString ParseSubInfo(const QString &info) { - if (info.trimmed().isEmpty()) return ""; - - QString result; - - long long used = 0; - long long total = 0; - long long expire = 0; - - auto re0m = QRegularExpression("total=([0-9]+)").match(info); - if (re0m.lastCapturedIndex() >= 1) { - total = re0m.captured(1).toLongLong(); - } else { - return ""; - } - auto re1m = QRegularExpression("upload=([0-9]+)").match(info); - if (re1m.lastCapturedIndex() >= 1) { - used += re1m.captured(1).toLongLong(); - } - auto re2m = QRegularExpression("download=([0-9]+)").match(info); - if (re2m.lastCapturedIndex() >= 1) { - used += re2m.captured(1).toLongLong(); - } - auto re3m = QRegularExpression("expire=([0-9]+)").match(info); - if (re3m.lastCapturedIndex() >= 1) { - expire = re3m.captured(1).toLongLong(); - } - - result = QObject::tr("Used: %1 Remain: %2 Expire: %3") - .arg(ReadableSize(used), ReadableSize(total - used), DisplayTime(expire, QLocale::ShortFormat)); - - return result; -} - -GroupItem::GroupItem(QWidget *parent, const std::shared_ptr &ent, QListWidgetItem *item) : QWidget(parent), ui(new Ui::GroupItem) { - ui->setupUi(this); - this->setLayoutDirection(Qt::LeftToRight); - - this->parentWindow = parent; - this->ent = ent; - this->item = item; - if (ent == nullptr) return; - - connect(this, &GroupItem::edit_clicked, this, &GroupItem::on_edit_clicked); - connect(NekoGui_sub::groupUpdater, &NekoGui_sub::GroupUpdater::asyncUpdateCallback, this, [=](int gid) { if (gid == this->ent->id) refresh_data(); }); - - refresh_data(); -} - -GroupItem::~GroupItem() { - delete ui; -} - -void GroupItem::refresh_data() { - ui->name->setText(ent->name); - - auto type = ent->url.isEmpty() ? tr("Basic") : tr("Subscription"); - if (ent->archive) type = tr("Archive") + " " + type; - type += " (" + Int2String(ent->Profiles().length()) + ")"; - ui->type->setText(type); - - if (ent->url.isEmpty()) { - ui->url->hide(); - ui->subinfo->hide(); - ui->update_sub->hide(); - } else { - ui->url->setText(ent->url); - QStringList info; - if (ent->sub_last_update != 0) { - info << tr("Last update: %1").arg(DisplayTime(ent->sub_last_update, QLocale::ShortFormat)); - } - auto subinfo = ParseSubInfo(ent->info); - if (!ent->info.isEmpty()) { - info << subinfo; - } - if (info.isEmpty()) { - ui->subinfo->hide(); - } else { - ui->subinfo->show(); - ui->subinfo->setText(info.join(" | ")); - } - } - runOnUiThread( - [=] { - adjustSize(); - item->setSizeHint(sizeHint()); - dynamic_cast(parent())->adjustSize(); - }, - this); -} - -void GroupItem::on_update_sub_clicked() { - NekoGui_sub::groupUpdater->AsyncUpdate(ent->url, ent->id); -} - -void GroupItem::on_edit_clicked() { - auto dialog = new DialogEditGroup(ent, parentWindow); - connect(dialog, &QDialog::finished, this, [=] { - if (dialog->result() == QDialog::Accepted) { - ent->Save(); - refresh_data(); - MW_dialog_message(Dialog_DialogManageGroups, "refresh" + Int2String(ent->id)); - } - dialog->deleteLater(); - }); - dialog->show(); -} - -void GroupItem::on_remove_clicked() { - if (NekoGui::profileManager->groups.size() <= 1) return; - if (QMessageBox::question(this, tr("Confirmation"), tr("Remove %1?").arg(ent->name)) == - QMessageBox::StandardButton::Yes) { - NekoGui::profileManager->DeleteGroup(ent->id); - MW_dialog_message(Dialog_DialogManageGroups, "refresh-1"); - delete item; - } -} diff --git a/ui/widget/GroupItem.h b/ui/widget/GroupItem.h deleted file mode 100644 index 14aa864..0000000 --- a/ui/widget/GroupItem.h +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -#include -#include - -#include "db/Database.hpp" - -QT_BEGIN_NAMESPACE -namespace Ui { - class GroupItem; -} -QT_END_NAMESPACE - -class GroupItem : public QWidget { - Q_OBJECT - -public: - explicit GroupItem(QWidget *parent, const std::shared_ptr &ent, QListWidgetItem *item); - - ~GroupItem() override; - - void refresh_data(); - - std::shared_ptr ent; - QListWidgetItem *item; - -private: - Ui::GroupItem *ui; - - QWidget *parentWindow; - -signals: - - void edit_clicked(); - -private slots: - - void on_update_sub_clicked(); - - void on_edit_clicked(); - - void on_remove_clicked(); -}; diff --git a/ui/widget/GroupItem.ui b/ui/widget/GroupItem.ui deleted file mode 100644 index fd2f77f..0000000 --- a/ui/widget/GroupItem.ui +++ /dev/null @@ -1,128 +0,0 @@ - - - GroupItem - - - - 0 - 0 - 403 - 300 - - - - - 0 - 0 - - - - - - - - - - - - - 0 - 0 - - - - color: rgb(251, 114, 153); - - - Type - - - - - - - - 0 - 0 - - - - Name - - - - - - - - 0 - 0 - - - - Update Subscription - - - - - - - - 0 - 0 - - - - Edit - - - - - - - - 0 - 0 - - - - Remove - - - - - - - - - - 0 - 0 - - - - color: rgb(102, 102, 102); - - - Url - - - - - - - - 0 - 0 - - - - 订阅流量信息 - - - - - - - - diff --git a/ui/widget/MessageBoxTimer.h b/ui/widget/MessageBoxTimer.h deleted file mode 100644 index 7258770..0000000 --- a/ui/widget/MessageBoxTimer.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include -#include - -class MessageBoxTimer : public QTimer { -public: - QMessageBox *msgbox = nullptr; - bool showed = false; - - explicit MessageBoxTimer(QObject *parent, QMessageBox *msgbox, int delayMs) : QTimer(parent) { - connect(this, &QTimer::timeout, this, &MessageBoxTimer::timeoutFunc, Qt::ConnectionType::QueuedConnection); - this->msgbox = msgbox; - setSingleShot(true); - setInterval(delayMs); - start(); - }; - - void cancel() { - QTimer::stop(); - if (msgbox != nullptr && showed) { - msgbox->reject(); // return the timeoutFunc - } - }; - -private: - void timeoutFunc() { - if (msgbox == nullptr) return; - showed = true; - msgbox->exec(); - msgbox = nullptr; - } -}; diff --git a/ui/widget/MyLineEdit.h b/ui/widget/MyLineEdit.h deleted file mode 100644 index 90dee9e..0000000 --- a/ui/widget/MyLineEdit.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include - -class MyLineEdit : public QLineEdit { -public slots: - - explicit MyLineEdit(QWidget *parent = nullptr) : QLineEdit(parent) { - } - - void setText(const QString &s) { - QLineEdit::setText(s); - QLineEdit::home(false); - } -}; diff --git a/ui/widget/MyTableWidget.h b/ui/widget/MyTableWidget.h deleted file mode 100644 index ff86256..0000000 --- a/ui/widget/MyTableWidget.h +++ /dev/null @@ -1,110 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -class MyTableWidget : public QTableWidget { -public: - explicit MyTableWidget(QWidget *parent = nullptr) : QTableWidget(parent) { - // 拖拽设置 - this->setDragDropMode(QAbstractItemView::InternalMove); // 内部移动 - this->setDropIndicatorShown(true); // drop位置 提示 - this->setSelectionBehavior(QAbstractItemView::SelectRows); - }; - - QList order; // id sorted (save) - std::map id2Row; // id2Row - QList row2Id; // row2Id: use this to refresh data - - std::function callback_save_order; - std::function refresh_data; - - void _save_order(bool saveToFile) { - order.clear(); - id2Row.clear(); - for (int i = 0; i < this->rowCount(); i++) { - auto id = row2Id[i]; - order += id; - id2Row[id] = i; - } - if (callback_save_order != nullptr && saveToFile) - callback_save_order(); - } - - void update_order(bool saveToFile) { - if (order.isEmpty()) { - _save_order(false); - return; - } - - // 纠错: order 里面含有不在当前表格控件的 id - bool needSave = false; - auto deleted_profiles = order; - for (int i = 0; i < this->rowCount(); i++) { - auto id = row2Id[i]; - deleted_profiles.removeAll(id); - } - for (auto deleted_profile: deleted_profiles) { - needSave = true; - order.removeAll(deleted_profile); - } - - // map(dstRow -> srcId) - QMap newRows; - for (int i = 0; i < this->rowCount(); i++) { - auto id = row2Id[i]; - auto dst = order.indexOf(id); - if (dst == i) continue; - if (dst == -1) { - // 纠错: 新的profile不需要移动 - needSave = true; - continue; - } - newRows[dst] = id; - } - - for (int i = 0; i < this->rowCount(); i++) { - if (!newRows.contains(i)) continue; - row2Id[i] = newRows[i]; - } - - // Then save the order - _save_order(needSave || saveToFile); - }; - -protected: - /* - * 2021.7.6 by gy - * 拖拽 继承QTableWidget overwrite dropEvent事件 - * 功能:拖动一行到鼠标落下的位置 - * 注意:DragDropMode相关参数的设置 - */ - void dropEvent(QDropEvent *event) override { - if (order.isEmpty()) order = row2Id; - - // 原行号与目标行号的确定 - int row_src, row_dst; - row_src = this->currentRow(); // 原行号 可加if - auto id_src = row2Id[row_src]; // id_src - QTableWidgetItem *item = this->itemAt(event->pos()); // 获取落点的item - if (item != nullptr) { - // 判断是否为空 - row_dst = item->row(); // 不为空 获取其行号 - // Modify order - order.removeAt(row_src); - order.insert(row_dst, id_src); - } else { - // 落点没有item 说明拖动到了最下面 - return; - } - - // Do update order & refresh - clearSelection(); - update_order(true); - refresh_data(-1); - }; -}; diff --git a/ui/widget/ProxyItem.cpp b/ui/widget/ProxyItem.cpp deleted file mode 100644 index f8c1587..0000000 --- a/ui/widget/ProxyItem.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "ProxyItem.h" -#include "ui_ProxyItem.h" - -#include - -ProxyItem::ProxyItem(QWidget *parent, const std::shared_ptr &ent, QListWidgetItem *item) - : QWidget(parent), ui(new Ui::ProxyItem) { - ui->setupUi(this); - this->setLayoutDirection(Qt::LeftToRight); - - this->item = item; - this->ent = ent; - if (ent == nullptr) return; - - refresh_data(); -} - -ProxyItem::~ProxyItem() { - delete ui; -} - -void ProxyItem::refresh_data() { - ui->type->setText(ent->bean->DisplayType()); - ui->name->setText(ent->bean->DisplayName()); - ui->address->setText(ent->bean->DisplayAddress()); - ui->traffic->setText(ent->traffic_data->DisplayTraffic()); - ui->test_result->setText(ent->DisplayLatency()); - - runOnUiThread( - [=] { - adjustSize(); - item->setSizeHint(sizeHint()); - dynamic_cast(parent())->adjustSize(); - }, - this); -} - -void ProxyItem::on_remove_clicked() { - if (!this->remove_confirm || - QMessageBox::question(this, tr("Confirmation"), tr("Remove %1?").arg(ent->bean->DisplayName())) == QMessageBox::StandardButton::Yes) { - // TODO do remove (or not) -> callback - delete item; - } -} - -QPushButton *ProxyItem::get_change_button() { - return ui->change; -} diff --git a/ui/widget/ProxyItem.h b/ui/widget/ProxyItem.h deleted file mode 100644 index ac8058f..0000000 --- a/ui/widget/ProxyItem.h +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include -#include - -#include "db/ProxyEntity.hpp" - -QT_BEGIN_NAMESPACE -namespace Ui { - class ProxyItem; -} -QT_END_NAMESPACE - -class QPushButton; - -class ProxyItem : public QWidget { - Q_OBJECT - -public: - explicit ProxyItem(QWidget *parent, const std::shared_ptr &ent, QListWidgetItem *item); - - ~ProxyItem() override; - - void refresh_data(); - - QPushButton *get_change_button(); - - std::shared_ptr ent; - QListWidgetItem *item; - bool remove_confirm = false; - -private: - Ui::ProxyItem *ui; - -private slots: - - void on_remove_clicked(); -}; diff --git a/ui/widget/ProxyItem.ui b/ui/widget/ProxyItem.ui deleted file mode 100644 index 351dbae..0000000 --- a/ui/widget/ProxyItem.ui +++ /dev/null @@ -1,146 +0,0 @@ - - - ProxyItem - - - - 0 - 0 - 400 - 300 - - - - - 0 - 0 - - - - - - - - - - - - - 0 - 0 - - - - 名称 - - - - - - - - 0 - 0 - - - - - :/icon/material/swap-horizontal.svg:/icon/material/swap-horizontal.svg - - - - - - - - 0 - 0 - - - - - :/icon/material/delete.svg:/icon/material/delete.svg - - - - - - - - - - - - 0 - 0 - - - - color: rgb(102, 102, 102); - - - 地址 - - - - - - - - 0 - 0 - - - - 测试结果 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - 0 - 0 - - - - color: rgb(251, 114, 153); - - - 类型 - - - - - - - - 0 - 0 - - - - 流量 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - -