XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEWarframe

【WinUI】基于Warframe游戏本体的公开服务器以及安装器

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Security.Cryptography;

namespace XFEWarframe.Client;

public static class ClientProtocol
{
    public static string BuildIdentity(string buildLabel, string cacheManifestHash)
    {
        if (string.IsNullOrWhiteSpace(buildLabel) || buildLabel.Contains('/') || buildLabel.Any(char.IsControl))
            throw new InvalidDataException("Invalid game build label.");
        if (cacheManifestHash.Length is < 16 or > 128 || !cacheManifestHash.All(c => char.IsAsciiLetterOrDigit(c) || c is '-' or '_' or '+' or '='))
            throw new InvalidDataException("The game cache manifest hash is unavailable or invalid.");
        return buildLabel + "/" + cacheManifestHash;
    }

    public static string NormalizeServer(string value)
    {
        if (!Uri.TryCreate(value.Trim(), UriKind.Absolute, out var uri) || uri.Scheme is not ("http" or "https") ||
            uri.UserInfo.Length != 0 || uri.AbsolutePath != "/" || uri.Query.Length != 0 || uri.Fragment.Length != 0)
            throw new ArgumentException("服务器地址必须为 http(s)://主机:端口,不包含账号、路径或查询参数。");
        return uri.GetLeftPart(UriPartial.Authority);
    }
    public static string Redirect(string original, string origin, string buildLabel)
    {
        if (!Uri.TryCreate(original, UriKind.Absolute, out var uri) || uri.Scheme is not ("http" or "https"))
            throw new InvalidDataException("游戏请求不是有效的 HTTP URL。");
        var url = origin + uri.PathAndQuery;
        var separator = uri.Query.Length == 0 ? '?' : '&';
        if (uri.AbsolutePath.EndsWith("/login.php", StringComparison.OrdinalIgnoreCase) ||
            uri.AbsolutePath.EndsWith("/worldState.php", StringComparison.OrdinalIgnoreCase))
            // The game's build identity is version/manifest-hash. A slash is valid
            // query data; keep it literal like the original client bridge because
            // ServerInteractive 4.0.1 rejects encoded slashes even in the query.
            url += separator + "buildLabel=" + Uri.EscapeDataString(buildLabel).Replace("%2F", "/", StringComparison.Ordinal) + "&clientMod=XFEWarframe";
        else if (uri.AbsolutePath.EndsWith("/inventory.php", StringComparison.OrdinalIgnoreCase) ||
                 uri.AbsolutePath.EndsWith("/missionInventoryUpdate.php", StringComparison.OrdinalIgnoreCase))
            url += separator + "xpBasedLevelCapDisabled=1";
        return url;
    }
    public static byte[] DecodeProtected(ReadOnlySpan<byte> body)
    {
        if (body.Length <= 137 || (body.Length - 137) % 16 != 0)
            throw new InvalidDataException("受保护请求长度无效。");
        using var aes = Aes.Create();
        aes.Key = Enumerable.Repeat((byte)'A', 24).ToArray();
        return aes.DecryptCbc(body[137..], Enumerable.Repeat((byte)'A', 16).ToArray(), PaddingMode.PKCS7);
    }
}