jellyfin-server/MediaBrowser.Api/EnvironmentService.cs

286 lines
10 KiB
C#
Raw Normal View History

using System;
2013-02-21 01:33:05 +00:00
using System.Collections.Generic;
using System.IO;
using System.Linq;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.IO;
2016-10-25 19:02:04 +00:00
using MediaBrowser.Model.Services;
using Microsoft.Extensions.Logging;
2013-02-21 01:33:05 +00:00
namespace MediaBrowser.Api
{
/// <summary>
/// Class GetDirectoryContents.
2013-02-21 01:33:05 +00:00
/// </summary>
2014-03-28 19:58:18 +00:00
[Route("/Environment/DirectoryContents", "GET", Summary = "Gets the contents of a given directory in the file system")]
2013-02-21 01:33:05 +00:00
public class GetDirectoryContents : IReturn<List<FileSystemEntryInfo>>
{
/// <summary>
/// Gets or sets the path.
/// </summary>
/// <value>The path.</value>
2013-03-08 19:14:09 +00:00
[ApiMember(Name = "Path", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
2013-02-21 01:33:05 +00:00
public string Path { get; set; }
2013-03-08 19:14:09 +00:00
2013-02-21 01:33:05 +00:00
/// <summary>
/// Gets or sets a value indicating whether [include files].
/// </summary>
/// <value><c>true</c> if [include files]; otherwise, <c>false</c>.</value>
2013-03-08 22:41:38 +00:00
[ApiMember(Name = "IncludeFiles", Description = "An optional filter to include or exclude files from the results. true/false", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
2013-02-21 01:33:05 +00:00
public bool IncludeFiles { get; set; }
2013-03-08 19:14:09 +00:00
2013-02-21 01:33:05 +00:00
/// <summary>
/// Gets or sets a value indicating whether [include directories].
/// </summary>
/// <value><c>true</c> if [include directories]; otherwise, <c>false</c>.</value>
2013-03-08 22:41:38 +00:00
[ApiMember(Name = "IncludeDirectories", Description = "An optional filter to include or exclude folders from the results. true/false", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
2013-02-21 01:33:05 +00:00
public bool IncludeDirectories { get; set; }
}
2017-07-07 22:04:46 +00:00
[Route("/Environment/ValidatePath", "POST", Summary = "Gets the contents of a given directory in the file system")]
public class ValidatePath
{
/// <summary>
/// Gets or sets the path.
/// </summary>
/// <value>The path.</value>
[ApiMember(Name = "Path", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
public string Path { get; set; }
public bool ValidateWriteable { get; set; }
2020-06-15 21:43:52 +00:00
2017-07-07 22:04:46 +00:00
public bool? IsFile { get; set; }
}
2019-11-28 16:46:06 +00:00
[Obsolete]
2014-03-28 19:58:18 +00:00
[Route("/Environment/NetworkShares", "GET", Summary = "Gets shares from a network device")]
public class GetNetworkShares : IReturn<List<FileSystemEntryInfo>>
{
/// <summary>
/// Gets or sets the path.
/// </summary>
/// <value>The path.</value>
[ApiMember(Name = "Path", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
public string Path { get; set; }
}
2013-02-21 01:33:05 +00:00
/// <summary>
/// Class GetDrives.
2013-02-21 01:33:05 +00:00
/// </summary>
2014-03-28 19:58:18 +00:00
[Route("/Environment/Drives", "GET", Summary = "Gets available drives from the server's file system")]
2013-02-21 01:33:05 +00:00
public class GetDrives : IReturn<List<FileSystemEntryInfo>>
{
}
2013-09-06 20:25:03 +00:00
/// <summary>
/// Class GetNetworkComputers.
2013-09-06 20:25:03 +00:00
/// </summary>
2014-03-28 19:58:18 +00:00
[Route("/Environment/NetworkDevices", "GET", Summary = "Gets a list of devices on the network")]
2013-09-06 20:25:03 +00:00
public class GetNetworkDevices : IReturn<List<FileSystemEntryInfo>>
{
}
2014-03-28 19:58:18 +00:00
[Route("/Environment/ParentPath", "GET", Summary = "Gets the parent path of a given path")]
public class GetParentPath : IReturn<string>
{
/// <summary>
/// Gets or sets the path.
/// </summary>
/// <value>The path.</value>
[ApiMember(Name = "Path", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
public string Path { get; set; }
}
public class DefaultDirectoryBrowserInfo
{
public string Path { get; set; }
}
[Route("/Environment/DefaultDirectoryBrowser", "GET", Summary = "Gets the parent path of a given path")]
public class GetDefaultDirectoryBrowser : IReturn<DefaultDirectoryBrowserInfo>
{
}
2013-02-21 01:33:05 +00:00
/// <summary>
/// Class EnvironmentService.
2013-02-21 01:33:05 +00:00
/// </summary>
2014-12-16 05:46:54 +00:00
[Authenticated(Roles = "Admin", AllowBeforeStartupWizard = true)]
2013-03-16 05:52:33 +00:00
public class EnvironmentService : BaseApiService
2013-02-21 01:33:05 +00:00
{
private const char UncSeparator = '\\';
private const string UncSeparatorString = "\\";
/// <summary>
/// The _network manager.
/// </summary>
private readonly INetworkManager _networkManager;
2017-07-07 22:04:46 +00:00
private readonly IFileSystem _fileSystem;
/// <summary>
/// Initializes a new instance of the <see cref="EnvironmentService" /> class.
/// </summary>
/// <param name="networkManager">The network manager.</param>
public EnvironmentService(
ILogger<EnvironmentService> logger,
IServerConfigurationManager serverConfigurationManager,
IHttpResultFactory httpResultFactory,
INetworkManager networkManager,
IFileSystem fileSystem)
: base(logger, serverConfigurationManager, httpResultFactory)
{
_networkManager = networkManager;
2015-09-15 01:16:31 +00:00
_fileSystem = fileSystem;
}
2017-07-07 22:04:46 +00:00
public void Post(ValidatePath request)
{
if (request.IsFile.HasValue)
{
if (request.IsFile.Value)
{
if (!File.Exists(request.Path))
2017-07-07 22:04:46 +00:00
{
throw new FileNotFoundException("File not found", request.Path);
}
}
else
{
if (!Directory.Exists(request.Path))
2017-07-07 22:04:46 +00:00
{
throw new FileNotFoundException("File not found", request.Path);
}
}
}
else
{
if (!File.Exists(request.Path) && !Directory.Exists(request.Path))
2017-07-07 22:04:46 +00:00
{
throw new FileNotFoundException("Path not found", request.Path);
}
if (request.ValidateWriteable)
{
EnsureWriteAccess(request.Path);
}
}
}
protected void EnsureWriteAccess(string path)
{
var file = Path.Combine(path, Guid.NewGuid().ToString());
File.WriteAllText(file, string.Empty);
2017-07-07 22:04:46 +00:00
_fileSystem.DeleteFile(file);
}
public object Get(GetDefaultDirectoryBrowser request) =>
2020-03-24 15:12:06 +00:00
ToOptimizedResult(new DefaultDirectoryBrowserInfo { Path = null });
2013-02-21 01:33:05 +00:00
/// <summary>
/// Gets the specified request.
/// </summary>
/// <param name="request">The request.</param>
/// <returns>System.Object.</returns>
public object Get(GetDirectoryContents request)
{
var path = request.Path;
if (string.IsNullOrEmpty(path))
{
throw new ArgumentNullException(nameof(Path));
2013-02-21 01:33:05 +00:00
}
2016-11-01 03:07:45 +00:00
var networkPrefix = UncSeparatorString + UncSeparatorString;
2013-10-01 21:18:31 +00:00
2019-11-28 16:46:06 +00:00
if (path.StartsWith(networkPrefix, StringComparison.OrdinalIgnoreCase)
&& path.LastIndexOf(UncSeparator) == 1)
2013-02-21 01:33:05 +00:00
{
2019-11-28 16:46:06 +00:00
return ToOptimizedResult(Array.Empty<FileSystemEntryInfo>());
2013-02-21 01:33:05 +00:00
}
2018-09-12 17:26:21 +00:00
return ToOptimizedResult(GetFileSystemEntries(request).ToList());
2013-02-21 01:33:05 +00:00
}
2019-11-28 16:46:06 +00:00
[Obsolete]
public object Get(GetNetworkShares request)
2019-11-28 16:46:06 +00:00
=> ToOptimizedResult(Array.Empty<FileSystemEntryInfo>());
2013-02-21 01:33:05 +00:00
/// <summary>
/// Gets the specified request.
/// </summary>
/// <param name="request">The request.</param>
/// <returns>System.Object.</returns>
public object Get(GetDrives request)
{
var result = GetDrives().ToList();
2018-09-12 17:26:21 +00:00
return ToOptimizedResult(result);
2013-02-21 01:33:05 +00:00
}
/// <summary>
/// Gets the list that is returned when an empty path is supplied.
2013-02-21 01:33:05 +00:00
/// </summary>
/// <returns>IEnumerable{FileSystemEntryInfo}.</returns>
private IEnumerable<FileSystemEntryInfo> GetDrives()
{
return _fileSystem.GetDrives().Select(d => new FileSystemEntryInfo(d.Name, d.FullName, FileSystemEntryType.Directory));
2013-02-21 01:33:05 +00:00
}
2013-09-06 20:25:03 +00:00
/// <summary>
/// Gets the specified request.
/// </summary>
/// <param name="request">The request.</param>
/// <returns>System.Object.</returns>
public object Get(GetNetworkDevices request)
2019-11-28 16:46:06 +00:00
=> ToOptimizedResult(Array.Empty<FileSystemEntryInfo>());
2013-02-21 01:33:05 +00:00
/// <summary>
/// Gets the file system entries.
/// </summary>
/// <param name="request">The request.</param>
/// <returns>IEnumerable{FileSystemEntryInfo}.</returns>
private IEnumerable<FileSystemEntryInfo> GetFileSystemEntries(GetDirectoryContents request)
{
2017-08-30 18:06:54 +00:00
var entries = _fileSystem.GetFileSystemEntries(request.Path).OrderBy(i => i.FullName).Where(i =>
2013-02-21 01:33:05 +00:00
{
2015-11-12 20:51:39 +00:00
var isDirectory = i.IsDirectory;
if (!request.IncludeFiles && !isDirectory)
{
return false;
}
2020-04-05 18:44:14 +00:00
return request.IncludeDirectories || !isDirectory;
});
2013-02-21 01:33:05 +00:00
return entries.Select(f => new FileSystemEntryInfo(f.Name, f.FullName, f.IsDirectory ? FileSystemEntryType.Directory : FileSystemEntryType.File));
2013-02-21 01:33:05 +00:00
}
public object Get(GetParentPath request)
2013-02-21 01:33:05 +00:00
{
var parent = Path.GetDirectoryName(request.Path);
if (string.IsNullOrEmpty(parent))
{
// Check if unc share
var index = request.Path.LastIndexOf(UncSeparator);
if (index != -1 && request.Path.IndexOf(UncSeparator) == 0)
{
parent = request.Path.Substring(0, index);
if (string.IsNullOrWhiteSpace(parent.TrimStart(UncSeparator)))
{
parent = null;
}
}
}
return parent;
2013-02-21 01:33:05 +00:00
}
}
}