Qv2ray/src/core/connection/Serialization.cpp

129 lines
5.5 KiB
C++

#include "Serialization.hpp"
#include "Generation.hpp"
#include "common/QvHelpers.hpp"
#include "components/plugins/QvPluginHost.hpp"
#include "core/CoreUtils.hpp"
#include "core/handler/ConfigHandler.hpp"
namespace Qv2ray::core::connection
{
namespace Serialization
{
QMultiHash<QString, CONFIGROOT> ConvertConfigFromString(const QString &link, QString *prefix, QString *errMessage, QString *newGroupName)
{
QMultiHash<QString, CONFIGROOT> connectionConf;
if (link.startsWith("vmess://"))
{
auto conf = ConvertConfigFromVMessString(link, prefix, errMessage);
//
if (GlobalConfig.advancedConfig.setAllowInsecureCiphers || GlobalConfig.advancedConfig.setAllowInsecure)
{
auto outbound = conf["outbounds"].toArray().first().toObject();
auto streamSettings = outbound["streamSettings"].toObject();
auto tlsSettings = streamSettings["tlsSettings"].toObject();
tlsSettings["allowInsecure"] = GlobalConfig.advancedConfig.setAllowInsecure;
tlsSettings["allowInsecureCiphers"] = GlobalConfig.advancedConfig.setAllowInsecureCiphers;
streamSettings["tlsSettings"] = tlsSettings;
outbound["streamSettings"] = streamSettings;
//
auto outbounds = conf["outbounds"].toArray();
outbounds[0] = outbound;
conf["outbounds"] = outbounds;
}
//
connectionConf.insert(*prefix, conf);
}
else if (link.startsWith("ss://"))
{
auto conf = ConvertConfigFromSSString(link, prefix, errMessage);
connectionConf.insert(*prefix, conf);
}
else if (link.startsWith("ssd://"))
{
QStringList errMessageList;
connectionConf = ConvertConfigFromSSDString(link, newGroupName, &errMessageList);
*errMessage = errMessageList.join(NEWLINE);
}
else
{
bool ok = false;
auto configs = PluginHost->TryDeserializeShareLink(link, prefix, errMessage, newGroupName, &ok);
for (const auto &key : configs.keys())
{
auto vals = configs.values(key);
for (const auto &val : vals)
{
CONFIGROOT root;
auto outbound = GenerateOutboundEntry(val.first, OUTBOUNDSETTING(val.second), {});
root.insert("outbounds", QJsonArray{ outbound });
connectionConf.insert(key, root);
}
}
if (!ok)
{
*errMessage = QObject::tr("Unsupported share link format.");
}
}
return connectionConf;
}
const QString ConvertConfigToString(const ConnectionId &id, bool isSip002)
{
auto alias = GetDisplayName(id);
if (IsComplexConfig(id))
{
DEBUG(MODULE_CONNECTION, "Ignored an complex config: " + alias)
return QV2RAY_SERIALIZATION_COMPLEX_CONFIG_PLACEHOLDER;
}
auto server = ConnectionManager->GetConnectionRoot(id);
return ConvertConfigToString(alias, GetDisplayName(GetConnectionGroupId(id)), server, isSip002);
}
const QString ConvertConfigToString(const QString &alias, const QString &groupName, const CONFIGROOT &server, bool isSip002)
{
const auto outbound = OUTBOUND(server["outbounds"].toArray().first().toObject());
const auto type = outbound["protocol"].toString();
const auto &settings = outbound["settings"].toObject();
QString sharelink = "";
if (type == "vmess")
{
auto vmessServer = VMessServerObject::fromJson(settings["vnext"].toArray().first().toObject());
auto transport = StreamSettingsObject::fromJson(outbound["streamSettings"].toObject());
sharelink = vmess::ConvertConfigToVMessString(transport, vmessServer, alias);
}
else if (type == "shadowsocks")
{
auto ssServer = ShadowSocksServerObject::fromJson(settings["servers"].toArray().first().toObject());
sharelink = ss::ConvertConfigToSSString(ssServer, alias, isSip002);
}
else
{
if (type.isEmpty())
{
DEBUG(MODULE_CONNECTION, "WARNING: Empty outbound type.")
}
else
{
bool ok = false;
sharelink = PluginHost->TrySerializeShareLink(type, settings, alias, groupName, &ok);
Q_UNUSED(ok)
}
}
return sharelink;
}
QString DecodeSubscriptionString(const QByteArray &arr)
{
// String may start with: vmess:// and ss://
// We only process vmess:// here
// Some subscription providers may use plain vmess:// saperated by
// lines But others may use base64 of above.
auto result = QString::fromUtf8(arr).trimmed();
return result.contains("://") ? result : Base64Decode(result);
}
} // namespace Serialization
} // namespace Qv2ray::core::connection