mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-06-12 10:40:24 +01:00
Add GPL modules
This commit is contained in:
61
MediaBrowser.Model/Services/ApiMemberAttribute.cs
Normal file
61
MediaBrowser.Model/Services/ApiMemberAttribute.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
using System;
|
||||
|
||||
namespace MediaBrowser.Model.Services
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = true)]
|
||||
public class ApiMemberAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets verb to which applies attribute. By default applies to all verbs.
|
||||
/// </summary>
|
||||
public string Verb { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets parameter type: It can be only one of the following: path, query, body, form, or header.
|
||||
/// </summary>
|
||||
public string ParameterType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets unique name for the parameter. Each name must be unique, even if they are associated with different paramType values.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Other notes on the name field:
|
||||
/// If paramType is body, the name is used only for UI and codegeneration.
|
||||
/// If paramType is path, the name field must correspond to the associated path segment from the path field in the api object.
|
||||
/// If paramType is query, the name field corresponds to the query param name.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the human-readable description for the parameter.
|
||||
/// </summary>
|
||||
public string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// For path, query, and header paramTypes, this field must be a primitive. For body, this can be a complex or container datatype.
|
||||
/// </summary>
|
||||
public string DataType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// For path, this is always true. Otherwise, this field tells the client whether or not the field must be supplied.
|
||||
/// </summary>
|
||||
public bool IsRequired { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// For query params, this specifies that a comma-separated list of values can be passed to the API. For path and body types, this field cannot be true.
|
||||
/// </summary>
|
||||
public bool AllowMultiple { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets route to which applies attribute, matches using StartsWith. By default applies to all routes.
|
||||
/// </summary>
|
||||
public string Route { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether to exclude this property from being included in the ModelSchema
|
||||
/// </summary>
|
||||
public bool ExcludeInSchema { get; set; }
|
||||
}
|
||||
}
|
||||
923
MediaBrowser.Model/Services/HttpUtility.cs
Normal file
923
MediaBrowser.Model/Services/HttpUtility.cs
Normal file
@@ -0,0 +1,923 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using MediaBrowser.Model.Services;
|
||||
using MediaBrowser.Model.Extensions;
|
||||
|
||||
namespace MediaBrowser.Model.Services
|
||||
{
|
||||
public static class MyHttpUtility
|
||||
{
|
||||
// Must be sorted
|
||||
static readonly long[] entities = new long[] {
|
||||
(long)'A' << 56 | (long)'E' << 48 | (long)'l' << 40 | (long)'i' << 32 | (long)'g' << 24,
|
||||
(long)'A' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
|
||||
(long)'A' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
|
||||
(long)'A' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
|
||||
(long)'A' << 56 | (long)'l' << 48 | (long)'p' << 40 | (long)'h' << 32 | (long)'a' << 24,
|
||||
(long)'A' << 56 | (long)'r' << 48 | (long)'i' << 40 | (long)'n' << 32 | (long)'g' << 24,
|
||||
(long)'A' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'l' << 32 | (long)'d' << 24 | (long)'e' << 16,
|
||||
(long)'A' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
|
||||
(long)'B' << 56 | (long)'e' << 48 | (long)'t' << 40 | (long)'a' << 32,
|
||||
(long)'C' << 56 | (long)'c' << 48 | (long)'e' << 40 | (long)'d' << 32 | (long)'i' << 24 | (long)'l' << 16,
|
||||
(long)'C' << 56 | (long)'h' << 48 | (long)'i' << 40,
|
||||
(long)'D' << 56 | (long)'a' << 48 | (long)'g' << 40 | (long)'g' << 32 | (long)'e' << 24 | (long)'r' << 16,
|
||||
(long)'D' << 56 | (long)'e' << 48 | (long)'l' << 40 | (long)'t' << 32 | (long)'a' << 24,
|
||||
(long)'E' << 56 | (long)'T' << 48 | (long)'H' << 40,
|
||||
(long)'E' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
|
||||
(long)'E' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
|
||||
(long)'E' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
|
||||
(long)'E' << 56 | (long)'p' << 48 | (long)'s' << 40 | (long)'i' << 32 | (long)'l' << 24 | (long)'o' << 16 | (long)'n' << 8,
|
||||
(long)'E' << 56 | (long)'t' << 48 | (long)'a' << 40,
|
||||
(long)'E' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
|
||||
(long)'G' << 56 | (long)'a' << 48 | (long)'m' << 40 | (long)'m' << 32 | (long)'a' << 24,
|
||||
(long)'I' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
|
||||
(long)'I' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
|
||||
(long)'I' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
|
||||
(long)'I' << 56 | (long)'o' << 48 | (long)'t' << 40 | (long)'a' << 32,
|
||||
(long)'I' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
|
||||
(long)'K' << 56 | (long)'a' << 48 | (long)'p' << 40 | (long)'p' << 32 | (long)'a' << 24,
|
||||
(long)'L' << 56 | (long)'a' << 48 | (long)'m' << 40 | (long)'b' << 32 | (long)'d' << 24 | (long)'a' << 16,
|
||||
(long)'M' << 56 | (long)'u' << 48,
|
||||
(long)'N' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'l' << 32 | (long)'d' << 24 | (long)'e' << 16,
|
||||
(long)'N' << 56 | (long)'u' << 48,
|
||||
(long)'O' << 56 | (long)'E' << 48 | (long)'l' << 40 | (long)'i' << 32 | (long)'g' << 24,
|
||||
(long)'O' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
|
||||
(long)'O' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
|
||||
(long)'O' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
|
||||
(long)'O' << 56 | (long)'m' << 48 | (long)'e' << 40 | (long)'g' << 32 | (long)'a' << 24,
|
||||
(long)'O' << 56 | (long)'m' << 48 | (long)'i' << 40 | (long)'c' << 32 | (long)'r' << 24 | (long)'o' << 16 | (long)'n' << 8,
|
||||
(long)'O' << 56 | (long)'s' << 48 | (long)'l' << 40 | (long)'a' << 32 | (long)'s' << 24 | (long)'h' << 16,
|
||||
(long)'O' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'l' << 32 | (long)'d' << 24 | (long)'e' << 16,
|
||||
(long)'O' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
|
||||
(long)'P' << 56 | (long)'h' << 48 | (long)'i' << 40,
|
||||
(long)'P' << 56 | (long)'i' << 48,
|
||||
(long)'P' << 56 | (long)'r' << 48 | (long)'i' << 40 | (long)'m' << 32 | (long)'e' << 24,
|
||||
(long)'P' << 56 | (long)'s' << 48 | (long)'i' << 40,
|
||||
(long)'R' << 56 | (long)'h' << 48 | (long)'o' << 40,
|
||||
(long)'S' << 56 | (long)'c' << 48 | (long)'a' << 40 | (long)'r' << 32 | (long)'o' << 24 | (long)'n' << 16,
|
||||
(long)'S' << 56 | (long)'i' << 48 | (long)'g' << 40 | (long)'m' << 32 | (long)'a' << 24,
|
||||
(long)'T' << 56 | (long)'H' << 48 | (long)'O' << 40 | (long)'R' << 32 | (long)'N' << 24,
|
||||
(long)'T' << 56 | (long)'a' << 48 | (long)'u' << 40,
|
||||
(long)'T' << 56 | (long)'h' << 48 | (long)'e' << 40 | (long)'t' << 32 | (long)'a' << 24,
|
||||
(long)'U' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
|
||||
(long)'U' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
|
||||
(long)'U' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
|
||||
(long)'U' << 56 | (long)'p' << 48 | (long)'s' << 40 | (long)'i' << 32 | (long)'l' << 24 | (long)'o' << 16 | (long)'n' << 8,
|
||||
(long)'U' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
|
||||
(long)'X' << 56 | (long)'i' << 48,
|
||||
(long)'Y' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
|
||||
(long)'Y' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
|
||||
(long)'Z' << 56 | (long)'e' << 48 | (long)'t' << 40 | (long)'a' << 32,
|
||||
(long)'a' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
|
||||
(long)'a' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
|
||||
(long)'a' << 56 | (long)'c' << 48 | (long)'u' << 40 | (long)'t' << 32 | (long)'e' << 24,
|
||||
(long)'a' << 56 | (long)'e' << 48 | (long)'l' << 40 | (long)'i' << 32 | (long)'g' << 24,
|
||||
(long)'a' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
|
||||
(long)'a' << 56 | (long)'l' << 48 | (long)'e' << 40 | (long)'f' << 32 | (long)'s' << 24 | (long)'y' << 16 | (long)'m' << 8,
|
||||
(long)'a' << 56 | (long)'l' << 48 | (long)'p' << 40 | (long)'h' << 32 | (long)'a' << 24,
|
||||
(long)'a' << 56 | (long)'m' << 48 | (long)'p' << 40,
|
||||
(long)'a' << 56 | (long)'n' << 48 | (long)'d' << 40,
|
||||
(long)'a' << 56 | (long)'n' << 48 | (long)'g' << 40,
|
||||
(long)'a' << 56 | (long)'p' << 48 | (long)'o' << 40 | (long)'s' << 32,
|
||||
(long)'a' << 56 | (long)'r' << 48 | (long)'i' << 40 | (long)'n' << 32 | (long)'g' << 24,
|
||||
(long)'a' << 56 | (long)'s' << 48 | (long)'y' << 40 | (long)'m' << 32 | (long)'p' << 24,
|
||||
(long)'a' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'l' << 32 | (long)'d' << 24 | (long)'e' << 16,
|
||||
(long)'a' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
|
||||
(long)'b' << 56 | (long)'d' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24,
|
||||
(long)'b' << 56 | (long)'e' << 48 | (long)'t' << 40 | (long)'a' << 32,
|
||||
(long)'b' << 56 | (long)'r' << 48 | (long)'v' << 40 | (long)'b' << 32 | (long)'a' << 24 | (long)'r' << 16,
|
||||
(long)'b' << 56 | (long)'u' << 48 | (long)'l' << 40 | (long)'l' << 32,
|
||||
(long)'c' << 56 | (long)'a' << 48 | (long)'p' << 40,
|
||||
(long)'c' << 56 | (long)'c' << 48 | (long)'e' << 40 | (long)'d' << 32 | (long)'i' << 24 | (long)'l' << 16,
|
||||
(long)'c' << 56 | (long)'e' << 48 | (long)'d' << 40 | (long)'i' << 32 | (long)'l' << 24,
|
||||
(long)'c' << 56 | (long)'e' << 48 | (long)'n' << 40 | (long)'t' << 32,
|
||||
(long)'c' << 56 | (long)'h' << 48 | (long)'i' << 40,
|
||||
(long)'c' << 56 | (long)'i' << 48 | (long)'r' << 40 | (long)'c' << 32,
|
||||
(long)'c' << 56 | (long)'l' << 48 | (long)'u' << 40 | (long)'b' << 32 | (long)'s' << 24,
|
||||
(long)'c' << 56 | (long)'o' << 48 | (long)'n' << 40 | (long)'g' << 32,
|
||||
(long)'c' << 56 | (long)'o' << 48 | (long)'p' << 40 | (long)'y' << 32,
|
||||
(long)'c' << 56 | (long)'r' << 48 | (long)'a' << 40 | (long)'r' << 32 | (long)'r' << 24,
|
||||
(long)'c' << 56 | (long)'u' << 48 | (long)'p' << 40,
|
||||
(long)'c' << 56 | (long)'u' << 48 | (long)'r' << 40 | (long)'r' << 32 | (long)'e' << 24 | (long)'n' << 16,
|
||||
(long)'d' << 56 | (long)'A' << 48 | (long)'r' << 40 | (long)'r' << 32,
|
||||
(long)'d' << 56 | (long)'a' << 48 | (long)'g' << 40 | (long)'g' << 32 | (long)'e' << 24 | (long)'r' << 16,
|
||||
(long)'d' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'r' << 32,
|
||||
(long)'d' << 56 | (long)'e' << 48 | (long)'g' << 40,
|
||||
(long)'d' << 56 | (long)'e' << 48 | (long)'l' << 40 | (long)'t' << 32 | (long)'a' << 24,
|
||||
(long)'d' << 56 | (long)'i' << 48 | (long)'a' << 40 | (long)'m' << 32 | (long)'s' << 24,
|
||||
(long)'d' << 56 | (long)'i' << 48 | (long)'v' << 40 | (long)'i' << 32 | (long)'d' << 24 | (long)'e' << 16,
|
||||
(long)'e' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
|
||||
(long)'e' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
|
||||
(long)'e' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
|
||||
(long)'e' << 56 | (long)'m' << 48 | (long)'p' << 40 | (long)'t' << 32 | (long)'y' << 24,
|
||||
(long)'e' << 56 | (long)'m' << 48 | (long)'s' << 40 | (long)'p' << 32,
|
||||
(long)'e' << 56 | (long)'n' << 48 | (long)'s' << 40 | (long)'p' << 32,
|
||||
(long)'e' << 56 | (long)'p' << 48 | (long)'s' << 40 | (long)'i' << 32 | (long)'l' << 24 | (long)'o' << 16 | (long)'n' << 8,
|
||||
(long)'e' << 56 | (long)'q' << 48 | (long)'u' << 40 | (long)'i' << 32 | (long)'v' << 24,
|
||||
(long)'e' << 56 | (long)'t' << 48 | (long)'a' << 40,
|
||||
(long)'e' << 56 | (long)'t' << 48 | (long)'h' << 40,
|
||||
(long)'e' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
|
||||
(long)'e' << 56 | (long)'u' << 48 | (long)'r' << 40 | (long)'o' << 32,
|
||||
(long)'e' << 56 | (long)'x' << 48 | (long)'i' << 40 | (long)'s' << 32 | (long)'t' << 24,
|
||||
(long)'f' << 56 | (long)'n' << 48 | (long)'o' << 40 | (long)'f' << 32,
|
||||
(long)'f' << 56 | (long)'o' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'l' << 24 | (long)'l' << 16,
|
||||
(long)'f' << 56 | (long)'r' << 48 | (long)'a' << 40 | (long)'c' << 32 | (long)'1' << 24 | (long)'2' << 16,
|
||||
(long)'f' << 56 | (long)'r' << 48 | (long)'a' << 40 | (long)'c' << 32 | (long)'1' << 24 | (long)'4' << 16,
|
||||
(long)'f' << 56 | (long)'r' << 48 | (long)'a' << 40 | (long)'c' << 32 | (long)'3' << 24 | (long)'4' << 16,
|
||||
(long)'f' << 56 | (long)'r' << 48 | (long)'a' << 40 | (long)'s' << 32 | (long)'l' << 24,
|
||||
(long)'g' << 56 | (long)'a' << 48 | (long)'m' << 40 | (long)'m' << 32 | (long)'a' << 24,
|
||||
(long)'g' << 56 | (long)'e' << 48,
|
||||
(long)'g' << 56 | (long)'t' << 48,
|
||||
(long)'h' << 56 | (long)'A' << 48 | (long)'r' << 40 | (long)'r' << 32,
|
||||
(long)'h' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'r' << 32,
|
||||
(long)'h' << 56 | (long)'e' << 48 | (long)'a' << 40 | (long)'r' << 32 | (long)'t' << 24 | (long)'s' << 16,
|
||||
(long)'h' << 56 | (long)'e' << 48 | (long)'l' << 40 | (long)'l' << 32 | (long)'i' << 24 | (long)'p' << 16,
|
||||
(long)'i' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
|
||||
(long)'i' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
|
||||
(long)'i' << 56 | (long)'e' << 48 | (long)'x' << 40 | (long)'c' << 32 | (long)'l' << 24,
|
||||
(long)'i' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
|
||||
(long)'i' << 56 | (long)'m' << 48 | (long)'a' << 40 | (long)'g' << 32 | (long)'e' << 24,
|
||||
(long)'i' << 56 | (long)'n' << 48 | (long)'f' << 40 | (long)'i' << 32 | (long)'n' << 24,
|
||||
(long)'i' << 56 | (long)'n' << 48 | (long)'t' << 40,
|
||||
(long)'i' << 56 | (long)'o' << 48 | (long)'t' << 40 | (long)'a' << 32,
|
||||
(long)'i' << 56 | (long)'q' << 48 | (long)'u' << 40 | (long)'e' << 32 | (long)'s' << 24 | (long)'t' << 16,
|
||||
(long)'i' << 56 | (long)'s' << 48 | (long)'i' << 40 | (long)'n' << 32,
|
||||
(long)'i' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
|
||||
(long)'k' << 56 | (long)'a' << 48 | (long)'p' << 40 | (long)'p' << 32 | (long)'a' << 24,
|
||||
(long)'l' << 56 | (long)'A' << 48 | (long)'r' << 40 | (long)'r' << 32,
|
||||
(long)'l' << 56 | (long)'a' << 48 | (long)'m' << 40 | (long)'b' << 32 | (long)'d' << 24 | (long)'a' << 16,
|
||||
(long)'l' << 56 | (long)'a' << 48 | (long)'n' << 40 | (long)'g' << 32,
|
||||
(long)'l' << 56 | (long)'a' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24,
|
||||
(long)'l' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'r' << 32,
|
||||
(long)'l' << 56 | (long)'c' << 48 | (long)'e' << 40 | (long)'i' << 32 | (long)'l' << 24,
|
||||
(long)'l' << 56 | (long)'d' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24,
|
||||
(long)'l' << 56 | (long)'e' << 48,
|
||||
(long)'l' << 56 | (long)'f' << 48 | (long)'l' << 40 | (long)'o' << 32 | (long)'o' << 24 | (long)'r' << 16,
|
||||
(long)'l' << 56 | (long)'o' << 48 | (long)'w' << 40 | (long)'a' << 32 | (long)'s' << 24 | (long)'t' << 16,
|
||||
(long)'l' << 56 | (long)'o' << 48 | (long)'z' << 40,
|
||||
(long)'l' << 56 | (long)'r' << 48 | (long)'m' << 40,
|
||||
(long)'l' << 56 | (long)'s' << 48 | (long)'a' << 40 | (long)'q' << 32 | (long)'u' << 24 | (long)'o' << 16,
|
||||
(long)'l' << 56 | (long)'s' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24,
|
||||
(long)'l' << 56 | (long)'t' << 48,
|
||||
(long)'m' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'r' << 32,
|
||||
(long)'m' << 56 | (long)'d' << 48 | (long)'a' << 40 | (long)'s' << 32 | (long)'h' << 24,
|
||||
(long)'m' << 56 | (long)'i' << 48 | (long)'c' << 40 | (long)'r' << 32 | (long)'o' << 24,
|
||||
(long)'m' << 56 | (long)'i' << 48 | (long)'d' << 40 | (long)'d' << 32 | (long)'o' << 24 | (long)'t' << 16,
|
||||
(long)'m' << 56 | (long)'i' << 48 | (long)'n' << 40 | (long)'u' << 32 | (long)'s' << 24,
|
||||
(long)'m' << 56 | (long)'u' << 48,
|
||||
(long)'n' << 56 | (long)'a' << 48 | (long)'b' << 40 | (long)'l' << 32 | (long)'a' << 24,
|
||||
(long)'n' << 56 | (long)'b' << 48 | (long)'s' << 40 | (long)'p' << 32,
|
||||
(long)'n' << 56 | (long)'d' << 48 | (long)'a' << 40 | (long)'s' << 32 | (long)'h' << 24,
|
||||
(long)'n' << 56 | (long)'e' << 48,
|
||||
(long)'n' << 56 | (long)'i' << 48,
|
||||
(long)'n' << 56 | (long)'o' << 48 | (long)'t' << 40,
|
||||
(long)'n' << 56 | (long)'o' << 48 | (long)'t' << 40 | (long)'i' << 32 | (long)'n' << 24,
|
||||
(long)'n' << 56 | (long)'s' << 48 | (long)'u' << 40 | (long)'b' << 32,
|
||||
(long)'n' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'l' << 32 | (long)'d' << 24 | (long)'e' << 16,
|
||||
(long)'n' << 56 | (long)'u' << 48,
|
||||
(long)'o' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
|
||||
(long)'o' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
|
||||
(long)'o' << 56 | (long)'e' << 48 | (long)'l' << 40 | (long)'i' << 32 | (long)'g' << 24,
|
||||
(long)'o' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
|
||||
(long)'o' << 56 | (long)'l' << 48 | (long)'i' << 40 | (long)'n' << 32 | (long)'e' << 24,
|
||||
(long)'o' << 56 | (long)'m' << 48 | (long)'e' << 40 | (long)'g' << 32 | (long)'a' << 24,
|
||||
(long)'o' << 56 | (long)'m' << 48 | (long)'i' << 40 | (long)'c' << 32 | (long)'r' << 24 | (long)'o' << 16 | (long)'n' << 8,
|
||||
(long)'o' << 56 | (long)'p' << 48 | (long)'l' << 40 | (long)'u' << 32 | (long)'s' << 24,
|
||||
(long)'o' << 56 | (long)'r' << 48,
|
||||
(long)'o' << 56 | (long)'r' << 48 | (long)'d' << 40 | (long)'f' << 32,
|
||||
(long)'o' << 56 | (long)'r' << 48 | (long)'d' << 40 | (long)'m' << 32,
|
||||
(long)'o' << 56 | (long)'s' << 48 | (long)'l' << 40 | (long)'a' << 32 | (long)'s' << 24 | (long)'h' << 16,
|
||||
(long)'o' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'l' << 32 | (long)'d' << 24 | (long)'e' << 16,
|
||||
(long)'o' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'m' << 32 | (long)'e' << 24 | (long)'s' << 16,
|
||||
(long)'o' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
|
||||
(long)'p' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'a' << 32,
|
||||
(long)'p' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'t' << 32,
|
||||
(long)'p' << 56 | (long)'e' << 48 | (long)'r' << 40 | (long)'m' << 32 | (long)'i' << 24 | (long)'l' << 16,
|
||||
(long)'p' << 56 | (long)'e' << 48 | (long)'r' << 40 | (long)'p' << 32,
|
||||
(long)'p' << 56 | (long)'h' << 48 | (long)'i' << 40,
|
||||
(long)'p' << 56 | (long)'i' << 48,
|
||||
(long)'p' << 56 | (long)'i' << 48 | (long)'v' << 40,
|
||||
(long)'p' << 56 | (long)'l' << 48 | (long)'u' << 40 | (long)'s' << 32 | (long)'m' << 24 | (long)'n' << 16,
|
||||
(long)'p' << 56 | (long)'o' << 48 | (long)'u' << 40 | (long)'n' << 32 | (long)'d' << 24,
|
||||
(long)'p' << 56 | (long)'r' << 48 | (long)'i' << 40 | (long)'m' << 32 | (long)'e' << 24,
|
||||
(long)'p' << 56 | (long)'r' << 48 | (long)'o' << 40 | (long)'d' << 32,
|
||||
(long)'p' << 56 | (long)'r' << 48 | (long)'o' << 40 | (long)'p' << 32,
|
||||
(long)'p' << 56 | (long)'s' << 48 | (long)'i' << 40,
|
||||
(long)'q' << 56 | (long)'u' << 48 | (long)'o' << 40 | (long)'t' << 32,
|
||||
(long)'r' << 56 | (long)'A' << 48 | (long)'r' << 40 | (long)'r' << 32,
|
||||
(long)'r' << 56 | (long)'a' << 48 | (long)'d' << 40 | (long)'i' << 32 | (long)'c' << 24,
|
||||
(long)'r' << 56 | (long)'a' << 48 | (long)'n' << 40 | (long)'g' << 32,
|
||||
(long)'r' << 56 | (long)'a' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24,
|
||||
(long)'r' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'r' << 32,
|
||||
(long)'r' << 56 | (long)'c' << 48 | (long)'e' << 40 | (long)'i' << 32 | (long)'l' << 24,
|
||||
(long)'r' << 56 | (long)'d' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24,
|
||||
(long)'r' << 56 | (long)'e' << 48 | (long)'a' << 40 | (long)'l' << 32,
|
||||
(long)'r' << 56 | (long)'e' << 48 | (long)'g' << 40,
|
||||
(long)'r' << 56 | (long)'f' << 48 | (long)'l' << 40 | (long)'o' << 32 | (long)'o' << 24 | (long)'r' << 16,
|
||||
(long)'r' << 56 | (long)'h' << 48 | (long)'o' << 40,
|
||||
(long)'r' << 56 | (long)'l' << 48 | (long)'m' << 40,
|
||||
(long)'r' << 56 | (long)'s' << 48 | (long)'a' << 40 | (long)'q' << 32 | (long)'u' << 24 | (long)'o' << 16,
|
||||
(long)'r' << 56 | (long)'s' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24,
|
||||
(long)'s' << 56 | (long)'b' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24,
|
||||
(long)'s' << 56 | (long)'c' << 48 | (long)'a' << 40 | (long)'r' << 32 | (long)'o' << 24 | (long)'n' << 16,
|
||||
(long)'s' << 56 | (long)'d' << 48 | (long)'o' << 40 | (long)'t' << 32,
|
||||
(long)'s' << 56 | (long)'e' << 48 | (long)'c' << 40 | (long)'t' << 32,
|
||||
(long)'s' << 56 | (long)'h' << 48 | (long)'y' << 40,
|
||||
(long)'s' << 56 | (long)'i' << 48 | (long)'g' << 40 | (long)'m' << 32 | (long)'a' << 24,
|
||||
(long)'s' << 56 | (long)'i' << 48 | (long)'g' << 40 | (long)'m' << 32 | (long)'a' << 24 | (long)'f' << 16,
|
||||
(long)'s' << 56 | (long)'i' << 48 | (long)'m' << 40,
|
||||
(long)'s' << 56 | (long)'p' << 48 | (long)'a' << 40 | (long)'d' << 32 | (long)'e' << 24 | (long)'s' << 16,
|
||||
(long)'s' << 56 | (long)'u' << 48 | (long)'b' << 40,
|
||||
(long)'s' << 56 | (long)'u' << 48 | (long)'b' << 40 | (long)'e' << 32,
|
||||
(long)'s' << 56 | (long)'u' << 48 | (long)'m' << 40,
|
||||
(long)'s' << 56 | (long)'u' << 48 | (long)'p' << 40,
|
||||
(long)'s' << 56 | (long)'u' << 48 | (long)'p' << 40 | (long)'1' << 32,
|
||||
(long)'s' << 56 | (long)'u' << 48 | (long)'p' << 40 | (long)'2' << 32,
|
||||
(long)'s' << 56 | (long)'u' << 48 | (long)'p' << 40 | (long)'3' << 32,
|
||||
(long)'s' << 56 | (long)'u' << 48 | (long)'p' << 40 | (long)'e' << 32,
|
||||
(long)'s' << 56 | (long)'z' << 48 | (long)'l' << 40 | (long)'i' << 32 | (long)'g' << 24,
|
||||
(long)'t' << 56 | (long)'a' << 48 | (long)'u' << 40,
|
||||
(long)'t' << 56 | (long)'h' << 48 | (long)'e' << 40 | (long)'r' << 32 | (long)'e' << 24 | (long)'4' << 16,
|
||||
(long)'t' << 56 | (long)'h' << 48 | (long)'e' << 40 | (long)'t' << 32 | (long)'a' << 24,
|
||||
(long)'t' << 56 | (long)'h' << 48 | (long)'e' << 40 | (long)'t' << 32 | (long)'a' << 24 | (long)'s' << 16 | (long)'y' << 8 | (long)'m' << 0,
|
||||
(long)'t' << 56 | (long)'h' << 48 | (long)'i' << 40 | (long)'n' << 32 | (long)'s' << 24 | (long)'p' << 16,
|
||||
(long)'t' << 56 | (long)'h' << 48 | (long)'o' << 40 | (long)'r' << 32 | (long)'n' << 24,
|
||||
(long)'t' << 56 | (long)'i' << 48 | (long)'l' << 40 | (long)'d' << 32 | (long)'e' << 24,
|
||||
(long)'t' << 56 | (long)'i' << 48 | (long)'m' << 40 | (long)'e' << 32 | (long)'s' << 24,
|
||||
(long)'t' << 56 | (long)'r' << 48 | (long)'a' << 40 | (long)'d' << 32 | (long)'e' << 24,
|
||||
(long)'u' << 56 | (long)'A' << 48 | (long)'r' << 40 | (long)'r' << 32,
|
||||
(long)'u' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
|
||||
(long)'u' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'r' << 32,
|
||||
(long)'u' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
|
||||
(long)'u' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
|
||||
(long)'u' << 56 | (long)'m' << 48 | (long)'l' << 40,
|
||||
(long)'u' << 56 | (long)'p' << 48 | (long)'s' << 40 | (long)'i' << 32 | (long)'h' << 24,
|
||||
(long)'u' << 56 | (long)'p' << 48 | (long)'s' << 40 | (long)'i' << 32 | (long)'l' << 24 | (long)'o' << 16 | (long)'n' << 8,
|
||||
(long)'u' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
|
||||
(long)'w' << 56 | (long)'e' << 48 | (long)'i' << 40 | (long)'e' << 32 | (long)'r' << 24 | (long)'p' << 16,
|
||||
(long)'x' << 56 | (long)'i' << 48,
|
||||
(long)'y' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
|
||||
(long)'y' << 56 | (long)'e' << 48 | (long)'n' << 40,
|
||||
(long)'y' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
|
||||
(long)'z' << 56 | (long)'e' << 48 | (long)'t' << 40 | (long)'a' << 32,
|
||||
(long)'z' << 56 | (long)'w' << 48 | (long)'j' << 40,
|
||||
(long)'z' << 56 | (long)'w' << 48 | (long)'n' << 40 | (long)'j' << 32
|
||||
};
|
||||
|
||||
static readonly char[] entities_values = new char[] {
|
||||
'\u00C6',
|
||||
'\u00C1',
|
||||
'\u00C2',
|
||||
'\u00C0',
|
||||
'\u0391',
|
||||
'\u00C5',
|
||||
'\u00C3',
|
||||
'\u00C4',
|
||||
'\u0392',
|
||||
'\u00C7',
|
||||
'\u03A7',
|
||||
'\u2021',
|
||||
'\u0394',
|
||||
'\u00D0',
|
||||
'\u00C9',
|
||||
'\u00CA',
|
||||
'\u00C8',
|
||||
'\u0395',
|
||||
'\u0397',
|
||||
'\u00CB',
|
||||
'\u0393',
|
||||
'\u00CD',
|
||||
'\u00CE',
|
||||
'\u00CC',
|
||||
'\u0399',
|
||||
'\u00CF',
|
||||
'\u039A',
|
||||
'\u039B',
|
||||
'\u039C',
|
||||
'\u00D1',
|
||||
'\u039D',
|
||||
'\u0152',
|
||||
'\u00D3',
|
||||
'\u00D4',
|
||||
'\u00D2',
|
||||
'\u03A9',
|
||||
'\u039F',
|
||||
'\u00D8',
|
||||
'\u00D5',
|
||||
'\u00D6',
|
||||
'\u03A6',
|
||||
'\u03A0',
|
||||
'\u2033',
|
||||
'\u03A8',
|
||||
'\u03A1',
|
||||
'\u0160',
|
||||
'\u03A3',
|
||||
'\u00DE',
|
||||
'\u03A4',
|
||||
'\u0398',
|
||||
'\u00DA',
|
||||
'\u00DB',
|
||||
'\u00D9',
|
||||
'\u03A5',
|
||||
'\u00DC',
|
||||
'\u039E',
|
||||
'\u00DD',
|
||||
'\u0178',
|
||||
'\u0396',
|
||||
'\u00E1',
|
||||
'\u00E2',
|
||||
'\u00B4',
|
||||
'\u00E6',
|
||||
'\u00E0',
|
||||
'\u2135',
|
||||
'\u03B1',
|
||||
'\u0026',
|
||||
'\u2227',
|
||||
'\u2220',
|
||||
'\u0027',
|
||||
'\u00E5',
|
||||
'\u2248',
|
||||
'\u00E3',
|
||||
'\u00E4',
|
||||
'\u201E',
|
||||
'\u03B2',
|
||||
'\u00A6',
|
||||
'\u2022',
|
||||
'\u2229',
|
||||
'\u00E7',
|
||||
'\u00B8',
|
||||
'\u00A2',
|
||||
'\u03C7',
|
||||
'\u02C6',
|
||||
'\u2663',
|
||||
'\u2245',
|
||||
'\u00A9',
|
||||
'\u21B5',
|
||||
'\u222A',
|
||||
'\u00A4',
|
||||
'\u21D3',
|
||||
'\u2020',
|
||||
'\u2193',
|
||||
'\u00B0',
|
||||
'\u03B4',
|
||||
'\u2666',
|
||||
'\u00F7',
|
||||
'\u00E9',
|
||||
'\u00EA',
|
||||
'\u00E8',
|
||||
'\u2205',
|
||||
'\u2003',
|
||||
'\u2002',
|
||||
'\u03B5',
|
||||
'\u2261',
|
||||
'\u03B7',
|
||||
'\u00F0',
|
||||
'\u00EB',
|
||||
'\u20AC',
|
||||
'\u2203',
|
||||
'\u0192',
|
||||
'\u2200',
|
||||
'\u00BD',
|
||||
'\u00BC',
|
||||
'\u00BE',
|
||||
'\u2044',
|
||||
'\u03B3',
|
||||
'\u2265',
|
||||
'\u003E',
|
||||
'\u21D4',
|
||||
'\u2194',
|
||||
'\u2665',
|
||||
'\u2026',
|
||||
'\u00ED',
|
||||
'\u00EE',
|
||||
'\u00A1',
|
||||
'\u00EC',
|
||||
'\u2111',
|
||||
'\u221E',
|
||||
'\u222B',
|
||||
'\u03B9',
|
||||
'\u00BF',
|
||||
'\u2208',
|
||||
'\u00EF',
|
||||
'\u03BA',
|
||||
'\u21D0',
|
||||
'\u03BB',
|
||||
'\u2329',
|
||||
'\u00AB',
|
||||
'\u2190',
|
||||
'\u2308',
|
||||
'\u201C',
|
||||
'\u2264',
|
||||
'\u230A',
|
||||
'\u2217',
|
||||
'\u25CA',
|
||||
'\u200E',
|
||||
'\u2039',
|
||||
'\u2018',
|
||||
'\u003C',
|
||||
'\u00AF',
|
||||
'\u2014',
|
||||
'\u00B5',
|
||||
'\u00B7',
|
||||
'\u2212',
|
||||
'\u03BC',
|
||||
'\u2207',
|
||||
'\u00A0',
|
||||
'\u2013',
|
||||
'\u2260',
|
||||
'\u220B',
|
||||
'\u00AC',
|
||||
'\u2209',
|
||||
'\u2284',
|
||||
'\u00F1',
|
||||
'\u03BD',
|
||||
'\u00F3',
|
||||
'\u00F4',
|
||||
'\u0153',
|
||||
'\u00F2',
|
||||
'\u203E',
|
||||
'\u03C9',
|
||||
'\u03BF',
|
||||
'\u2295',
|
||||
'\u2228',
|
||||
'\u00AA',
|
||||
'\u00BA',
|
||||
'\u00F8',
|
||||
'\u00F5',
|
||||
'\u2297',
|
||||
'\u00F6',
|
||||
'\u00B6',
|
||||
'\u2202',
|
||||
'\u2030',
|
||||
'\u22A5',
|
||||
'\u03C6',
|
||||
'\u03C0',
|
||||
'\u03D6',
|
||||
'\u00B1',
|
||||
'\u00A3',
|
||||
'\u2032',
|
||||
'\u220F',
|
||||
'\u221D',
|
||||
'\u03C8',
|
||||
'\u0022',
|
||||
'\u21D2',
|
||||
'\u221A',
|
||||
'\u232A',
|
||||
'\u00BB',
|
||||
'\u2192',
|
||||
'\u2309',
|
||||
'\u201D',
|
||||
'\u211C',
|
||||
'\u00AE',
|
||||
'\u230B',
|
||||
'\u03C1',
|
||||
'\u200F',
|
||||
'\u203A',
|
||||
'\u2019',
|
||||
'\u201A',
|
||||
'\u0161',
|
||||
'\u22C5',
|
||||
'\u00A7',
|
||||
'\u00AD',
|
||||
'\u03C3',
|
||||
'\u03C2',
|
||||
'\u223C',
|
||||
'\u2660',
|
||||
'\u2282',
|
||||
'\u2286',
|
||||
'\u2211',
|
||||
'\u2283',
|
||||
'\u00B9',
|
||||
'\u00B2',
|
||||
'\u00B3',
|
||||
'\u2287',
|
||||
'\u00DF',
|
||||
'\u03C4',
|
||||
'\u2234',
|
||||
'\u03B8',
|
||||
'\u03D1',
|
||||
'\u2009',
|
||||
'\u00FE',
|
||||
'\u02DC',
|
||||
'\u00D7',
|
||||
'\u2122',
|
||||
'\u21D1',
|
||||
'\u00FA',
|
||||
'\u2191',
|
||||
'\u00FB',
|
||||
'\u00F9',
|
||||
'\u00A8',
|
||||
'\u03D2',
|
||||
'\u03C5',
|
||||
'\u00FC',
|
||||
'\u2118',
|
||||
'\u03BE',
|
||||
'\u00FD',
|
||||
'\u00A5',
|
||||
'\u00FF',
|
||||
'\u03B6',
|
||||
'\u200D',
|
||||
'\u200C'
|
||||
};
|
||||
|
||||
#region Methods
|
||||
|
||||
static void WriteCharBytes(IList buf, char ch, Encoding e)
|
||||
{
|
||||
if (ch > 255)
|
||||
{
|
||||
foreach (byte b in e.GetBytes(new char[] { ch }))
|
||||
buf.Add(b);
|
||||
}
|
||||
else
|
||||
buf.Add((byte)ch);
|
||||
}
|
||||
|
||||
public static string UrlDecode(string s, Encoding e)
|
||||
{
|
||||
if (null == s)
|
||||
return null;
|
||||
|
||||
if (s.IndexOf('%') == -1 && s.IndexOf('+') == -1)
|
||||
return s;
|
||||
|
||||
if (e == null)
|
||||
e = Encoding.UTF8;
|
||||
|
||||
long len = s.Length;
|
||||
var bytes = new List<byte>();
|
||||
int xchar;
|
||||
char ch;
|
||||
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
ch = s[i];
|
||||
if (ch == '%' && i + 2 < len && s[i + 1] != '%')
|
||||
{
|
||||
if (s[i + 1] == 'u' && i + 5 < len)
|
||||
{
|
||||
// unicode hex sequence
|
||||
xchar = GetChar(s, i + 2, 4);
|
||||
if (xchar != -1)
|
||||
{
|
||||
WriteCharBytes(bytes, (char)xchar, e);
|
||||
i += 5;
|
||||
}
|
||||
else
|
||||
WriteCharBytes(bytes, '%', e);
|
||||
}
|
||||
else if ((xchar = GetChar(s, i + 1, 2)) != -1)
|
||||
{
|
||||
WriteCharBytes(bytes, (char)xchar, e);
|
||||
i += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteCharBytes(bytes, '%', e);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ch == '+')
|
||||
WriteCharBytes(bytes, ' ', e);
|
||||
else
|
||||
WriteCharBytes(bytes, ch, e);
|
||||
}
|
||||
|
||||
byte[] buf = bytes.ToArray(bytes.Count);
|
||||
bytes = null;
|
||||
return e.GetString(buf, 0, buf.Length);
|
||||
|
||||
}
|
||||
|
||||
static int GetInt(byte b)
|
||||
{
|
||||
char c = (char)b;
|
||||
if (c >= '0' && c <= '9')
|
||||
return c - '0';
|
||||
|
||||
if (c >= 'a' && c <= 'f')
|
||||
return c - 'a' + 10;
|
||||
|
||||
if (c >= 'A' && c <= 'F')
|
||||
return c - 'A' + 10;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int GetChar(string str, int offset, int length)
|
||||
{
|
||||
int val = 0;
|
||||
int end = length + offset;
|
||||
for (int i = offset; i < end; i++)
|
||||
{
|
||||
char c = str[i];
|
||||
if (c > 127)
|
||||
return -1;
|
||||
|
||||
int current = GetInt((byte)c);
|
||||
if (current == -1)
|
||||
return -1;
|
||||
val = (val << 4) + current;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static bool TryConvertKeyToEntity(string key, out char value)
|
||||
{
|
||||
var token = CalculateKeyValue(key);
|
||||
if (token == 0)
|
||||
{
|
||||
value = '\0';
|
||||
return false;
|
||||
}
|
||||
|
||||
var idx = Array.BinarySearch(entities, token);
|
||||
if (idx < 0)
|
||||
{
|
||||
value = '\0';
|
||||
return false;
|
||||
}
|
||||
|
||||
value = entities_values[idx];
|
||||
return true;
|
||||
}
|
||||
|
||||
static long CalculateKeyValue(string s)
|
||||
{
|
||||
if (s.Length > 8)
|
||||
return 0;
|
||||
|
||||
long key = 0;
|
||||
for (int i = 0; i < s.Length; ++i)
|
||||
{
|
||||
long ch = s[i];
|
||||
if (ch > 'z' || ch < '0')
|
||||
return 0;
|
||||
|
||||
key |= ch << ((7 - i) * 8);
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes an HTML-encoded string and returns the decoded string.
|
||||
/// </summary>
|
||||
/// <param name="s">The HTML string to decode. </param>
|
||||
/// <returns>The decoded text.</returns>
|
||||
public static string HtmlDecode(string s)
|
||||
{
|
||||
if (s == null)
|
||||
throw new ArgumentNullException("s");
|
||||
|
||||
if (s.IndexOf('&') == -1)
|
||||
return s;
|
||||
|
||||
StringBuilder entity = new StringBuilder();
|
||||
StringBuilder output = new StringBuilder();
|
||||
int len = s.Length;
|
||||
// 0 -> nothing,
|
||||
// 1 -> right after '&'
|
||||
// 2 -> between '&' and ';' but no '#'
|
||||
// 3 -> '#' found after '&' and getting numbers
|
||||
int state = 0;
|
||||
int number = 0;
|
||||
int digit_start = 0;
|
||||
bool hex_number = false;
|
||||
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
char c = s[i];
|
||||
if (state == 0)
|
||||
{
|
||||
if (c == '&')
|
||||
{
|
||||
entity.Append(c);
|
||||
state = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
output.Append(c);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '&')
|
||||
{
|
||||
state = 1;
|
||||
if (digit_start > 0)
|
||||
{
|
||||
entity.Append(s, digit_start, i - digit_start);
|
||||
digit_start = 0;
|
||||
}
|
||||
|
||||
output.Append(entity.ToString());
|
||||
entity.Length = 0;
|
||||
entity.Append('&');
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case 1:
|
||||
if (c == ';')
|
||||
{
|
||||
state = 0;
|
||||
output.Append(entity.ToString());
|
||||
output.Append(c);
|
||||
entity.Length = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
number = 0;
|
||||
hex_number = false;
|
||||
if (c != '#')
|
||||
{
|
||||
state = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = 3;
|
||||
}
|
||||
entity.Append(c);
|
||||
|
||||
break;
|
||||
case 2:
|
||||
entity.Append(c);
|
||||
if (c == ';')
|
||||
{
|
||||
string key = entity.ToString();
|
||||
state = 0;
|
||||
entity.Length = 0;
|
||||
|
||||
if (key.Length > 1)
|
||||
{
|
||||
var skey = key.Substring(1, key.Length - 2);
|
||||
if (TryConvertKeyToEntity(skey, out c))
|
||||
{
|
||||
output.Append(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
output.Append(key);
|
||||
}
|
||||
|
||||
break;
|
||||
case 3:
|
||||
if (c == ';')
|
||||
{
|
||||
if (number < 0x10000)
|
||||
{
|
||||
output.Append((char)number);
|
||||
}
|
||||
else
|
||||
{
|
||||
output.Append((char)(0xd800 + ((number - 0x10000) >> 10)));
|
||||
output.Append((char)(0xdc00 + ((number - 0x10000) & 0x3ff)));
|
||||
}
|
||||
state = 0;
|
||||
entity.Length = 0;
|
||||
digit_start = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (c == 'x' || c == 'X' && !hex_number)
|
||||
{
|
||||
digit_start = i;
|
||||
hex_number = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (Char.IsDigit(c))
|
||||
{
|
||||
if (digit_start == 0)
|
||||
digit_start = i;
|
||||
|
||||
number = number * (hex_number ? 16 : 10) + ((int)c - '0');
|
||||
break;
|
||||
}
|
||||
|
||||
if (hex_number)
|
||||
{
|
||||
if (c >= 'a' && c <= 'f')
|
||||
{
|
||||
number = number * 16 + 10 + ((int)c - 'a');
|
||||
break;
|
||||
}
|
||||
if (c >= 'A' && c <= 'F')
|
||||
{
|
||||
number = number * 16 + 10 + ((int)c - 'A');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
state = 2;
|
||||
if (digit_start > 0)
|
||||
{
|
||||
entity.Append(s, digit_start, i - digit_start);
|
||||
digit_start = 0;
|
||||
}
|
||||
|
||||
entity.Append(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (entity.Length > 0)
|
||||
{
|
||||
output.Append(entity);
|
||||
}
|
||||
else if (digit_start > 0)
|
||||
{
|
||||
output.Append(s, digit_start, s.Length - digit_start);
|
||||
}
|
||||
return output.ToString();
|
||||
}
|
||||
|
||||
public static QueryParamCollection ParseQueryString(string query)
|
||||
{
|
||||
return ParseQueryString(query, Encoding.UTF8);
|
||||
}
|
||||
|
||||
public static QueryParamCollection ParseQueryString(string query, Encoding encoding)
|
||||
{
|
||||
if (query == null)
|
||||
throw new ArgumentNullException("query");
|
||||
if (encoding == null)
|
||||
throw new ArgumentNullException("encoding");
|
||||
if (query.Length == 0 || (query.Length == 1 && query[0] == '?'))
|
||||
return new QueryParamCollection();
|
||||
if (query[0] == '?')
|
||||
query = query.Substring(1);
|
||||
|
||||
QueryParamCollection result = new QueryParamCollection();
|
||||
ParseQueryString(query, encoding, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static void ParseQueryString(string query, Encoding encoding, QueryParamCollection result)
|
||||
{
|
||||
if (query.Length == 0)
|
||||
return;
|
||||
|
||||
string decoded = HtmlDecode(query);
|
||||
int decodedLength = decoded.Length;
|
||||
int namePos = 0;
|
||||
bool first = true;
|
||||
while (namePos <= decodedLength)
|
||||
{
|
||||
int valuePos = -1, valueEnd = -1;
|
||||
for (int q = namePos; q < decodedLength; q++)
|
||||
{
|
||||
if (valuePos == -1 && decoded[q] == '=')
|
||||
{
|
||||
valuePos = q + 1;
|
||||
}
|
||||
else if (decoded[q] == '&')
|
||||
{
|
||||
valueEnd = q;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (first)
|
||||
{
|
||||
first = false;
|
||||
if (decoded[namePos] == '?')
|
||||
namePos++;
|
||||
}
|
||||
|
||||
string name, value;
|
||||
if (valuePos == -1)
|
||||
{
|
||||
name = null;
|
||||
valuePos = namePos;
|
||||
}
|
||||
else
|
||||
{
|
||||
name = UrlDecode(decoded.Substring(namePos, valuePos - namePos - 1), encoding);
|
||||
}
|
||||
if (valueEnd < 0)
|
||||
{
|
||||
namePos = -1;
|
||||
valueEnd = decoded.Length;
|
||||
}
|
||||
else
|
||||
{
|
||||
namePos = valueEnd + 1;
|
||||
}
|
||||
value = UrlDecode(decoded.Substring(valuePos, valueEnd - valuePos), encoding);
|
||||
|
||||
result.Add(name, value);
|
||||
if (namePos == -1)
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endregion // Methods
|
||||
}
|
||||
}
|
||||
11
MediaBrowser.Model/Services/IAsyncStreamWriter.cs
Normal file
11
MediaBrowser.Model/Services/IAsyncStreamWriter.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MediaBrowser.Model.Services
|
||||
{
|
||||
public interface IAsyncStreamWriter
|
||||
{
|
||||
Task WriteToAsync(Stream responseStream, CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
9
MediaBrowser.Model/Services/IHasHeaders.cs
Normal file
9
MediaBrowser.Model/Services/IHasHeaders.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MediaBrowser.Model.Services
|
||||
{
|
||||
public interface IHasHeaders
|
||||
{
|
||||
IDictionary<string, string> Headers { get; }
|
||||
}
|
||||
}
|
||||
21
MediaBrowser.Model/Services/IHasRequestFilter.cs
Normal file
21
MediaBrowser.Model/Services/IHasRequestFilter.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
|
||||
namespace MediaBrowser.Model.Services
|
||||
{
|
||||
public interface IHasRequestFilter
|
||||
{
|
||||
/// <summary>
|
||||
/// Order in which Request Filters are executed.
|
||||
/// <0 Executed before global request filters
|
||||
/// >0 Executed after global request filters
|
||||
/// </summary>
|
||||
int Priority { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The request filter is executed before the service.
|
||||
/// </summary>
|
||||
/// <param name="req">The http request wrapper</param>
|
||||
/// <param name="res">The http response wrapper</param>
|
||||
/// <param name="requestDto">The request DTO</param>
|
||||
void RequestFilter(IRequest req, IResponse res, object requestDto);
|
||||
}
|
||||
}
|
||||
45
MediaBrowser.Model/Services/IHttpRequest.cs
Normal file
45
MediaBrowser.Model/Services/IHttpRequest.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MediaBrowser.Model.Services
|
||||
{
|
||||
public interface IHttpRequest : IRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// The HttpResponse
|
||||
/// </summary>
|
||||
IHttpResponse HttpResponse { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The HTTP Verb
|
||||
/// </summary>
|
||||
string HttpMethod { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The IP Address of the X-Forwarded-For header, null if null or empty
|
||||
/// </summary>
|
||||
string XForwardedFor { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The Port number of the X-Forwarded-Port header, null if null or empty
|
||||
/// </summary>
|
||||
int? XForwardedPort { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The http or https scheme of the X-Forwarded-Proto header, null if null or empty
|
||||
/// </summary>
|
||||
string XForwardedProtocol { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The value of the X-Real-IP header, null if null or empty
|
||||
/// </summary>
|
||||
string XRealIp { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The value of the Accept HTTP Request Header
|
||||
/// </summary>
|
||||
string Accept { get; }
|
||||
}
|
||||
}
|
||||
24
MediaBrowser.Model/Services/IHttpResponse.cs
Normal file
24
MediaBrowser.Model/Services/IHttpResponse.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MediaBrowser.Model.Services
|
||||
{
|
||||
public interface IHttpResponse : IResponse
|
||||
{
|
||||
//ICookies Cookies { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new Set-Cookie instruction to Response
|
||||
/// </summary>
|
||||
/// <param name="cookie"></param>
|
||||
void SetCookie(Cookie cookie);
|
||||
|
||||
/// <summary>
|
||||
/// Removes all pending Set-Cookie instructions
|
||||
/// </summary>
|
||||
void ClearCookies();
|
||||
}
|
||||
}
|
||||
36
MediaBrowser.Model/Services/IHttpResult.cs
Normal file
36
MediaBrowser.Model/Services/IHttpResult.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MediaBrowser.Model.Services
|
||||
{
|
||||
public interface IHttpResult : IHasHeaders
|
||||
{
|
||||
/// <summary>
|
||||
/// The HTTP Response Status
|
||||
/// </summary>
|
||||
int Status { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The HTTP Response Status Code
|
||||
/// </summary>
|
||||
HttpStatusCode StatusCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The HTTP Response ContentType
|
||||
/// </summary>
|
||||
string ContentType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Response DTO
|
||||
/// </summary>
|
||||
object Response { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Holds the request call context
|
||||
/// </summary>
|
||||
IRequest RequestContext { get; set; }
|
||||
}
|
||||
}
|
||||
159
MediaBrowser.Model/Services/IRequest.cs
Normal file
159
MediaBrowser.Model/Services/IRequest.cs
Normal file
@@ -0,0 +1,159 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Model.IO;
|
||||
|
||||
namespace MediaBrowser.Model.Services
|
||||
{
|
||||
public interface IRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// The underlying ASP.NET or HttpListener HttpRequest
|
||||
/// </summary>
|
||||
object OriginalRequest { get; }
|
||||
|
||||
IResponse Response { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of the service being called (e.g. Request DTO Name)
|
||||
/// </summary>
|
||||
string OperationName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The Verb / HttpMethod or Action for this request
|
||||
/// </summary>
|
||||
string Verb { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The Request DTO, after it has been deserialized.
|
||||
/// </summary>
|
||||
object Dto { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The request ContentType
|
||||
/// </summary>
|
||||
string ContentType { get; }
|
||||
|
||||
bool IsLocal { get; }
|
||||
|
||||
string UserAgent { get; }
|
||||
|
||||
IDictionary<string, Cookie> Cookies { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The expected Response ContentType for this request
|
||||
/// </summary>
|
||||
string ResponseContentType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Attach any data to this request that all filters and services can access.
|
||||
/// </summary>
|
||||
Dictionary<string, object> Items { get; }
|
||||
|
||||
QueryParamCollection Headers { get; }
|
||||
|
||||
QueryParamCollection QueryString { get; }
|
||||
|
||||
Task<QueryParamCollection> GetFormData();
|
||||
|
||||
string RawUrl { get; }
|
||||
|
||||
string AbsoluteUri { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The Remote Ip as reported by Request.UserHostAddress
|
||||
/// </summary>
|
||||
string UserHostAddress { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The Remote Ip as reported by X-Forwarded-For, X-Real-IP or Request.UserHostAddress
|
||||
/// </summary>
|
||||
string RemoteIp { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The value of the Authorization Header used to send the Api Key, null if not available
|
||||
/// </summary>
|
||||
string Authorization { get; }
|
||||
|
||||
/// <summary>
|
||||
/// e.g. is https or not
|
||||
/// </summary>
|
||||
bool IsSecureConnection { get; }
|
||||
|
||||
string[] AcceptTypes { get; }
|
||||
|
||||
string PathInfo { get; }
|
||||
|
||||
Stream InputStream { get; }
|
||||
|
||||
long ContentLength { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Access to the multi-part/formdata files posted on this request
|
||||
/// </summary>
|
||||
IHttpFile[] Files { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The value of the Referrer, null if not available
|
||||
/// </summary>
|
||||
Uri UrlReferrer { get; }
|
||||
}
|
||||
|
||||
public interface IHttpFile
|
||||
{
|
||||
string Name { get; }
|
||||
string FileName { get; }
|
||||
long ContentLength { get; }
|
||||
string ContentType { get; }
|
||||
Stream InputStream { get; }
|
||||
}
|
||||
|
||||
public interface IRequiresRequest
|
||||
{
|
||||
IRequest Request { get; set; }
|
||||
}
|
||||
|
||||
public interface IResponse
|
||||
{
|
||||
IRequest Request { get; }
|
||||
|
||||
int StatusCode { get; set; }
|
||||
|
||||
string StatusDescription { get; set; }
|
||||
|
||||
string ContentType { get; set; }
|
||||
|
||||
void AddHeader(string name, string value);
|
||||
|
||||
string GetHeader(string name);
|
||||
|
||||
void Redirect(string url);
|
||||
|
||||
Stream OutputStream { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Signal that this response has been handled and no more processing should be done.
|
||||
/// When used in a request or response filter, no more filters or processing is done on this request.
|
||||
/// </summary>
|
||||
void Close();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance is closed.
|
||||
/// </summary>
|
||||
bool IsClosed { get; }
|
||||
|
||||
void SetContentLength(long contentLength);
|
||||
|
||||
//Add Metadata to Response
|
||||
Dictionary<string, object> Items { get; }
|
||||
|
||||
QueryParamCollection Headers { get; }
|
||||
|
||||
Task TransmitFile(string path, long offset, long count, FileShareMode fileShareMode, CancellationToken cancellationToken);
|
||||
|
||||
bool SendChunked { get; set; }
|
||||
}
|
||||
}
|
||||
12
MediaBrowser.Model/Services/IRequiresRequestStream.cs
Normal file
12
MediaBrowser.Model/Services/IRequiresRequestStream.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using System.IO;
|
||||
|
||||
namespace MediaBrowser.Model.Services
|
||||
{
|
||||
public interface IRequiresRequestStream
|
||||
{
|
||||
/// <summary>
|
||||
/// The raw Http Request Input Stream
|
||||
/// </summary>
|
||||
Stream RequestStream { get; set; }
|
||||
}
|
||||
}
|
||||
12
MediaBrowser.Model/Services/IService.cs
Normal file
12
MediaBrowser.Model/Services/IService.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
namespace MediaBrowser.Model.Services
|
||||
{
|
||||
// marker interface
|
||||
public interface IService
|
||||
{
|
||||
}
|
||||
|
||||
public interface IReturn { }
|
||||
public interface IReturn<T> : IReturn { }
|
||||
public interface IReturnVoid : IReturn { }
|
||||
}
|
||||
9
MediaBrowser.Model/Services/IStreamWriter.cs
Normal file
9
MediaBrowser.Model/Services/IStreamWriter.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using System.IO;
|
||||
|
||||
namespace MediaBrowser.Model.Services
|
||||
{
|
||||
public interface IStreamWriter
|
||||
{
|
||||
void WriteTo(Stream responseStream);
|
||||
}
|
||||
}
|
||||
229
MediaBrowser.Model/Services/QueryParamCollection.cs
Normal file
229
MediaBrowser.Model/Services/QueryParamCollection.cs
Normal file
@@ -0,0 +1,229 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.Extensions;
|
||||
|
||||
namespace MediaBrowser.Model.Services
|
||||
{
|
||||
public class QueryParamCollection : List<NameValuePair>
|
||||
{
|
||||
public QueryParamCollection()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public QueryParamCollection(IDictionary<string, string> headers)
|
||||
{
|
||||
foreach (var pair in headers)
|
||||
{
|
||||
Add(pair.Key, pair.Value);
|
||||
}
|
||||
}
|
||||
|
||||
private StringComparison GetStringComparison()
|
||||
{
|
||||
return StringComparison.OrdinalIgnoreCase;
|
||||
}
|
||||
|
||||
private StringComparer GetStringComparer()
|
||||
{
|
||||
return StringComparer.OrdinalIgnoreCase;
|
||||
}
|
||||
|
||||
public string GetKey(int index)
|
||||
{
|
||||
return this[index].Name;
|
||||
}
|
||||
|
||||
public string Get(int index)
|
||||
{
|
||||
return this[index].Value;
|
||||
}
|
||||
|
||||
public virtual string[] GetValues(int index)
|
||||
{
|
||||
return new[] { Get(index) };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new query parameter.
|
||||
/// </summary>
|
||||
public virtual void Add(string key, string value)
|
||||
{
|
||||
Add(new NameValuePair(key, value));
|
||||
}
|
||||
|
||||
public virtual void Set(string key, string value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
var parameters = GetItems(key);
|
||||
|
||||
foreach (var p in parameters)
|
||||
{
|
||||
Remove(p);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var pair in this)
|
||||
{
|
||||
var stringComparison = GetStringComparison();
|
||||
|
||||
if (string.Equals(key, pair.Name, stringComparison))
|
||||
{
|
||||
pair.Value = value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Add(key, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all parameters of the given name.
|
||||
/// </summary>
|
||||
/// <returns>The number of parameters that were removed</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="name" /> is null.</exception>
|
||||
public virtual int Remove(string name)
|
||||
{
|
||||
return RemoveAll(p => p.Name == name);
|
||||
}
|
||||
|
||||
public string Get(string name)
|
||||
{
|
||||
var stringComparison = GetStringComparison();
|
||||
|
||||
foreach (var pair in this)
|
||||
{
|
||||
if (string.Equals(pair.Name, name, stringComparison))
|
||||
{
|
||||
return pair.Value;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public virtual List<NameValuePair> GetItems(string name)
|
||||
{
|
||||
var stringComparison = GetStringComparison();
|
||||
|
||||
var list = new List<NameValuePair>();
|
||||
|
||||
foreach (var pair in this)
|
||||
{
|
||||
if (string.Equals(pair.Name, name, stringComparison))
|
||||
{
|
||||
list.Add(pair);
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public virtual List<string> GetValues(string name)
|
||||
{
|
||||
var stringComparison = GetStringComparison();
|
||||
|
||||
var list = new List<string>();
|
||||
|
||||
foreach (var pair in this)
|
||||
{
|
||||
if (string.Equals(pair.Name, name, stringComparison))
|
||||
{
|
||||
list.Add(pair.Value);
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public Dictionary<string, string> ToDictionary()
|
||||
{
|
||||
var stringComparer = GetStringComparer();
|
||||
|
||||
var headers = new Dictionary<string, string>(stringComparer);
|
||||
|
||||
foreach (var pair in this)
|
||||
{
|
||||
headers[pair.Name] = pair.Value;
|
||||
}
|
||||
|
||||
return headers;
|
||||
}
|
||||
|
||||
public IEnumerable<string> Keys
|
||||
{
|
||||
get
|
||||
{
|
||||
var keys = new string[this.Count];
|
||||
|
||||
for (var i = 0; i < keys.Length; i++)
|
||||
{
|
||||
keys[i] = this[i].Name;
|
||||
}
|
||||
|
||||
return keys;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a query parameter value by name. A query may contain multiple values of the same name
|
||||
/// (i.e. "x=1&x=2"), in which case the value is an array, which works for both getting and setting.
|
||||
/// </summary>
|
||||
/// <param name="name">The query parameter name</param>
|
||||
/// <returns>The query parameter value or array of values</returns>
|
||||
public string this[string name]
|
||||
{
|
||||
get { return Get(name); }
|
||||
set
|
||||
{
|
||||
Set(name, value);
|
||||
//var parameters = this.Where(p => p.Name == name).ToArray();
|
||||
//var values = new[] { value };
|
||||
|
||||
//for (int i = 0; ; i++)
|
||||
//{
|
||||
// if (i < parameters.Length && i < values.Length)
|
||||
// {
|
||||
// if (values[i] == null)
|
||||
// Remove(parameters[i]);
|
||||
// else if (values[i] is NameValuePair)
|
||||
// this[IndexOf(parameters[i])] = (NameValuePair)values[i];
|
||||
// else
|
||||
// parameters[i].Value = values[i];
|
||||
// }
|
||||
// else if (i < parameters.Length)
|
||||
// Remove(parameters[i]);
|
||||
// else if (i < values.Length)
|
||||
// {
|
||||
// if (values[i] != null)
|
||||
// {
|
||||
// if (values[i] is NameValuePair)
|
||||
// Add((NameValuePair)values[i]);
|
||||
// else
|
||||
// Add(name, values[i]);
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// break;
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
private string GetQueryStringValue(NameValuePair pair)
|
||||
{
|
||||
return pair.Name + "=" + pair.Value;
|
||||
}
|
||||
|
||||
public override String ToString()
|
||||
{
|
||||
var vals = this.Select(GetQueryStringValue).ToArray(this.Count);
|
||||
|
||||
return string.Join("&", vals);
|
||||
}
|
||||
}
|
||||
}
|
||||
148
MediaBrowser.Model/Services/RouteAttribute.cs
Normal file
148
MediaBrowser.Model/Services/RouteAttribute.cs
Normal file
@@ -0,0 +1,148 @@
|
||||
using System;
|
||||
|
||||
namespace MediaBrowser.Model.Services
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
|
||||
public class RouteAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// <para>Initializes an instance of the <see cref="RouteAttribute"/> class.</para>
|
||||
/// </summary>
|
||||
/// <param name="path">
|
||||
/// <para>The path template to map to the request. See
|
||||
/// <see cref="Path">RouteAttribute.Path</see>
|
||||
/// for details on the correct format.</para>
|
||||
/// </param>
|
||||
public RouteAttribute(string path)
|
||||
: this(path, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>Initializes an instance of the <see cref="RouteAttribute"/> class.</para>
|
||||
/// </summary>
|
||||
/// <param name="path">
|
||||
/// <para>The path template to map to the request. See
|
||||
/// <see cref="Path">RouteAttribute.Path</see>
|
||||
/// for details on the correct format.</para>
|
||||
/// </param>
|
||||
/// <param name="verbs">A comma-delimited list of HTTP verbs supported by the
|
||||
/// service. If unspecified, all verbs are assumed to be supported.</param>
|
||||
public RouteAttribute(string path, string verbs)
|
||||
{
|
||||
Path = path;
|
||||
Verbs = verbs;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the path template to be mapped to the request.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="String"/> value providing the path mapped to
|
||||
/// the request. Never <see langword="null"/>.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// <para>Some examples of valid paths are:</para>
|
||||
///
|
||||
/// <list>
|
||||
/// <item>"/Inventory"</item>
|
||||
/// <item>"/Inventory/{Category}/{ItemId}"</item>
|
||||
/// <item>"/Inventory/{ItemPath*}"</item>
|
||||
/// </list>
|
||||
///
|
||||
/// <para>Variables are specified within "{}"
|
||||
/// brackets. Each variable in the path is mapped to the same-named property
|
||||
/// on the request DTO. At runtime, ServiceStack will parse the
|
||||
/// request URL, extract the variable values, instantiate the request DTO,
|
||||
/// and assign the variable values into the corresponding request properties,
|
||||
/// prior to passing the request DTO to the service object for processing.</para>
|
||||
///
|
||||
/// <para>It is not necessary to specify all request properties as
|
||||
/// variables in the path. For unspecified properties, callers may provide
|
||||
/// values in the query string. For example: the URL
|
||||
/// "http://services/Inventory?Category=Books&ItemId=12345" causes the same
|
||||
/// request DTO to be processed as "http://services/Inventory/Books/12345",
|
||||
/// provided that the paths "/Inventory" (which supports the first URL) and
|
||||
/// "/Inventory/{Category}/{ItemId}" (which supports the second URL)
|
||||
/// are both mapped to the request DTO.</para>
|
||||
///
|
||||
/// <para>Please note that while it is possible to specify property values
|
||||
/// in the query string, it is generally considered to be less RESTful and
|
||||
/// less desirable than to specify them as variables in the path. Using the
|
||||
/// query string to specify property values may also interfere with HTTP
|
||||
/// caching.</para>
|
||||
///
|
||||
/// <para>The final variable in the path may contain a "*" suffix
|
||||
/// to grab all remaining segments in the path portion of the request URL and assign
|
||||
/// them to a single property on the request DTO.
|
||||
/// For example, if the path "/Inventory/{ItemPath*}" is mapped to the request DTO,
|
||||
/// then the request URL "http://services/Inventory/Books/12345" will result
|
||||
/// in a request DTO whose ItemPath property contains "Books/12345".
|
||||
/// You may only specify one such variable in the path, and it must be positioned at
|
||||
/// the end of the path.</para>
|
||||
/// </remarks>
|
||||
public string Path { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets short summary of what the route does.
|
||||
/// </summary>
|
||||
public string Summary { get; set; }
|
||||
|
||||
public string Description { get; set; }
|
||||
|
||||
public bool IsHidden { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets longer text to explain the behaviour of the route.
|
||||
/// </summary>
|
||||
public string Notes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a comma-delimited list of HTTP verbs supported by the service, such as
|
||||
/// "GET,PUT,POST,DELETE".
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="String"/> providing a comma-delimited list of HTTP verbs supported
|
||||
/// by the service, <see langword="null"/> or empty if all verbs are supported.
|
||||
/// </value>
|
||||
public string Verbs { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Used to rank the precedences of route definitions in reverse routing.
|
||||
/// i.e. Priorities below 0 are auto-generated have less precedence.
|
||||
/// </summary>
|
||||
public int Priority { get; set; }
|
||||
|
||||
protected bool Equals(RouteAttribute other)
|
||||
{
|
||||
return base.Equals(other)
|
||||
&& string.Equals(Path, other.Path)
|
||||
&& string.Equals(Summary, other.Summary)
|
||||
&& string.Equals(Notes, other.Notes)
|
||||
&& string.Equals(Verbs, other.Verbs)
|
||||
&& Priority == other.Priority;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
if (ReferenceEquals(this, obj)) return true;
|
||||
if (obj.GetType() != this.GetType()) return false;
|
||||
return Equals((RouteAttribute)obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
var hashCode = base.GetHashCode();
|
||||
hashCode = (hashCode * 397) ^ (Path != null ? Path.GetHashCode() : 0);
|
||||
hashCode = (hashCode * 397) ^ (Summary != null ? Summary.GetHashCode() : 0);
|
||||
hashCode = (hashCode * 397) ^ (Notes != null ? Notes.GetHashCode() : 0);
|
||||
hashCode = (hashCode * 397) ^ (Verbs != null ? Verbs.GetHashCode() : 0);
|
||||
hashCode = (hashCode * 397) ^ Priority;
|
||||
return hashCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user