| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 | using System;using System.Collections.Generic;using System.Linq;using Jellyfin.Extensions;using Microsoft.AspNetCore.Http;using Microsoft.AspNetCore.Http.Features;using Microsoft.Extensions.Primitives;namespace Jellyfin.Server.Middleware{    /// <summary>    /// Defines the <see cref="UrlDecodeQueryFeature"/>.    /// </summary>    public class UrlDecodeQueryFeature : IQueryFeature    {        private IQueryCollection? _store;        /// <summary>        /// Initializes a new instance of the <see cref="UrlDecodeQueryFeature"/> class.        /// </summary>        /// <param name="feature">The <see cref="IQueryFeature"/> instance.</param>        public UrlDecodeQueryFeature(IQueryFeature feature)        {            Query = feature.Query;        }        /// <summary>        /// Gets or sets a value indicating the url decoded <see cref="IQueryCollection"/>.        /// </summary>        public IQueryCollection Query        {            get            {                return _store ?? QueryCollection.Empty;            }            set            {                // Only interested in where the querystring is encoded which shows up as one key with nothing in the value.                if (value.Count != 1)                {                    _store = value;                    return;                }                // Encoded querystrings have no value, so don't process anything if a value is present.                var (key, stringValues) = value.First();                if (!string.IsNullOrEmpty(stringValues))                {                    _store = value;                    return;                }                if (!key.Contains('=', StringComparison.Ordinal))                {                    _store = value;                    return;                }                var pairs = new Dictionary<string, StringValues>();                foreach (var pair in key.SpanSplit('&'))                {                    var i = pair.IndexOf('=');                    if (i == -1)                    {                        // encoded is an equals.                        // We use TryAdd so duplicate keys get ignored                        pairs.TryAdd(pair.ToString(), StringValues.Empty);                        continue;                    }                    var k = pair[..i].ToString();                    var v = pair[(i + 1)..].ToString();                    if (!pairs.TryAdd(k, new StringValues(v)))                    {                        pairs[k] = StringValues.Concat(pairs[k], v);                    }                }                _store = new QueryCollection(pairs);            }        }    }}
 |