diff --git a/app/vpn/wireguardconfig.cpp b/app/vpn/wireguardconfig.cpp new file mode 100644 index 0000000..61218e8 --- /dev/null +++ b/app/vpn/wireguardconfig.cpp @@ -0,0 +1,89 @@ +// wireguardconfig.cpp + +#include "wireguardconfig.h" + +// ─── Factory ────────────────────────────────────────────────────────────────── + +WireGuardConfig WireGuardConfig::fromConf(const QString &conf) +{ + WireGuardConfig cfg; + QString section; + + for (const QString &rawLine : conf.split(QLatin1Char('\n'))) { + const QString line = rawLine.trimmed(); + if (line.isEmpty() || line.startsWith(QLatin1Char('#'))) + continue; + + // Section header: [Interface] or [Peer] + if (line.startsWith(QLatin1Char('['))) { + const int close = line.indexOf(QLatin1Char(']')); + section = (close > 1) ? line.mid(1, close - 1).toLower() : QString(); + continue; + } + + const int eq = line.indexOf(QLatin1Char('=')); + if (eq < 1) continue; + + const QString key = line.left(eq).trimmed().toLower(); + const QString val = line.mid(eq + 1).trimmed(); + + if (section == QLatin1String("interface")) { + if (key == QLatin1String("privatekey")) cfg.privateKey = val; + else if (key == QLatin1String("address")) cfg.address = val; + else if (key == QLatin1String("dns")) cfg.dns = val; + + } else if (section == QLatin1String("peer")) { + if (key == QLatin1String("publickey")) cfg.peerPublicKey = val; + else if (key == QLatin1String("presharedkey")) cfg.presharedKey = val; + else if (key == QLatin1String("endpoint")) cfg.endpoint = val; + else if (key == QLatin1String("allowedips")) { + cfg.allowedIPs.clear(); + for (const QString &part : val.split(QLatin1Char(','))) + cfg.allowedIPs << part.trimmed(); + } + else if (key == QLatin1String("persistentkeepalive")) + cfg.persistentKeepalive = static_cast(val.toUInt()); + } + } + + return cfg; +} + +// ─── Helpers ────────────────────────────────────────────────────────────────── + +QString WireGuardConfig::endpointHost() const +{ + // Handle IPv6 [::1]:port notation + if (endpoint.startsWith(QLatin1Char('['))) { + const int close = endpoint.indexOf(QLatin1Char(']')); + if (close > 0) return endpoint.mid(1, close - 1); + } + const int colon = endpoint.lastIndexOf(QLatin1Char(':')); + return (colon > 0) ? endpoint.left(colon) : endpoint; +} + +quint16 WireGuardConfig::endpointPort() const +{ + if (endpoint.startsWith(QLatin1Char('['))) { + const int bracketClose = endpoint.indexOf(QLatin1Char(']')); + const int colon = endpoint.indexOf(QLatin1Char(':'), bracketClose); + if (colon > 0) return static_cast(endpoint.mid(colon + 1).toUInt()); + return 51820; + } + const int colon = endpoint.lastIndexOf(QLatin1Char(':')); + return (colon > 0) ? static_cast(endpoint.mid(colon + 1).toUInt()) : 51820; +} + +QString WireGuardConfig::localIP() const +{ + const int slash = address.indexOf(QLatin1Char('/')); + return (slash > 0) ? address.left(slash) : address; +} + +bool WireGuardConfig::isValid() const +{ + return !privateKey.isEmpty() + && !peerPublicKey.isEmpty() + && !endpoint.isEmpty() + && !address.isEmpty(); +}