using System;
using System.Collections.Generic;
using System.Linq;
namespace Jellyfin.Plugin.Chaosflix.Api;
///
/// Reads back a proxy url the channel handed out, so a diagnostic can check it and show
/// it without handing the reader a url they could stream through.
///
internal static class ProxyUrl
{
private const string FolderParameter = "recordingFolder";
private const string LanguageParameter = "language";
///
/// Renders the url without its signature. The result is rebuilt from the parts that
/// were understood rather than edited in place, so nothing of the signature can
/// survive a url shaped differently than expected.
///
internal static string Redact(string url)
{
if (!Uri.TryCreate(url, UriKind.Absolute, out var uri))
{
return "";
}
var query = Parse(uri);
var parts = new List();
if (query.TryGetValue(FolderParameter, out var folder))
{
parts.Add($"{FolderParameter}={folder}");
}
if (query.TryGetValue(LanguageParameter, out var language))
{
parts.Add($"{LanguageParameter}={language}");
}
parts.Add($"{ProxySignature.QueryParameter}=");
return $"{uri.GetLeftPart(UriPartial.Path)}?{string.Join('&', parts)}";
}
///
/// Whether the url carries a signature the proxy endpoint would accept for exactly
/// the recording the url names.
///
internal static bool IsSignedCorrectly(string url)
{
if (!Uri.TryCreate(url, UriKind.Absolute, out var uri))
{
return false;
}
var guid = uri.Segments.LastOrDefault()?.TrimEnd('/');
if (string.IsNullOrEmpty(guid))
{
return false;
}
var query = Parse(uri);
query.TryGetValue(ProxySignature.QueryParameter, out var signature);
return ProxySignature.Verify(
Uri.UnescapeDataString(guid),
query.GetValueOrDefault(FolderParameter),
query.GetValueOrDefault(LanguageParameter),
signature);
}
private static Dictionary Parse(Uri uri)
{
var query = new Dictionary(StringComparer.Ordinal);
foreach (var pair in uri.Query.TrimStart('?').Split('&', StringSplitOptions.RemoveEmptyEntries))
{
var separator = pair.IndexOf('=', StringComparison.Ordinal);
if (separator > 0)
{
query[pair[..separator]] = Uri.UnescapeDataString(pair[(separator + 1)..]);
}
}
return query;
}
}