Merge branch 'master' into h265

This commit is contained in:
Joshua M. Boniface
2019-08-19 14:57:48 -04:00
committed by GitHub
333 changed files with 9061 additions and 14665 deletions

View File

@@ -1,11 +0,0 @@
namespace MediaBrowser.Model.Configuration
{
public class FanartOptions
{
/// <summary>
/// Gets or sets the user API key.
/// </summary>
/// <value>The user API key.</value>
public string UserApiKey { get; set; }
}
}

View File

@@ -49,9 +49,9 @@ namespace MediaBrowser.Model.Configuration
public bool EnableNormalizedItemByNameIds { get; set; }
/// <summary>
/// Gets or sets the value pointing to the file system where the ssl certiifcate is located..
/// Gets or sets the value pointing to the file system where the ssl certificate is located..
/// </summary>
/// <value>The value pointing to the file system where the ssl certiifcate is located..</value>
/// <value>The value pointing to the file system where the ssl certificate is located..</value>
public string CertificatePath { get; set; }
public string CertificatePassword { get; set; }
@@ -163,6 +163,7 @@ namespace MediaBrowser.Model.Configuration
public string ServerName { get; set; }
public string WanDdns { get; set; }
public string BaseUrl { get; set; }
public string UICulture { get; set; }
@@ -243,6 +244,7 @@ namespace MediaBrowser.Model.Configuration
SortRemoveCharacters = new[] { ",", "&", "-", "{", "}", "'" };
SortRemoveWords = new[] { "the", "a", "an" };
BaseUrl = "jellyfin";
UICulture = "en-US";
MetadataOptions = new[]
@@ -259,7 +261,7 @@ namespace MediaBrowser.Model.Configuration
{
ItemType = "MusicVideo",
DisabledMetadataFetchers = new [] { "The Open Movie Database" },
DisabledImageFetchers = new [] { "The Open Movie Database", "FanArt" }
DisabledImageFetchers = new [] { "The Open Movie Database" }
},
new MetadataOptions
{
@@ -285,7 +287,6 @@ namespace MediaBrowser.Model.Configuration
{
ItemType = "Season",
DisabledMetadataFetchers = new [] { "TheMovieDb" },
DisabledImageFetchers = new [] { "FanArt" }
},
new MetadataOptions
{

View File

@@ -6,9 +6,14 @@ namespace MediaBrowser.Model.Cryptography
{
public interface ICryptoProvider
{
string DefaultHashMethod { get; }
[Obsolete("Use System.Security.Cryptography.MD5 directly")]
Guid GetMD5(string str);
[Obsolete("Use System.Security.Cryptography.MD5 directly")]
byte[] ComputeMD5(Stream str);
[Obsolete("Use System.Security.Cryptography.MD5 directly")]
byte[] ComputeMD5(byte[] bytes);
[Obsolete("Use System.Security.Cryptography.SHA1 directly")]
byte[] ComputeSHA1(byte[] bytes);
IEnumerable<string> GetSupportedHashMethods();
byte[] ComputeHash(string HashMethod, byte[] bytes);
@@ -17,6 +22,5 @@ namespace MediaBrowser.Model.Cryptography
byte[] ComputeHashWithDefaultMethod(byte[] bytes, byte[] salt);
byte[] ComputeHash(PasswordHash hash);
byte[] GenerateSalt();
string DefaultHashMethod { get; }
}
}

View File

@@ -1,153 +1,142 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace MediaBrowser.Model.Cryptography
{
public class PasswordHash
{
// Defined from this hash storage spec
// https://github.com/P-H-C/phc-string-format/blob/master/phc-sf-spec.md
// $<id>[$<param>=<value>(,<param>=<value>)*][$<salt>[$<hash>]]
// with one slight amendment to ease the transition, we're writing out the bytes in hex
// rather than making them a BASE64 string with stripped padding
private string _id;
private Dictionary<string, string> _parameters = new Dictionary<string, string>();
private string _salt;
private byte[] _saltBytes;
private string _hash;
private byte[] _hashBytes;
public string Id { get => _id; set => _id = value; }
public Dictionary<string, string> Parameters { get => _parameters; set => _parameters = value; }
public string Salt { get => _salt; set => _salt = value; }
public byte[] SaltBytes { get => _saltBytes; set => _saltBytes = value; }
public string Hash { get => _hash; set => _hash = value; }
public byte[] HashBytes { get => _hashBytes; set => _hashBytes = value; }
public PasswordHash(string storageString)
{
string[] splitted = storageString.Split('$');
_id = splitted[1];
if (splitted[2].Contains("="))
{
foreach (string paramset in (splitted[2].Split(',')))
{
if (!string.IsNullOrEmpty(paramset))
{
string[] fields = paramset.Split('=');
if (fields.Length == 2)
{
_parameters.Add(fields[0], fields[1]);
}
else
{
throw new Exception($"Malformed parameter in password hash string {paramset}");
}
}
}
if (splitted.Length == 5)
{
_salt = splitted[3];
_saltBytes = ConvertFromByteString(_salt);
_hash = splitted[4];
_hashBytes = ConvertFromByteString(_hash);
}
else
{
_salt = string.Empty;
_hash = splitted[3];
_hashBytes = ConvertFromByteString(_hash);
}
}
else
{
if (splitted.Length == 4)
{
_salt = splitted[2];
_saltBytes = ConvertFromByteString(_salt);
_hash = splitted[3];
_hashBytes = ConvertFromByteString(_hash);
}
else
{
_salt = string.Empty;
_hash = splitted[2];
_hashBytes = ConvertFromByteString(_hash);
}
}
}
public PasswordHash(ICryptoProvider cryptoProvider)
{
_id = cryptoProvider.DefaultHashMethod;
_saltBytes = cryptoProvider.GenerateSalt();
_salt = ConvertToByteString(SaltBytes);
}
public static byte[] ConvertFromByteString(string byteString)
{
byte[] bytes = new byte[byteString.Length / 2];
for (int i = 0; i < byteString.Length; i += 2)
{
// TODO: NetStandard2.1 switch this to use a span instead of a substring.
bytes[i / 2] = Convert.ToByte(byteString.Substring(i, 2), 16);
}
return bytes;
}
public static string ConvertToByteString(byte[] bytes)
{
return BitConverter.ToString(bytes).Replace("-", "");
}
private string SerializeParameters()
{
string returnString = string.Empty;
foreach (var KVP in _parameters)
{
returnString += $",{KVP.Key}={KVP.Value}";
}
if ((!string.IsNullOrEmpty(returnString)) && returnString[0] == ',')
{
returnString = returnString.Remove(0, 1);
}
return returnString;
}
public override string ToString()
{
string outString = "$" + _id;
string paramstring = SerializeParameters();
if (!string.IsNullOrEmpty(paramstring))
{
outString += $"${paramstring}";
}
if (!string.IsNullOrEmpty(_salt))
{
outString += $"${_salt}";
}
outString += $"${_hash}";
return outString;
}
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace MediaBrowser.Model.Cryptography
{
public class PasswordHash
{
// Defined from this hash storage spec
// https://github.com/P-H-C/phc-string-format/blob/master/phc-sf-spec.md
// $<id>[$<param>=<value>(,<param>=<value>)*][$<salt>[$<hash>]]
// with one slight amendment to ease the transition, we're writing out the bytes in hex
// rather than making them a BASE64 string with stripped padding
private string _id;
private Dictionary<string, string> _parameters = new Dictionary<string, string>();
private byte[] _salt;
private byte[] _hash;
public PasswordHash(string storageString)
{
string[] splitted = storageString.Split('$');
// The string should at least contain the hash function and the hash itself
if (splitted.Length < 3)
{
throw new ArgumentException("String doesn't contain enough segments", nameof(storageString));
}
// Start at 1, the first index shouldn't contain any data
int index = 1;
// Name of the hash function
_id = splitted[index++];
// Optional parameters
if (splitted[index].IndexOf('=') != -1)
{
foreach (string paramset in splitted[index++].Split(','))
{
if (string.IsNullOrEmpty(paramset))
{
continue;
}
string[] fields = paramset.Split('=');
if (fields.Length != 2)
{
throw new InvalidDataException($"Malformed parameter in password hash string {paramset}");
}
_parameters.Add(fields[0], fields[1]);
}
}
// Check if the string also contains a salt
if (splitted.Length - index == 2)
{
_salt = ConvertFromByteString(splitted[index++]);
_hash = ConvertFromByteString(splitted[index++]);
}
else
{
_salt = Array.Empty<byte>();
_hash = ConvertFromByteString(splitted[index++]);
}
}
public string Id { get => _id; set => _id = value; }
public Dictionary<string, string> Parameters { get => _parameters; set => _parameters = value; }
public byte[] Salt { get => _salt; set => _salt = value; }
public byte[] Hash { get => _hash; set => _hash = value; }
public PasswordHash(ICryptoProvider cryptoProvider)
{
_id = cryptoProvider.DefaultHashMethod;
_salt = cryptoProvider.GenerateSalt();
_hash = Array.Empty<Byte>();
}
// TODO: move this class and use the HexHelper class
public static byte[] ConvertFromByteString(string byteString)
{
byte[] bytes = new byte[byteString.Length / 2];
for (int i = 0; i < byteString.Length; i += 2)
{
// TODO: NetStandard2.1 switch this to use a span instead of a substring.
bytes[i / 2] = Convert.ToByte(byteString.Substring(i, 2), 16);
}
return bytes;
}
public static string ConvertToByteString(byte[] bytes)
=> BitConverter.ToString(bytes).Replace("-", string.Empty);
private void SerializeParameters(StringBuilder stringBuilder)
{
if (_parameters.Count == 0)
{
return;
}
stringBuilder.Append('$');
foreach (var pair in _parameters)
{
stringBuilder.Append(pair.Key);
stringBuilder.Append('=');
stringBuilder.Append(pair.Value);
stringBuilder.Append(',');
}
// Remove last ','
stringBuilder.Length -= 1;
}
public override string ToString()
{
var str = new StringBuilder();
str.Append('$');
str.Append(_id);
SerializeParameters(str);
if (_salt.Length == 0)
{
str.Append('$');
str.Append(ConvertToByteString(_salt));
}
str.Append('$');
str.Append(ConvertToByteString(_hash));
return str.ToString();
}
}
}

View File

@@ -13,7 +13,8 @@ namespace MediaBrowser.Model.Dlna
_profile = profile;
}
public string BuildImageHeader(string container,
public string BuildImageHeader(
string container,
int? width,
int? height,
bool isDirectStream,
@@ -28,8 +29,7 @@ namespace MediaBrowser.Model.Dlna
DlnaFlags.InteractiveTransferMode |
DlnaFlags.DlnaV15;
string dlnaflags = string.Format(";DLNA.ORG_FLAGS={0}",
DlnaMaps.FlagsToString(flagValue));
string dlnaflags = string.Format(";DLNA.ORG_FLAGS={0}", DlnaMaps.FlagsToString(flagValue));
ResponseProfile mediaProfile = _profile.GetImageMediaProfile(container,
width,
@@ -37,7 +37,7 @@ namespace MediaBrowser.Model.Dlna
if (string.IsNullOrEmpty(orgPn))
{
orgPn = mediaProfile == null ? null : mediaProfile.OrgPn;
orgPn = mediaProfile?.OrgPn;
}
if (string.IsNullOrEmpty(orgPn))
@@ -50,7 +50,8 @@ namespace MediaBrowser.Model.Dlna
return (contentFeatures + orgOp + orgCi + dlnaflags).Trim(';');
}
public string BuildAudioHeader(string container,
public string BuildAudioHeader(
string container,
string audioCodec,
int? audioBitrate,
int? audioSampleRate,
@@ -102,7 +103,8 @@ namespace MediaBrowser.Model.Dlna
return (contentFeatures + orgOp + orgCi + dlnaflags).Trim(';');
}
public List<string> BuildVideoHeader(string container,
public List<string> BuildVideoHeader(
string container,
string videoCodec,
string audioCodec,
int? width,
@@ -206,7 +208,7 @@ namespace MediaBrowser.Model.Dlna
return contentFeatureList;
}
private string GetImageOrgPnValue(string container, int? width, int? height)
private static string GetImageOrgPnValue(string container, int? width, int? height)
{
MediaFormatProfile? format = new MediaFormatProfileResolver()
.ResolveImageFormat(container,
@@ -216,7 +218,7 @@ namespace MediaBrowser.Model.Dlna
return format.HasValue ? format.Value.ToString() : null;
}
private string GetAudioOrgPnValue(string container, int? audioBitrate, int? audioSampleRate, int? audioChannels)
private static string GetAudioOrgPnValue(string container, int? audioBitrate, int? audioSampleRate, int? audioChannels)
{
MediaFormatProfile? format = new MediaFormatProfileResolver()
.ResolveAudioFormat(container,
@@ -227,7 +229,7 @@ namespace MediaBrowser.Model.Dlna
return format.HasValue ? format.Value.ToString() : null;
}
private string[] GetVideoOrgPnValue(string container, string videoCodec, string audioCodec, int? width, int? height, TransportStreamTimestamp timestamp)
private static string[] GetVideoOrgPnValue(string container, string videoCodec, string audioCodec, int? width, int? height, TransportStreamTimestamp timestamp)
{
return new MediaFormatProfileResolver().ResolveVideoFormat(container, videoCodec, audioCodec, width, height, timestamp);
}

View File

@@ -1,6 +1,6 @@
using System;
using System.Collections.Generic;
using MediaBrowser.Model.Net;
using System.Net;
namespace MediaBrowser.Model.Dlna
{
@@ -8,7 +8,7 @@ namespace MediaBrowser.Model.Dlna
{
public Uri Location { get; set; }
public Dictionary<string, string> Headers { get; set; }
public IpAddressInfo LocalIpAddress { get; set; }
public IPAddress LocalIpAddress { get; set; }
public int LocalPort { get; set; }
}
}

View File

@@ -38,6 +38,7 @@ namespace MediaBrowser.Model.Globalization
{
return vals[0];
}
return null;
}
}

View File

@@ -1,6 +1,5 @@
using System.Collections.Generic;
using System.Globalization;
using System.Threading.Tasks;
using MediaBrowser.Model.Entities;
namespace MediaBrowser.Model.Globalization
@@ -13,23 +12,26 @@ namespace MediaBrowser.Model.Globalization
/// <summary>
/// Gets the cultures.
/// </summary>
/// <returns>IEnumerable{CultureDto}.</returns>
CultureDto[] GetCultures();
/// <returns><see cref="IEnumerable{CultureDto}" />.</returns>
IEnumerable<CultureDto> GetCultures();
/// <summary>
/// Gets the countries.
/// </summary>
/// <returns>IEnumerable{CountryInfo}.</returns>
Task<CountryInfo[]> GetCountries();
/// <returns><see cref="IEnumerable{CountryInfo}" />.</returns>
IEnumerable<CountryInfo> GetCountries();
/// <summary>
/// Gets the parental ratings.
/// </summary>
/// <returns>IEnumerable{ParentalRating}.</returns>
/// <returns><see cref="IEnumerable{ParentalRating}" />.</returns>
IEnumerable<ParentalRating> GetParentalRatings();
/// <summary>
/// Gets the rating level.
/// </summary>
/// <param name="rating">The rating.</param>
/// <returns>System.Int32.</returns>
/// <returns><see cref="int" /> or <c>null</c>.</returns>
int? GetRatingLevel(string rating);
/// <summary>
@@ -37,7 +39,7 @@ namespace MediaBrowser.Model.Globalization
/// </summary>
/// <param name="phrase">The phrase.</param>
/// <param name="culture">The culture.</param>
/// <returns>System.String.</returns>
/// <returns><see cref="string" />.</returns>
string GetLocalizedString(string phrase, string culture);
/// <summary>
@@ -50,13 +52,22 @@ namespace MediaBrowser.Model.Globalization
/// <summary>
/// Gets the localization options.
/// </summary>
/// <returns>IEnumerable{LocalizatonOption}.</returns>
LocalizationOption[] GetLocalizationOptions();
string NormalizeFormKD(string text);
/// <returns><see cref="IEnumerable{LocalizatonOption}" />.</returns>
IEnumerable<LocalizationOption> GetLocalizationOptions();
/// <summary>
/// Checks if the string contains a character with the specified unicode category.
/// </summary>
/// <param name="value">The string.</param>
/// <param name="category">The unicode category.</param>
/// <returns>Wether or not the string contains a character with the specified unicode category.</returns>
bool HasUnicodeCategory(string value, UnicodeCategory category);
/// <summary>
/// Returns the correct <see cref="Cultureinfo" /> for the given language.
/// </summary>
/// <param name="language">The language.</param>
/// <returns>The correct <see cref="Cultureinfo" /> for the given language.</returns>
CultureDto FindLanguageInfo(string language);
}
}

View File

@@ -6,7 +6,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Model.IO
{
public interface IIsoManager : IDisposable
public interface IIsoManager
{
/// <summary>
/// Mounts the specified iso path.

View File

@@ -5,7 +5,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Model.IO
{
public interface IIsoMounter : IDisposable
public interface IIsoMounter
{
/// <summary>
/// Mounts the specified iso path.

View File

@@ -13,6 +13,6 @@ namespace MediaBrowser.Model.IO
/// <summary>
/// The default file stream buffer size
/// </summary>
public const int DefaultFileStreamBufferSize = 81920;
public const int DefaultFileStreamBufferSize = 4096;
}
}

View File

@@ -10,6 +10,7 @@
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<ItemGroup>

View File

@@ -1,4 +1,5 @@
using System;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
@@ -9,7 +10,7 @@ namespace MediaBrowser.Model.Net
/// </summary>
public interface ISocket : IDisposable
{
IpAddressInfo LocalIPAddress { get; }
IPAddress LocalIPAddress { get; }
Task<SocketReceiveResult> ReceiveAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken);
@@ -21,6 +22,6 @@ namespace MediaBrowser.Model.Net
/// <summary>
/// Sends a UDP message to a particular end point (uni or multicast).
/// </summary>
Task SendToAsync(byte[] buffer, int offset, int bytes, IpEndPointInfo endPoint, CancellationToken cancellationToken);
Task SendToAsync(byte[] buffer, int offset, int bytes, IPEndPoint endPoint, CancellationToken cancellationToken);
}
}

View File

@@ -1,4 +1,5 @@
using System.IO;
using System.Net;
namespace MediaBrowser.Model.Net
{
@@ -8,7 +9,7 @@ namespace MediaBrowser.Model.Net
public interface ISocketFactory
{
/// <summary>
/// Createa a new unicast socket using the specified local port number.
/// Creates a new unicast socket using the specified local port number.
/// </summary>
/// <param name="localPort">The local port to bind to.</param>
/// <returns>A <see cref="ISocket"/> implementation.</returns>
@@ -16,15 +17,13 @@ namespace MediaBrowser.Model.Net
ISocket CreateUdpBroadcastSocket(int localPort);
ISocket CreateTcpSocket(IpAddressInfo remoteAddress, int remotePort);
/// <summary>
/// Createa a new unicast socket using the specified local port number.
/// Creates a new unicast socket using the specified local port number.
/// </summary>
ISocket CreateSsdpUdpSocket(IpAddressInfo localIp, int localPort);
ISocket CreateSsdpUdpSocket(IPAddress localIp, int localPort);
/// <summary>
/// Createa a new multicast socket using the specified multicast IP address, multicast time to live and local port.
/// Creates a new multicast socket using the specified multicast IP address, multicast time to live and local port.
/// </summary>
/// <param name="ipAddress">The multicast IP address to bind to.</param>
/// <param name="multicastTimeToLive">The multicast time to live value. Actually a maximum number of network hops for UDP packets.</param>
@@ -34,14 +33,4 @@ namespace MediaBrowser.Model.Net
Stream CreateNetworkStream(ISocket socket, bool ownsSocket);
}
public enum SocketType
{
Stream
}
public enum ProtocolType
{
Tcp
}
}

View File

@@ -1,38 +0,0 @@
using System;
namespace MediaBrowser.Model.Net
{
public class IpAddressInfo
{
public static IpAddressInfo Any = new IpAddressInfo("0.0.0.0", IpAddressFamily.InterNetwork);
public static IpAddressInfo IPv6Any = new IpAddressInfo("00000000000000000000", IpAddressFamily.InterNetworkV6);
public static IpAddressInfo Loopback = new IpAddressInfo("127.0.0.1", IpAddressFamily.InterNetwork);
public static IpAddressInfo IPv6Loopback = new IpAddressInfo("::1", IpAddressFamily.InterNetworkV6);
public string Address { get; set; }
public IpAddressInfo SubnetMask { get; set; }
public IpAddressFamily AddressFamily { get; set; }
public IpAddressInfo(string address, IpAddressFamily addressFamily)
{
Address = address;
AddressFamily = addressFamily;
}
public bool Equals(IpAddressInfo address)
{
return string.Equals(address.Address, Address, StringComparison.OrdinalIgnoreCase);
}
public override string ToString()
{
return Address;
}
}
public enum IpAddressFamily
{
InterNetwork,
InterNetworkV6
}
}

View File

@@ -1,29 +0,0 @@
using System.Globalization;
namespace MediaBrowser.Model.Net
{
public class IpEndPointInfo
{
public IpAddressInfo IpAddress { get; set; }
public int Port { get; set; }
public IpEndPointInfo()
{
}
public IpEndPointInfo(IpAddressInfo address, int port)
{
IpAddress = address;
Port = port;
}
public override string ToString()
{
var ipAddresString = IpAddress == null ? string.Empty : IpAddress.ToString();
return ipAddresString + ":" + Port.ToString(CultureInfo.InvariantCulture);
}
}
}

View File

@@ -12,113 +12,133 @@ namespace MediaBrowser.Model.Net
public static class MimeTypes
{
/// <summary>
/// Any extension in this list is considered a video file - can be added to at runtime for extensibility
/// Any extension in this list is considered a video file
/// </summary>
private static readonly string[] VideoFileExtensions = new string[]
{
".mkv",
".m2t",
".m2ts",
".img",
".iso",
".mk3d",
".ts",
".rmvb",
".mov",
".avi",
".mpg",
".mpeg",
".wmv",
".mp4",
".divx",
".dvr-ms",
".wtv",
".ogm",
".ogv",
".asf",
".m4v",
".flv",
".f4v",
".3gp",
".webm",
".mts",
".m2v",
".rec"
};
private static Dictionary<string, string> GetVideoFileExtensionsDictionary()
private static readonly HashSet<string> _videoFileExtensions = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
var dict = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
foreach (string ext in VideoFileExtensions)
{
dict[ext] = ext;
}
return dict;
}
private static readonly Dictionary<string, string> VideoFileExtensionsDictionary = GetVideoFileExtensionsDictionary();
".mkv",
".m2t",
".m2ts",
".img",
".iso",
".mk3d",
".ts",
".rmvb",
".mov",
".avi",
".mpg",
".mpeg",
".wmv",
".mp4",
".divx",
".dvr-ms",
".wtv",
".ogm",
".ogv",
".asf",
".m4v",
".flv",
".f4v",
".3gp",
".webm",
".mts",
".m2v",
".rec"
};
// http://en.wikipedia.org/wiki/Internet_media_type
// Add more as needed
private static Dictionary<string, string> GetMimeTypeLookup()
private static readonly Dictionary<string, string> _mimeTypeLookup = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
var dict = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
// Type application
{ ".cbz", "application/x-cbz" },
{ ".cbr", "application/epub+zip" },
{ ".eot", "application/vnd.ms-fontobject" },
{ ".epub", "application/epub+zip" },
{ ".js", "application/x-javascript" },
{ ".json", "application/json" },
{ ".map", "application/x-javascript" },
{ ".pdf", "application/pdf" },
{ ".ttml", "application/ttml+xml" },
{ ".m3u8", "application/x-mpegURL" },
{ ".mobi", "application/x-mobipocket-ebook" },
{ ".xml", "application/xml" },
dict.Add(".jpg", "image/jpeg");
dict.Add(".jpeg", "image/jpeg");
dict.Add(".tbn", "image/jpeg");
dict.Add(".png", "image/png");
dict.Add(".gif", "image/gif");
dict.Add(".tiff", "image/tiff");
dict.Add(".webp", "image/webp");
dict.Add(".ico", "image/vnd.microsoft.icon");
dict.Add(".mpg", "video/mpeg");
dict.Add(".mpeg", "video/mpeg");
dict.Add(".ogv", "video/ogg");
dict.Add(".mov", "video/quicktime");
dict.Add(".webm", "video/webm");
dict.Add(".mkv", "video/x-matroska");
dict.Add(".wmv", "video/x-ms-wmv");
dict.Add(".flv", "video/x-flv");
dict.Add(".avi", "video/x-msvideo");
dict.Add(".asf", "video/x-ms-asf");
dict.Add(".m4v", "video/x-m4v");
dict.Add(".m4s", "video/mp4");
dict.Add(".cbz", "application/x-cbz");
dict.Add(".cbr", "application/epub+zip");
dict.Add(".epub", "application/epub+zip");
dict.Add(".pdf", "application/pdf");
dict.Add(".mobi", "application/x-mobipocket-ebook");
// Type image
{ ".jpg", "image/jpeg" },
{ ".jpeg", "image/jpeg" },
{ ".tbn", "image/jpeg" },
{ ".png", "image/png" },
{ ".gif", "image/gif" },
{ ".tiff", "image/tiff" },
{ ".webp", "image/webp" },
{ ".ico", "image/vnd.microsoft.icon" },
{ ".svg", "image/svg+xml" },
{ ".svgz", "image/svg+xml" },
dict.Add(".ass", "text/x-ssa");
dict.Add(".ssa", "text/x-ssa");
// Type font
{ ".ttf" , "font/ttf" },
{ ".woff" , "font/woff" },
return dict;
}
// Type text
{ ".ass", "text/x-ssa" },
{ ".ssa", "text/x-ssa" },
{ ".css", "text/css" },
{ ".csv", "text/csv" },
{ ".txt", "text/plain" },
{ ".vtt", "text/vtt" },
private static readonly Dictionary<string, string> MimeTypeLookup = GetMimeTypeLookup();
// Type video
{ ".mpg", "video/mpeg" },
{ ".ogv", "video/ogg" },
{ ".mov", "video/quicktime" },
{ ".webm", "video/webm" },
{ ".mkv", "video/x-matroska" },
{ ".wmv", "video/x-ms-wmv" },
{ ".flv", "video/x-flv" },
{ ".avi", "video/x-msvideo" },
{ ".asf", "video/x-ms-asf" },
{ ".m4v", "video/x-m4v" },
{ ".m4s", "video/mp4" },
{ ".3gp", "video/3gpp" },
{ ".3g2", "video/3gpp2" },
{ ".mpd", "video/vnd.mpeg.dash.mpd" },
{ ".ts", "video/mp2t" },
private static readonly Dictionary<string, string> ExtensionLookup = CreateExtensionLookup();
// Type audio
{ ".mp3", "audio/mpeg" },
{ ".m4a", "audio/mp4" },
{ ".aac", "audio/mp4" },
{ ".webma", "audio/webm" },
{ ".wav", "audio/wav" },
{ ".wma", "audio/x-ms-wma" },
{ ".ogg", "audio/ogg" },
{ ".oga", "audio/ogg" },
{ ".opus", "audio/ogg" },
{ ".ac3", "audio/ac3" },
{ ".dsf", "audio/dsf" },
{ ".m4b", "audio/m4b" },
{ ".xsp", "audio/xsp" },
{ ".dsp", "audio/dsp" },
};
private static readonly Dictionary<string, string> _extensionLookup = CreateExtensionLookup();
private static Dictionary<string, string> CreateExtensionLookup()
{
var dict = MimeTypeLookup
var dict = _mimeTypeLookup
.GroupBy(i => i.Value)
.ToDictionary(x => x.Key, x => x.First().Key, StringComparer.OrdinalIgnoreCase);
dict["image/jpg"] = ".jpg";
dict["image/x-png"] = ".png";
dict["audio/x-aac"] = ".aac";
return dict;
}
public static string GetMimeType(string path)
{
return GetMimeType(path, true);
}
public static string GetMimeType(string path) => GetMimeType(path, true);
/// <summary>
/// Gets the type of the MIME.
@@ -130,138 +150,31 @@ namespace MediaBrowser.Model.Net
throw new ArgumentNullException(nameof(path));
}
var ext = Path.GetExtension(path) ?? string.Empty;
var ext = Path.GetExtension(path);
if (MimeTypeLookup.TryGetValue(ext, out string result))
if (_mimeTypeLookup.TryGetValue(ext, out string result))
{
return result;
}
// Type video
if (StringHelper.EqualsIgnoreCase(ext, ".3gp"))
{
return "video/3gpp";
}
if (StringHelper.EqualsIgnoreCase(ext, ".3g2"))
{
return "video/3gpp2";
}
if (StringHelper.EqualsIgnoreCase(ext, ".ts"))
{
return "video/mp2t";
}
if (StringHelper.EqualsIgnoreCase(ext, ".mpd"))
{
return "video/vnd.mpeg.dash.mpd";
}
// Catch-all for all video types that don't require specific mime types
if (VideoFileExtensionsDictionary.ContainsKey(ext))
if (_videoFileExtensions.Contains(ext))
{
return "video/" + ext.TrimStart('.').ToLowerInvariant();
return "video/" + ext.Substring(1);
}
// Type text
if (StringHelper.EqualsIgnoreCase(ext, ".css"))
{
return "text/css";
}
if (StringHelper.EqualsIgnoreCase(ext, ".csv"))
{
return "text/csv";
}
if (StringHelper.EqualsIgnoreCase(ext, ".html"))
if (StringHelper.EqualsIgnoreCase(ext, ".html")
|| StringHelper.EqualsIgnoreCase(ext, ".htm"))
{
return "text/html; charset=UTF-8";
}
if (StringHelper.EqualsIgnoreCase(ext, ".htm"))
{
return "text/html; charset=UTF-8";
}
if (StringHelper.EqualsIgnoreCase(ext, ".txt"))
if (StringHelper.EqualsIgnoreCase(ext, ".log")
|| StringHelper.EqualsIgnoreCase(ext, ".srt"))
{
return "text/plain";
}
if (StringHelper.EqualsIgnoreCase(ext, ".log"))
{
return "text/plain";
}
if (StringHelper.EqualsIgnoreCase(ext, ".xml"))
{
return "application/xml";
}
// Type audio
if (StringHelper.EqualsIgnoreCase(ext, ".mp3"))
{
return "audio/mpeg";
}
if (StringHelper.EqualsIgnoreCase(ext, ".m4a"))
{
return "audio/mp4";
}
if (StringHelper.EqualsIgnoreCase(ext, ".aac"))
{
return "audio/mp4";
}
if (StringHelper.EqualsIgnoreCase(ext, ".webma"))
{
return "audio/webm";
}
if (StringHelper.EqualsIgnoreCase(ext, ".wav"))
{
return "audio/wav";
}
if (StringHelper.EqualsIgnoreCase(ext, ".wma"))
{
return "audio/x-ms-wma";
}
if (StringHelper.EqualsIgnoreCase(ext, ".flac"))
{
return "audio/flac";
}
if (StringHelper.EqualsIgnoreCase(ext, ".aac"))
{
return "audio/x-aac";
}
if (StringHelper.EqualsIgnoreCase(ext, ".ogg"))
{
return "audio/ogg";
}
if (StringHelper.EqualsIgnoreCase(ext, ".oga"))
{
return "audio/ogg";
}
if (StringHelper.EqualsIgnoreCase(ext, ".opus"))
{
return "audio/ogg";
}
if (StringHelper.EqualsIgnoreCase(ext, ".ac3"))
{
return "audio/ac3";
}
if (StringHelper.EqualsIgnoreCase(ext, ".dsf"))
{
return "audio/dsf";
}
if (StringHelper.EqualsIgnoreCase(ext, ".m4b"))
{
return "audio/m4b";
}
if (StringHelper.EqualsIgnoreCase(ext, ".xsp"))
{
return "audio/xsp";
}
if (StringHelper.EqualsIgnoreCase(ext, ".dsp"))
{
return "audio/dsp";
}
// Playlists
if (StringHelper.EqualsIgnoreCase(ext, ".m3u8"))
{
return "application/x-mpegURL";
}
// Misc
if (StringHelper.EqualsIgnoreCase(ext, ".dll"))
@@ -269,63 +182,7 @@ namespace MediaBrowser.Model.Net
return "application/octet-stream";
}
// Web
if (StringHelper.EqualsIgnoreCase(ext, ".js"))
{
return "application/x-javascript";
}
if (StringHelper.EqualsIgnoreCase(ext, ".json"))
{
return "application/json";
}
if (StringHelper.EqualsIgnoreCase(ext, ".map"))
{
return "application/x-javascript";
}
if (StringHelper.EqualsIgnoreCase(ext, ".woff"))
{
return "font/woff";
}
if (StringHelper.EqualsIgnoreCase(ext, ".ttf"))
{
return "font/ttf";
}
if (StringHelper.EqualsIgnoreCase(ext, ".eot"))
{
return "application/vnd.ms-fontobject";
}
if (StringHelper.EqualsIgnoreCase(ext, ".svg"))
{
return "image/svg+xml";
}
if (StringHelper.EqualsIgnoreCase(ext, ".svgz"))
{
return "image/svg+xml";
}
if (StringHelper.EqualsIgnoreCase(ext, ".srt"))
{
return "text/plain";
}
if (StringHelper.EqualsIgnoreCase(ext, ".vtt"))
{
return "text/vtt";
}
if (StringHelper.EqualsIgnoreCase(ext, ".ttml"))
{
return "application/ttml+xml";
}
if (enableStreamDefault)
{
return "application/octet-stream";
}
return null;
return enableStreamDefault ? "application/octet-stream" : null;
}
public static string ToExtension(string mimeType)
@@ -338,10 +195,11 @@ namespace MediaBrowser.Model.Net
// handle text/html; charset=UTF-8
mimeType = mimeType.Split(';')[0];
if (ExtensionLookup.TryGetValue(mimeType, out string result))
if (_extensionLookup.TryGetValue(mimeType, out string result))
{
return result;
}
return null;
}
}

View File

@@ -1,3 +1,5 @@
using System.Net;
namespace MediaBrowser.Model.Net
{
/// <summary>
@@ -18,7 +20,7 @@ namespace MediaBrowser.Model.Net
/// <summary>
/// The <see cref="IpEndPointInfo"/> the data was received from.
/// </summary>
public IpEndPointInfo RemoteEndPoint { get; set; }
public IpAddressInfo LocalIPAddress { get; set; }
public IPEndPoint RemoteEndPoint { get; set; }
public IPAddress LocalIPAddress { get; set; }
}
}

View File

@@ -1,7 +1,7 @@
namespace MediaBrowser.Model.Plugins
{
/// <summary>
/// Class BasePluginConfiguration
/// Class BasePluginConfiguration.
/// </summary>
public class BasePluginConfiguration
{

View File

@@ -1,3 +1,5 @@
using Microsoft.AspNetCore.Http;
namespace MediaBrowser.Model.Services
{
public interface IHasRequestFilter
@@ -15,6 +17,6 @@ namespace MediaBrowser.Model.Services
/// <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);
void RequestFilter(IRequest req, HttpResponse res, object requestDto);
}
}

View File

@@ -1,16 +1,13 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Model.IO;
using Microsoft.AspNetCore.Http;
namespace MediaBrowser.Model.Services
{
public interface IRequest
{
IResponse Response { get; }
HttpResponse Response { get; }
/// <summary>
/// The name of the service being called (e.g. Request DTO Name)
@@ -22,11 +19,6 @@ namespace MediaBrowser.Model.Services
/// </summary>
string Verb { get; }
/// <summary>
/// The Request DTO, after it has been deserialized.
/// </summary>
object Dto { get; set; }
/// <summary>
/// The request ContentType
/// </summary>
@@ -50,8 +42,6 @@ namespace MediaBrowser.Model.Services
IQueryCollection QueryString { get; }
Task<QueryParamCollection> GetFormData();
string RawUrl { get; }
string AbsoluteUri { get; }
@@ -74,11 +64,6 @@ namespace MediaBrowser.Model.Services
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>
@@ -98,25 +83,4 @@ namespace MediaBrowser.Model.Services
{
IRequest Request { get; set; }
}
public interface IResponse
{
HttpResponse OriginalResponse { get; }
int StatusCode { get; set; }
string StatusDescription { get; set; }
string ContentType { get; set; }
void AddHeader(string name, string value);
void Redirect(string url);
Stream OutputStream { get; }
Task TransmitFile(string path, long offset, long count, FileShareMode fileShareMode, IFileSystem fileSystem, IStreamHelper streamHelper, CancellationToken cancellationToken);
bool SendChunked { get; set; }
}
}

View File

@@ -1,10 +1,47 @@
using System.Net.NetworkInformation;
namespace MediaBrowser.Model.System
{
/// <summary>
/// Provides the MAC address and port for wake-on-LAN functionality.
/// </summary>
public class WakeOnLanInfo
{
/// <summary>
/// Returns the MAC address of the device.
/// </summary>
/// <value>The MAC address.</value>
public string MacAddress { get; set; }
/// <summary>
/// Returns the wake-on-LAN port.
/// </summary>
/// <value>The wake-on-LAN port.</value>
public int Port { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="WakeOnLanInfo" /> class.
/// </summary>
/// <param name="macAddress">The MAC address.</param>
public WakeOnLanInfo(PhysicalAddress macAddress)
{
MacAddress = macAddress.ToString();
Port = 9;
}
/// <summary>
/// Initializes a new instance of the <see cref="WakeOnLanInfo" /> class.
/// </summary>
/// <param name="macAddress">The MAC address.</param>
public WakeOnLanInfo(string macAddress)
{
MacAddress = macAddress;
Port = 9;
}
/// <summary>
/// Initializes a new instance of the <see cref="WakeOnLanInfo" /> class.
/// </summary>
public WakeOnLanInfo()
{
Port = 9;

View File

@@ -36,11 +36,5 @@ namespace MediaBrowser.Model.Updates
/// </summary>
/// <value>The update class.</value>
public PackageVersionClass UpdateClass { get; set; }
/// <summary>
/// Gets or sets the percent complete.
/// </summary>
/// <value>The percent complete.</value>
public double? PercentComplete { get; set; }
}
}

View File

@@ -30,23 +30,25 @@ namespace MediaBrowser.Model.Updates
/// The _version
/// </summary>
private Version _version;
/// <summary>
/// Gets or sets the version.
/// Had to make this an interpreted property since Protobuf can't handle Version
/// </summary>
/// <value>The version.</value>
[IgnoreDataMember]
public Version version => _version ?? (_version = new Version(ValueOrDefault(versionStr, "0.0.0.1")));
/// <summary>
/// Values the or default.
/// </summary>
/// <param name="str">The STR.</param>
/// <param name="def">The def.</param>
/// <returns>System.String.</returns>
private static string ValueOrDefault(string str, string def)
public Version Version
{
return string.IsNullOrEmpty(str) ? def : str;
get
{
if (_version == null)
{
var ver = versionStr;
_version = new Version(string.IsNullOrEmpty(ver) ? "0.0.0.1" : ver);
}
return _version;
}
}
/// <summary>