aboutsummaryrefslogtreecommitdiff
path: root/Jellyfin.Server
diff options
context:
space:
mode:
authorLogicalPhallacy <44458166+LogicalPhallacy@users.noreply.github.com>2019-02-11 22:48:50 -0800
committerGitHub <noreply@github.com>2019-02-11 22:48:50 -0800
commit8bf88f4cb2ddb140baffd8e4542d8f528b482a67 (patch)
tree5f60f345a22c2468b504b925c0bf4785869185ae /Jellyfin.Server
parent4519ce26e2250cb233836296d292ddb7b3cf6346 (diff)
parenteb4b7051676b7493a57a99a821d5dd38bd9d4919 (diff)
Merge pull request #9 from jellyfin/master
Yanking in latest changes
Diffstat (limited to 'Jellyfin.Server')
-rw-r--r--Jellyfin.Server/CoreAppHost.cs4
-rw-r--r--Jellyfin.Server/Jellyfin.Server.csproj6
-rw-r--r--Jellyfin.Server/Program.cs88
-rw-r--r--Jellyfin.Server/SocketSharp/HttpFile.cs2
-rw-r--r--Jellyfin.Server/SocketSharp/RequestMono.cs86
-rw-r--r--Jellyfin.Server/SocketSharp/SharpWebSocket.cs2
-rw-r--r--Jellyfin.Server/SocketSharp/WebSocketSharpListener.cs2
-rw-r--r--Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs84
-rw-r--r--Jellyfin.Server/SocketSharp/WebSocketSharpResponse.cs2
-rw-r--r--Jellyfin.Server/StartupOptions.cs44
10 files changed, 214 insertions, 106 deletions
diff --git a/Jellyfin.Server/CoreAppHost.cs b/Jellyfin.Server/CoreAppHost.cs
index b580f45ca..315e34a04 100644
--- a/Jellyfin.Server/CoreAppHost.cs
+++ b/Jellyfin.Server/CoreAppHost.cs
@@ -2,7 +2,7 @@ using System.Collections.Generic;
using System.Reflection;
using Emby.Server.Implementations;
using Emby.Server.Implementations.HttpServer;
-using Jellyfin.SocketSharp;
+using Jellyfin.Server.SocketSharp;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.System;
using Microsoft.Extensions.Logging;
@@ -16,7 +16,7 @@ namespace Jellyfin.Server
{
}
- public override bool CanSelfRestart => StartupOptions.ContainsOption("-restartpath");
+ public override bool CanSelfRestart => StartupOptions.RestartPath != null;
protected override void RestartInternal() => Program.Restart();
diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj
index 5a4bf5149..b1515df43 100644
--- a/Jellyfin.Server/Jellyfin.Server.csproj
+++ b/Jellyfin.Server/Jellyfin.Server.csproj
@@ -32,6 +32,7 @@
</PropertyGroup>
<ItemGroup>
+ <PackageReference Include="CommandLineParser" Version="2.4.3" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.2.0" />
<PackageReference Include="Serilog.AspNetCore" Version="2.1.1" />
@@ -40,9 +41,8 @@
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
<PackageReference Include="Serilog.Sinks.File" Version="4.0.0" />
<PackageReference Include="SkiaSharp" Version="1.68.0" />
- <PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="1.1.12" />
- <PackageReference Include="SQLitePCLRaw.core" Version="1.1.12" />
- <PackageReference Include="SQLitePCLRaw.provider.sqlite3.netstandard11" Version="1.1.12" />
+ <PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="1.1.13" />
+ <PackageReference Include="SQLitePCLRaw.provider.sqlite3.netstandard11" Version="1.1.13" />
</ItemGroup>
<ItemGroup>
diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs
index 66586d4e4..7826fde35 100644
--- a/Jellyfin.Server/Program.cs
+++ b/Jellyfin.Server/Program.cs
@@ -6,8 +6,10 @@ using System.Net;
using System.Net.Security;
using System.Reflection;
using System.Runtime.InteropServices;
+using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
+using CommandLine;
using Emby.Drawing;
using Emby.Server.Implementations;
using Emby.Server.Implementations.EnvironmentInfo;
@@ -35,19 +37,32 @@ namespace Jellyfin.Server
public static async Task Main(string[] args)
{
- StartupOptions options = new StartupOptions(args);
- Version version = Assembly.GetEntryAssembly().GetName().Version;
-
- if (options.ContainsOption("-v") || options.ContainsOption("--version"))
+ // For backwards compatibility.
+ // Modify any input arguments now which start with single-hyphen to POSIX standard
+ // double-hyphen to allow parsing by CommandLineParser package.
+ const string pattern = @"^(-[^-\s]{2})"; // Match -xx, not -x, not --xx, not xx
+ const string substitution = @"-$1"; // Prepend with additional single-hyphen
+ var regex = new Regex(pattern);
+
+ for (var i = 0; i < args.Length; i++)
{
- Console.WriteLine(version.ToString());
+ args[i] = regex.Replace(args[i], substitution);
}
+ // Parse the command line arguments and either start the app or exit indicating error
+ await Parser.Default.ParseArguments<StartupOptions>(args)
+ .MapResult(
+ options => StartApp(options),
+ errs => Task.FromResult(0)).ConfigureAwait(false);
+ }
+
+ private static async Task StartApp(StartupOptions options)
+ {
ServerApplicationPaths appPaths = CreateApplicationPaths(options);
// $JELLYFIN_LOG_DIR needs to be set for the logger configuration manager
Environment.SetEnvironmentVariable("JELLYFIN_LOG_DIR", appPaths.LogDirectoryPath);
- await createLogger(appPaths);
+ await CreateLogger(appPaths);
_logger = _loggerFactory.CreateLogger("Main");
AppDomain.CurrentDomain.UnhandledException += (sender, e)
@@ -78,9 +93,9 @@ namespace Jellyfin.Server
Shutdown();
};
- _logger.LogInformation("Jellyfin version: {Version}", version);
+ _logger.LogInformation("Jellyfin version: {Version}", Assembly.GetEntryAssembly().GetName().Version);
- EnvironmentInfo environmentInfo = new EnvironmentInfo(getOperatingSystem());
+ EnvironmentInfo environmentInfo = new EnvironmentInfo(GetOperatingSystem());
ApplicationHost.LogEnvironmentInfo(_logger, appPaths, environmentInfo);
SQLitePCL.Batteries_V2.Init();
@@ -99,12 +114,10 @@ namespace Jellyfin.Server
new NullImageEncoder(),
new NetworkManager(_loggerFactory, environmentInfo)))
{
- appHost.Init();
+ await appHost.Init();
appHost.ImageProcessor.ImageEncoder = GetImageEncoder(fileSystem, appPaths, appHost.LocalizationManager);
- _logger.LogInformation("Running startup tasks");
-
await appHost.RunStartupTasks();
// TODO: read input for a stop command
@@ -118,8 +131,6 @@ namespace Jellyfin.Server
{
// Don't throw on cancellation
}
-
- _logger.LogInformation("Disposing app host");
}
if (_restartOnShutdown)
@@ -133,9 +144,9 @@ namespace Jellyfin.Server
string programDataPath = Environment.GetEnvironmentVariable("JELLYFIN_DATA_PATH");
if (string.IsNullOrEmpty(programDataPath))
{
- if (options.ContainsOption("-programdata"))
+ if (options.DataDir != null)
{
- programDataPath = options.GetOption("-programdata");
+ programDataPath = options.DataDir;
}
else
{
@@ -171,9 +182,9 @@ namespace Jellyfin.Server
string configDir = Environment.GetEnvironmentVariable("JELLYFIN_CONFIG_DIR");
if (string.IsNullOrEmpty(configDir))
{
- if (options.ContainsOption("-configdir"))
+ if (options.ConfigDir != null)
{
- configDir = options.GetOption("-configdir");
+ configDir = options.ConfigDir;
}
else
{
@@ -187,12 +198,37 @@ namespace Jellyfin.Server
Directory.CreateDirectory(configDir);
}
+ string cacheDir = Environment.GetEnvironmentVariable("JELLYFIN_CACHE_DIR");
+ if (string.IsNullOrEmpty(cacheDir))
+ {
+ if (options.CacheDir != null)
+ {
+ cacheDir = options.CacheDir;
+ }
+ else if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ // $XDG_CACHE_HOME defines the base directory relative to which user specific non-essential data files should be stored.
+ cacheDir = Environment.GetEnvironmentVariable("XDG_CACHE_HOME");
+ // If $XDG_CACHE_HOME is either not set or empty, $HOME/.cache should be used.
+ if (string.IsNullOrEmpty(cacheDir))
+ {
+ cacheDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".cache");
+ }
+ cacheDir = Path.Combine(cacheDir, "jellyfin");
+ }
+ }
+
+ if (cacheDir != null)
+ {
+ Directory.CreateDirectory(cacheDir);
+ }
+
string logDir = Environment.GetEnvironmentVariable("JELLYFIN_LOG_DIR");
if (string.IsNullOrEmpty(logDir))
{
- if (options.ContainsOption("-logdir"))
+ if (options.LogDir != null)
{
- logDir = options.GetOption("-logdir");
+ logDir = options.LogDir;
}
else
{
@@ -208,10 +244,10 @@ namespace Jellyfin.Server
string appPath = AppContext.BaseDirectory;
- return new ServerApplicationPaths(programDataPath, appPath, appPath, logDir, configDir);
+ return new ServerApplicationPaths(programDataPath, appPath, appPath, logDir, configDir, cacheDir);
}
- private static async Task createLogger(IApplicationPaths appPaths)
+ private static async Task CreateLogger(IApplicationPaths appPaths)
{
try
{
@@ -271,7 +307,7 @@ namespace Jellyfin.Server
return new NullImageEncoder();
}
- private static MediaBrowser.Model.System.OperatingSystem getOperatingSystem()
+ private static MediaBrowser.Model.System.OperatingSystem GetOperatingSystem()
{
switch (Environment.OSVersion.Platform)
{
@@ -315,11 +351,11 @@ namespace Jellyfin.Server
Shutdown();
}
- private static void StartNewInstance(StartupOptions startupOptions)
+ private static void StartNewInstance(StartupOptions options)
{
_logger.LogInformation("Starting new instance");
- string module = startupOptions.GetOption("-restartpath");
+ string module = options.RestartPath;
if (string.IsNullOrWhiteSpace(module))
{
@@ -328,9 +364,9 @@ namespace Jellyfin.Server
string commandLineArgsString;
- if (startupOptions.ContainsOption("-restartargs"))
+ if (options.RestartArgs != null)
{
- commandLineArgsString = startupOptions.GetOption("-restartargs") ?? string.Empty;
+ commandLineArgsString = options.RestartArgs ?? string.Empty;
}
else
{
diff --git a/Jellyfin.Server/SocketSharp/HttpFile.cs b/Jellyfin.Server/SocketSharp/HttpFile.cs
index 77ce03510..89c75e536 100644
--- a/Jellyfin.Server/SocketSharp/HttpFile.cs
+++ b/Jellyfin.Server/SocketSharp/HttpFile.cs
@@ -1,7 +1,7 @@
using System.IO;
using MediaBrowser.Model.Services;
-namespace Jellyfin.SocketSharp
+namespace Jellyfin.Server.SocketSharp
{
public class HttpFile : IHttpFile
{
diff --git a/Jellyfin.Server/SocketSharp/RequestMono.cs b/Jellyfin.Server/SocketSharp/RequestMono.cs
index 017690062..a8ba4cdb5 100644
--- a/Jellyfin.Server/SocketSharp/RequestMono.cs
+++ b/Jellyfin.Server/SocketSharp/RequestMono.cs
@@ -7,11 +7,11 @@ using System.Text;
using System.Threading.Tasks;
using MediaBrowser.Model.Services;
-namespace Jellyfin.SocketSharp
+namespace Jellyfin.Server.SocketSharp
{
public partial class WebSocketSharpRequest : IHttpRequest
{
- static internal string GetParameter(string header, string attr)
+ internal static string GetParameter(string header, string attr)
{
int ap = header.IndexOf(attr);
if (ap == -1)
@@ -40,7 +40,7 @@ namespace Jellyfin.SocketSharp
return header.Substring(ap + 1, end - ap - 1);
}
- async Task LoadMultiPart(WebROCollection form)
+ private async Task LoadMultiPart(WebROCollection form)
{
string boundary = GetParameter(ContentType, "; boundary=");
if (boundary == null)
@@ -50,8 +50,8 @@ namespace Jellyfin.SocketSharp
using (var requestStream = InputStream)
{
- //DB: 30/01/11 - Hack to get around non-seekable stream and received HTTP request
- //Not ending with \r\n?
+ // DB: 30/01/11 - Hack to get around non-seekable stream and received HTTP request
+ // Not ending with \r\n?
var ms = new MemoryStream(32 * 1024);
await requestStream.CopyToAsync(ms).ConfigureAwait(false);
@@ -62,9 +62,9 @@ namespace Jellyfin.SocketSharp
input.Position = 0;
// Uncomment to debug
- //var content = new StreamReader(ms).ReadToEnd();
- //Console.WriteLine(boundary + "::" + content);
- //input.Position = 0;
+ // var content = new StreamReader(ms).ReadToEnd();
+ // Console.WriteLine(boundary + "::" + content);
+ // input.Position = 0;
var multi_part = new HttpMultipart(input, boundary, ContentEncoding);
@@ -111,7 +111,7 @@ namespace Jellyfin.SocketSharp
// Setting this before calling the validator prevents
// possible endless recursion
checked_form = true;
- ValidateNameValueCollection ("Form", query_string_nvc, RequestValidationSource.Form);
+ ValidateNameValueCollection("Form", query_string_nvc, RequestValidationSource.Form);
} else
#endif
if (validate_form && !checked_form)
@@ -130,7 +130,7 @@ namespace Jellyfin.SocketSharp
protected bool validate_cookies, validate_query_string, validate_form;
protected bool checked_cookies, checked_query_string, checked_form;
- static void ThrowValidationException(string name, string key, string value)
+ private static void ThrowValidationException(string name, string key, string value)
{
string v = "\"" + value + "\"";
if (v.Length > 20)
@@ -144,7 +144,7 @@ namespace Jellyfin.SocketSharp
throw new Exception(msg);
}
- static void ValidateNameValueCollection(string name, QueryParamCollection coll)
+ private static void ValidateNameValueCollection(string name, QueryParamCollection coll)
{
if (coll == null)
{
@@ -209,7 +209,7 @@ namespace Jellyfin.SocketSharp
validate_form = true;
}
- bool IsContentType(string ct, bool starts_with)
+ private bool IsContentType(string ct, bool starts_with)
{
if (ct == null || ContentType == null)
{
@@ -224,7 +224,7 @@ namespace Jellyfin.SocketSharp
return string.Equals(ContentType, ct, StringComparison.OrdinalIgnoreCase);
}
- async Task LoadWwwForm(WebROCollection form)
+ private async Task LoadWwwForm(WebROCollection form)
{
using (var input = InputStream)
{
@@ -280,7 +280,7 @@ namespace Jellyfin.SocketSharp
}
}
- static void AddRawKeyValue(WebROCollection form, StringBuilder key, StringBuilder value)
+ private static void AddRawKeyValue(WebROCollection form, StringBuilder key, StringBuilder value)
{
form.Add(WebUtility.UrlDecode(key.ToString()), WebUtility.UrlDecode(value.ToString()));
@@ -288,9 +288,9 @@ namespace Jellyfin.SocketSharp
value.Length = 0;
}
- Dictionary<string, HttpPostedFile> files;
+ private Dictionary<string, HttpPostedFile> files;
- class WebROCollection : QueryParamCollection
+ private class WebROCollection : QueryParamCollection
{
public override string ToString()
{
@@ -317,16 +317,16 @@ namespace Jellyfin.SocketSharp
public sealed class HttpPostedFile
{
- string name;
- string content_type;
- Stream stream;
+ private string name;
+ private string content_type;
+ private Stream stream;
- class ReadSubStream : Stream
+ private class ReadSubStream : Stream
{
- Stream s;
- long offset;
- long end;
- long position;
+ private Stream s;
+ private long offset;
+ private long end;
+ private long position;
public ReadSubStream(Stream s, long offset, long length)
{
@@ -360,13 +360,13 @@ namespace Jellyfin.SocketSharp
int len = buffer.Length;
if (dest_offset > len)
{
- throw new ArgumentException("destination offset is beyond array size");
+ throw new ArgumentException("destination offset is beyond array size", nameof(dest_offset));
}
// reordered to avoid possible integer overflow
if (dest_offset > len - count)
{
- throw new ArgumentException("Reading would overrun buffer");
+ throw new ArgumentException("Reading would overrun buffer", nameof(count));
}
if (count > end - position)
@@ -429,7 +429,7 @@ namespace Jellyfin.SocketSharp
real = position + d;
break;
default:
- throw new ArgumentException();
+ throw new ArgumentException(nameof(origin));
}
long virt = real - offset;
@@ -491,7 +491,7 @@ namespace Jellyfin.SocketSharp
public Stream InputStream => stream;
}
- class Helpers
+ private class Helpers
{
public static readonly CultureInfo InvariantCulture = CultureInfo.InvariantCulture;
}
@@ -528,7 +528,7 @@ namespace Jellyfin.SocketSharp
}
}
- class HttpMultipart
+ private class HttpMultipart
{
public class Element
@@ -543,19 +543,19 @@ namespace Jellyfin.SocketSharp
public override string ToString()
{
return "ContentType " + ContentType + ", Name " + Name + ", Filename " + Filename + ", Start " +
- Start.ToString() + ", Length " + Length.ToString();
+ Start.ToString(CultureInfo.CurrentCulture) + ", Length " + Length.ToString(CultureInfo.CurrentCulture);
}
}
- Stream data;
- string boundary;
- byte[] boundary_bytes;
- byte[] buffer;
- bool at_eof;
- Encoding encoding;
- StringBuilder sb;
+ private Stream data;
+ private string boundary;
+ private byte[] boundary_bytes;
+ private byte[] buffer;
+ private bool at_eof;
+ private Encoding encoding;
+ private StringBuilder sb;
- const byte LF = (byte)'\n', CR = (byte)'\r';
+ private const byte LF = (byte)'\n', CR = (byte)'\r';
// See RFC 2046
// In the case of multipart entities, in which one or more different
@@ -610,12 +610,11 @@ namespace Jellyfin.SocketSharp
}
return sb.ToString();
-
}
private static string GetContentDispositionAttribute(string l, string name)
{
- int idx = l.IndexOf(name + "=\"");
+ int idx = l.IndexOf(name + "=\"", StringComparison.Ordinal);
if (idx < 0)
{
return null;
@@ -638,7 +637,7 @@ namespace Jellyfin.SocketSharp
private string GetContentDispositionAttributeWithEncoding(string l, string name)
{
- int idx = l.IndexOf(name + "=\"");
+ int idx = l.IndexOf(name + "=\"", StringComparison.Ordinal);
if (idx < 0)
{
return null;
@@ -670,11 +669,12 @@ namespace Jellyfin.SocketSharp
{
try
{
- string line = ReadLine();
- while (line == string.Empty)
+ string line;
+ do
{
line = ReadLine();
}
+ while (line.Length == 0);
if (line[0] != '-' || line[1] != '-')
{
diff --git a/Jellyfin.Server/SocketSharp/SharpWebSocket.cs b/Jellyfin.Server/SocketSharp/SharpWebSocket.cs
index d0dcd86eb..f371cb25a 100644
--- a/Jellyfin.Server/SocketSharp/SharpWebSocket.cs
+++ b/Jellyfin.Server/SocketSharp/SharpWebSocket.cs
@@ -5,7 +5,7 @@ using System.Threading.Tasks;
using Emby.Server.Implementations.Net;
using Microsoft.Extensions.Logging;
-namespace Jellyfin.SocketSharp
+namespace Jellyfin.Server.SocketSharp
{
public class SharpWebSocket : IWebSocket
{
diff --git a/Jellyfin.Server/SocketSharp/WebSocketSharpListener.cs b/Jellyfin.Server/SocketSharp/WebSocketSharpListener.cs
index c7f9f01b5..a44343ab2 100644
--- a/Jellyfin.Server/SocketSharp/WebSocketSharpListener.cs
+++ b/Jellyfin.Server/SocketSharp/WebSocketSharpListener.cs
@@ -15,7 +15,7 @@ using MediaBrowser.Model.System;
using Microsoft.Extensions.Logging;
using SocketHttpListener.Net;
-namespace Jellyfin.SocketSharp
+namespace Jellyfin.Server.SocketSharp
{
public class WebSocketSharpListener : IHttpListener
{
diff --git a/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs b/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs
index 97550e686..ebeb18ea0 100644
--- a/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs
+++ b/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs
@@ -11,7 +11,7 @@ using IHttpRequest = MediaBrowser.Model.Services.IHttpRequest;
using IHttpResponse = MediaBrowser.Model.Services.IHttpResponse;
using IResponse = MediaBrowser.Model.Services.IResponse;
-namespace Jellyfin.SocketSharp
+namespace Jellyfin.Server.SocketSharp
{
public partial class WebSocketSharpRequest : IHttpRequest
{
@@ -29,12 +29,24 @@ namespace Jellyfin.SocketSharp
private static string GetHandlerPathIfAny(string listenerUrl)
{
- if (listenerUrl == null) return null;
+ if (listenerUrl == null)
+ {
+ return null;
+ }
+
var pos = listenerUrl.IndexOf("://", StringComparison.OrdinalIgnoreCase);
- if (pos == -1) return null;
+ if (pos == -1)
+ {
+ return null;
+ }
+
var startHostUrl = listenerUrl.Substring(pos + "://".Length);
var endPos = startHostUrl.IndexOf('/');
- if (endPos == -1) return null;
+ if (endPos == -1)
+ {
+ return null;
+ }
+
var endHostUrl = startHostUrl.Substring(endPos + 1);
return string.IsNullOrEmpty(endHostUrl) ? null : endHostUrl.TrimEnd('/');
}
@@ -68,15 +80,13 @@ namespace Jellyfin.SocketSharp
private string remoteIp;
public string RemoteIp =>
remoteIp ??
- (remoteIp = (CheckBadChars(XForwardedFor)) ??
- (NormalizeIp(CheckBadChars(XRealIp)) ??
+ (remoteIp = CheckBadChars(XForwardedFor) ??
+ NormalizeIp(CheckBadChars(XRealIp) ??
(request.RemoteEndPoint != null ? NormalizeIp(request.RemoteEndPoint.Address.ToString()) : null)));
private static readonly char[] HttpTrimCharacters = new char[] { (char)0x09, (char)0xA, (char)0xB, (char)0xC, (char)0xD, (char)0x20 };
- //
// CheckBadChars - throws on invalid chars to be not found in header name/value
- //
internal static string CheckBadChars(string name)
{
if (name == null || name.Length == 0)
@@ -85,11 +95,11 @@ namespace Jellyfin.SocketSharp
}
// VALUE check
- //Trim spaces from both ends
+ // Trim spaces from both ends
name = name.Trim(HttpTrimCharacters);
- //First, check for correctly formed multi-line value
- //Second, check for absenece of CTL characters
+ // First, check for correctly formed multi-line value
+ // Second, check for absenece of CTL characters
int crlf = 0;
for (int i = 0; i < name.Length; ++i)
{
@@ -186,9 +196,12 @@ namespace Jellyfin.SocketSharp
public static string GetResponseContentType(IRequest httpReq)
{
var specifiedContentType = GetQueryStringContentType(httpReq);
- if (!string.IsNullOrEmpty(specifiedContentType)) return specifiedContentType;
+ if (!string.IsNullOrEmpty(specifiedContentType))
+ {
+ return specifiedContentType;
+ }
- var serverDefaultContentType = "application/json";
+ const string serverDefaultContentType = "application/json";
var acceptContentTypes = httpReq.AcceptTypes;
string defaultContentType = null;
@@ -198,7 +211,7 @@ namespace Jellyfin.SocketSharp
}
var acceptsAnything = false;
- var hasDefaultContentType = !string.IsNullOrEmpty(defaultContentType);
+ var hasDefaultContentType = defaultContentType != null;
if (acceptContentTypes != null)
{
foreach (var acceptsType in acceptContentTypes)
@@ -210,9 +223,13 @@ namespace Jellyfin.SocketSharp
if (acceptsAnything)
{
if (hasDefaultContentType)
+ {
return defaultContentType;
- if (serverDefaultContentType != null)
+ }
+ else if (serverDefaultContentType != null)
+ {
return serverDefaultContentType;
+ }
}
}
@@ -221,7 +238,7 @@ namespace Jellyfin.SocketSharp
return Soap11;
}
- //We could also send a '406 Not Acceptable', but this is allowed also
+ // We could also send a '406 Not Acceptable', but this is allowed also
return serverDefaultContentType;
}
@@ -229,11 +246,19 @@ namespace Jellyfin.SocketSharp
public static bool HasAnyOfContentTypes(IRequest request, params string[] contentTypes)
{
- if (contentTypes == null || request.ContentType == null) return false;
+ if (contentTypes == null || request.ContentType == null)
+ {
+ return false;
+ }
+
foreach (var contentType in contentTypes)
{
- if (IsContentType(request, contentType)) return true;
+ if (IsContentType(request, contentType))
+ {
+ return true;
+ }
}
+
return false;
}
@@ -253,10 +278,12 @@ namespace Jellyfin.SocketSharp
{
return null;
}
+
if (pi[0] == '/')
{
pi = pi.Substring(1);
}
+
format = LeftPart(pi, '/');
if (format.Length > formatMaxLength)
{
@@ -264,12 +291,12 @@ namespace Jellyfin.SocketSharp
}
}
- format = LeftPart(format, '.').ToLower();
+ format = LeftPart(format, '.');
if (format.Contains("json", StringComparison.OrdinalIgnoreCase))
{
return "application/json";
}
- if (format.Contains("xml", StringComparison.OrdinalIgnoreCase))
+ else if (format.Contains("xml", StringComparison.OrdinalIgnoreCase))
{
return "application/xml";
}
@@ -283,10 +310,9 @@ namespace Jellyfin.SocketSharp
{
return null;
}
- var pos = strVal.IndexOf(needle);
- return pos == -1
- ? strVal
- : strVal.Substring(0, pos);
+
+ var pos = strVal.IndexOf(needle, StringComparison.Ordinal);
+ return pos == -1 ? strVal : strVal.Substring(0, pos);
}
public static string HandlerFactoryPath;
@@ -329,7 +355,7 @@ namespace Jellyfin.SocketSharp
return pathInfo;
}
- //Wildcard mode relies on this to work out the handlerPath
+ // Wildcard mode relies on this to work out the handlerPath
pathInfo = ResolvePathInfoFromMappedPath(fullPath, appPath);
if (!string.IsNullOrEmpty(pathInfo))
{
@@ -371,6 +397,7 @@ namespace Jellyfin.SocketSharp
}
}
}
+
if (!pathRootFound)
{
return null;
@@ -433,6 +460,7 @@ namespace Jellyfin.SocketSharp
{
return null;
}
+
try
{
return Encoding.GetEncoding(param);
@@ -480,10 +508,10 @@ namespace Jellyfin.SocketSharp
public static string NormalizePathInfo(string pathInfo, string handlerPath)
{
- if (handlerPath != null && pathInfo.TrimStart('/').StartsWith(
- handlerPath, StringComparison.OrdinalIgnoreCase))
+ var trimmed = pathInfo.TrimStart('/');
+ if (handlerPath != null && trimmed.StartsWith(handlerPath, StringComparison.OrdinalIgnoreCase))
{
- return pathInfo.TrimStart('/').Substring(handlerPath.Length);
+ return trimmed.Substring(handlerPath.Length);
}
return pathInfo;
diff --git a/Jellyfin.Server/SocketSharp/WebSocketSharpResponse.cs b/Jellyfin.Server/SocketSharp/WebSocketSharpResponse.cs
index 21bfac55d..cabc96b23 100644
--- a/Jellyfin.Server/SocketSharp/WebSocketSharpResponse.cs
+++ b/Jellyfin.Server/SocketSharp/WebSocketSharpResponse.cs
@@ -14,7 +14,7 @@ using IHttpResponse = MediaBrowser.Model.Services.IHttpResponse;
using IRequest = MediaBrowser.Model.Services.IRequest;
-namespace Jellyfin.SocketSharp
+namespace Jellyfin.Server.SocketSharp
{
public class WebSocketSharpResponse : IHttpResponse
{
diff --git a/Jellyfin.Server/StartupOptions.cs b/Jellyfin.Server/StartupOptions.cs
new file mode 100644
index 000000000..5d3f7b171
--- /dev/null
+++ b/Jellyfin.Server/StartupOptions.cs
@@ -0,0 +1,44 @@
+using CommandLine;
+using Emby.Server.Implementations;
+
+namespace Jellyfin.Server
+{
+ /// <summary>
+ /// Class used by CommandLine package when parsing the command line arguments.
+ /// </summary>
+ public class StartupOptions : IStartupOptions
+ {
+ [Option('d', "datadir", Required = false, HelpText = "Path to use for the data folder (database files, etc.).")]
+ public string DataDir { get; set; }
+
+ [Option('C', "cachedir", Required = false, HelpText = "Path to use for caching.")]
+ public string CacheDir { get; set; }
+
+ [Option('c', "configdir", Required = false, HelpText = "Path to use for configuration data (user settings and pictures).")]
+ public string ConfigDir { get; set; }
+
+ [Option('l', "logdir", Required = false, HelpText = "Path to use for writing log files.")]
+ public string LogDir { get; set; }
+
+ [Option("ffmpeg", Required = false, HelpText = "Path to external FFmpeg executable to use in place of default found in PATH. Must be specified along with --ffprobe.")]
+ public string FFmpegPath { get; set; }
+
+ [Option("ffprobe", Required = false, HelpText = "Path to external FFprobe executable to use in place of default found in PATH. Must be specified along with --ffmpeg.")]
+ public string FFprobePath { get; set; }
+
+ [Option("service", Required = false, HelpText = "Run as headless service.")]
+ public bool IsService { get; set; }
+
+ [Option("noautorunwebapp", Required = false, HelpText = "Run headless if startup wizard is complete.")]
+ public bool NoAutoRunWebApp { get; set; }
+
+ [Option("package-name", Required = false, HelpText = "Used when packaging Jellyfin (example, synology).")]
+ public string PackageName { get; set; }
+
+ [Option("restartpath", Required = false, HelpText = "Path to restart script.")]
+ public string RestartPath { get; set; }
+
+ [Option("restartargs", Required = false, HelpText = "Arguments for restart script.")]
+ public string RestartArgs { get; set; }
+ }
+}