add: added SIP008 subscription support

This commit is contained in:
QxQ 2020-09-25 19:38:24 +08:00
parent 21bf0fd27e
commit eb2a1284bc
3 changed files with 104 additions and 22 deletions

View File

@ -1 +1 @@
5939
5940

View File

@ -1 +1,77 @@
#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;
}

View File

@ -2,6 +2,8 @@
#include "CommonTypes.hpp"
#include "QvPluginProcessor.hpp"
using namespace Qv2rayPlugin;
const inline QStringList SplitLines(const QString &_string)
{
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
@ -13,43 +15,47 @@ const inline QStringList SplitLines(const QString &_string)
#endif
}
class BuiltinSerializer : public Qv2rayPlugin::SubscriptionDecoder
class SimpleBase64Decoder : public Qv2rayPlugin::SubscriptionDecoder
{
public:
explicit BuiltinSerializer() : Qv2rayPlugin::SubscriptionDecoder(){};
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();
const auto resultList = source.contains("://") ? source : SafeBase64Decode(source);
//
SubscriptionDecodeResult result;
result.links = SplitLines(resultList);
return result;
}
explicit SimpleBase64Decoder() : SubscriptionDecoder(){};
SubscriptionDecodeResult DecodeData(const QByteArray &data) const override;
};
class BuiltinSubscriptionAdapterInterface : public Qv2rayPlugin::SubscriptionInterface
class SIP008Decoder : public Qv2rayPlugin::SubscriptionDecoder
{
public:
explicit BuiltinSubscriptionAdapterInterface() : Qv2rayPlugin::SubscriptionInterface()
explicit SIP008Decoder() : SubscriptionDecoder(){};
SubscriptionDecodeResult DecodeData(const QByteArray &data) const override;
};
class BuiltinSubscriptionAdapterInterface : public SubscriptionInterface
{
public:
explicit BuiltinSubscriptionAdapterInterface() : SubscriptionInterface()
{
simple_base64 = std::make_shared<BuiltinSerializer>();
simple_base64 = std::make_shared<SimpleBase64Decoder>();
sip008 = std::make_shared<SIP008Decoder>();
}
QList<Qv2rayPlugin::ProtocolInfoObject> SupportedSubscriptionTypes() const override
{
// "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
{
if (type == "simple_base64")
return simple_base64;
if (type == "sip008")
return sip008;
return nullptr;
}
std::shared_ptr<Qv2rayPlugin::SubscriptionDecoder> simple_base64;
std::shared_ptr<SubscriptionDecoder> simple_base64;
std::shared_ptr<SubscriptionDecoder> sip008;
};