mirror of
https://github.com/Qv2ray/Qv2ray.git
synced 2025-05-20 10:50:23 +08:00
add: added SIP008 subscription support
This commit is contained in:
parent
21bf0fd27e
commit
eb2a1284bc
@ -1 +1 @@
|
|||||||
5939
|
5940
|
||||||
|
@ -1 +1,77 @@
|
|||||||
#include "SubscriptionAdapter.hpp"
|
#include "SubscriptionAdapter.hpp"
|
||||||
|
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonValue>
|
||||||
|
#include <QUrl>
|
||||||
|
#include <QUrlQuery>
|
||||||
|
|
||||||
|
QString SafeBase64Decode(QString string)
|
||||||
|
{
|
||||||
|
QByteArray ba = string.replace(QChar('-'), QChar('+')).replace(QChar('_'), QChar('/')).toUtf8();
|
||||||
|
return QByteArray::fromBase64(ba, QByteArray::Base64Option::OmitTrailingEquals);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString SafeBase64Encode(const QString &string)
|
||||||
|
{
|
||||||
|
QString base64 = string.toUtf8().toBase64();
|
||||||
|
return base64.replace(QChar('+'), QChar('-')).replace(QChar('/'), QChar('_'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simple Base64 Decoder
|
||||||
|
SubscriptionDecoder::SubscriptionDecodeResult SimpleBase64Decoder::DecodeData(const QByteArray &data) const
|
||||||
|
{
|
||||||
|
auto source = QString::fromUtf8(data).trimmed();
|
||||||
|
const auto resultList = source.contains("://") ? source : SafeBase64Decode(source);
|
||||||
|
//
|
||||||
|
SubscriptionDecodeResult result;
|
||||||
|
result.links = SplitLines(resultList);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SIP008 Decoder
|
||||||
|
SubscriptionDecoder::SubscriptionDecodeResult SIP008Decoder::DecodeData(const QByteArray &data) const
|
||||||
|
{
|
||||||
|
const auto root = QJsonDocument::fromJson(data).object();
|
||||||
|
//
|
||||||
|
const auto version = root["version"].toString();
|
||||||
|
const auto username = root["username"].toString();
|
||||||
|
const auto user_uuid = root["user_uuid"].toString();
|
||||||
|
const auto servers = root["servers"].toArray();
|
||||||
|
|
||||||
|
// ss://Y2hhY2hhMjAtaWV0Zi1wb2x5MTMwNTpwYXNzQGhvc3Q6MTIzNA/?plugin=plugin%3Bopt#sssip003
|
||||||
|
|
||||||
|
SubscriptionDecodeResult result;
|
||||||
|
#define GetVal(x) const auto x = serverObj[#x].toString()
|
||||||
|
for (const auto &servVal : servers)
|
||||||
|
{
|
||||||
|
const auto serverObj = servVal.toObject();
|
||||||
|
GetVal(server);
|
||||||
|
GetVal(password);
|
||||||
|
GetVal(method);
|
||||||
|
GetVal(plugin);
|
||||||
|
GetVal(plugin_opts);
|
||||||
|
GetVal(remarks);
|
||||||
|
GetVal(id);
|
||||||
|
const auto server_port = serverObj["server_port"].toInt();
|
||||||
|
bool isSIP003 = !plugin.isEmpty();
|
||||||
|
const auto userInfo = SafeBase64Encode(method + ":" + password);
|
||||||
|
//
|
||||||
|
QUrl link;
|
||||||
|
link.setScheme("ss");
|
||||||
|
link.setUserInfo(userInfo);
|
||||||
|
link.setHost(server);
|
||||||
|
link.setPort(server_port);
|
||||||
|
link.setFragment(remarks);
|
||||||
|
if (isSIP003)
|
||||||
|
{
|
||||||
|
QUrlQuery q;
|
||||||
|
q.addQueryItem("plugin", QUrl::toPercentEncoding(plugin + ";" + plugin_opts));
|
||||||
|
link.setQuery(q);
|
||||||
|
}
|
||||||
|
result.links << link.toString(QUrl::FullyEncoded);
|
||||||
|
}
|
||||||
|
#undef GetVal
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
#include "CommonTypes.hpp"
|
#include "CommonTypes.hpp"
|
||||||
#include "QvPluginProcessor.hpp"
|
#include "QvPluginProcessor.hpp"
|
||||||
|
|
||||||
|
using namespace Qv2rayPlugin;
|
||||||
|
|
||||||
const inline QStringList SplitLines(const QString &_string)
|
const inline QStringList SplitLines(const QString &_string)
|
||||||
{
|
{
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||||
@ -13,43 +15,47 @@ const inline QStringList SplitLines(const QString &_string)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
class BuiltinSerializer : public Qv2rayPlugin::SubscriptionDecoder
|
class SimpleBase64Decoder : public Qv2rayPlugin::SubscriptionDecoder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit BuiltinSerializer() : Qv2rayPlugin::SubscriptionDecoder(){};
|
explicit SimpleBase64Decoder() : SubscriptionDecoder(){};
|
||||||
SubscriptionDecodeResult DecodeData(const QByteArray &data) const override
|
SubscriptionDecodeResult DecodeData(const QByteArray &data) const override;
|
||||||
{
|
|
||||||
const static auto SafeBase64Decode = [](QString string) -> QString {
|
|
||||||
QByteArray ba = string.replace(QChar('-'), QChar('+')).replace(QChar('_'), QChar('/')).toUtf8();
|
|
||||||
return QByteArray::fromBase64(ba, QByteArray::Base64Option::OmitTrailingEquals);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
auto source = QString::fromUtf8(data).trimmed();
|
class SIP008Decoder : public Qv2rayPlugin::SubscriptionDecoder
|
||||||
const auto resultList = source.contains("://") ? source : SafeBase64Decode(source);
|
|
||||||
//
|
|
||||||
SubscriptionDecodeResult result;
|
|
||||||
result.links = SplitLines(resultList);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class BuiltinSubscriptionAdapterInterface : public Qv2rayPlugin::SubscriptionInterface
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit BuiltinSubscriptionAdapterInterface() : Qv2rayPlugin::SubscriptionInterface()
|
explicit SIP008Decoder() : SubscriptionDecoder(){};
|
||||||
|
SubscriptionDecodeResult DecodeData(const QByteArray &data) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BuiltinSubscriptionAdapterInterface : public SubscriptionInterface
|
||||||
{
|
{
|
||||||
simple_base64 = std::make_shared<BuiltinSerializer>();
|
public:
|
||||||
|
explicit BuiltinSubscriptionAdapterInterface() : SubscriptionInterface()
|
||||||
|
{
|
||||||
|
simple_base64 = std::make_shared<SimpleBase64Decoder>();
|
||||||
|
sip008 = std::make_shared<SIP008Decoder>();
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<Qv2rayPlugin::ProtocolInfoObject> SupportedSubscriptionTypes() const override
|
QList<Qv2rayPlugin::ProtocolInfoObject> SupportedSubscriptionTypes() const override
|
||||||
{
|
{
|
||||||
// "simple_base64" = magic value in Qv2ray main application
|
// "simple_base64" = magic value in Qv2ray main application
|
||||||
return { Qv2rayPlugin::ProtocolInfoObject{ "simple_base64", "Basic Base64" } };
|
return { //
|
||||||
|
ProtocolInfoObject{ "simple_base64", "Basic Base64" }, //
|
||||||
|
ProtocolInfoObject{ "sip008", "SIP008" }
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Qv2rayPlugin::SubscriptionDecoder> GetSubscriptionDecoder(const QString &type) const override
|
std::shared_ptr<Qv2rayPlugin::SubscriptionDecoder> GetSubscriptionDecoder(const QString &type) const override
|
||||||
{
|
{
|
||||||
if (type == "simple_base64")
|
if (type == "simple_base64")
|
||||||
return simple_base64;
|
return simple_base64;
|
||||||
|
if (type == "sip008")
|
||||||
|
return sip008;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
std::shared_ptr<Qv2rayPlugin::SubscriptionDecoder> simple_base64;
|
|
||||||
|
std::shared_ptr<SubscriptionDecoder> simple_base64;
|
||||||
|
std::shared_ptr<SubscriptionDecoder> sip008;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user