using System.Text; using Microsoft.AspNetCore.Mvc; namespace RadicadeServer.CDN { [Route("cdn/sigs")] public class SigsCDN : Controller { private static readonly byte[] PlaceholderSignature = Encoding.ASCII.GetBytes( "RecRoom.exe:AAAAAAAAAAAAAAAAAAAAAA==:AAAAAAAAAAAAAAAAAAAAAA==\n" + "RecRoom_Data/globalgamemanagers:AAAAAAAAAAAAAAAAAAAAAA==:AAAAAAAAAAAAAAAAAAAAAA==\n" + "GameAssembly.dll:AAAAAAAAAAAAAAAAAAAAAA==:AAAAAAAAAAAAAAAAAAAAAA==\n"); [HttpGet("{signatureId}")] public IActionResult GetSignature(string signatureId) { if (string.IsNullOrWhiteSpace(signatureId)) return BadRequest(); var rangeHeader = ControllerContext.HttpContext?.Request.Headers.Range.ToString(); if (string.IsNullOrWhiteSpace(rangeHeader) || !rangeHeader.StartsWith("bytes=", StringComparison.OrdinalIgnoreCase)) return File(PlaceholderSignature, "text/plain"); var (start, end) = ParseByteRange(rangeHeader, PlaceholderSignature.Length); var count = end - start + 1; var body = new byte[count]; Array.Copy(PlaceholderSignature, start, body, 0, count); Response.Headers.AcceptRanges = "bytes"; Response.Headers.ContentRange = $"bytes {start}-{end}/{PlaceholderSignature.Length}"; Response.StatusCode = StatusCodes.Status206PartialContent; return File(body, "text/plain", enableRangeProcessing: false); } private static (int Start, int End) ParseByteRange(string rangeHeader, int length) { var spec = rangeHeader["bytes=".Length..].Trim(); if (spec.Contains(',')) return (0, length - 1); var parts = spec.Split('-', 2); if (parts.Length != 2) return (0, length - 1); if (parts[0].Length == 0) { if (!int.TryParse(parts[1], out var suffixLength) || suffixLength <= 0) return (0, length - 1); var start = Math.Max(0, length - suffixLength); return (start, length - 1); } if (!int.TryParse(parts[0], out var parsedStart)) return (0, length - 1); var startOffset = parsedStart >= length ? 0 : Math.Max(0, parsedStart); var endOffset = length - 1; if (parts[1].Length > 0 && int.TryParse(parts[1], out var parsedEnd)) endOffset = Math.Clamp(parsedEnd, startOffset, length - 1); return (startOffset, endOffset); } } }