< Summary - Jellyfin

Information
Class: Jellyfin.Api.Controllers.EnvironmentController
Assembly: Jellyfin.Api
File(s): /srv/git/jellyfin/Jellyfin.Api/Controllers/EnvironmentController.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 40
Coverable lines: 40
Total lines: 182
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 30
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100 11/7/2025 - 12:11:55 AM Line coverage: 0% (0/40) Branch coverage: 0% (0/30) Total lines: 1971/29/2026 - 12:13:32 AM Line coverage: 0% (0/40) Branch coverage: 0% (0/30) Total lines: 182 11/7/2025 - 12:11:55 AM Line coverage: 0% (0/40) Branch coverage: 0% (0/30) Total lines: 1971/29/2026 - 12:13:32 AM Line coverage: 0% (0/40) Branch coverage: 0% (0/30) Total lines: 182

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%210%
GetDirectoryContents(...)0%2040%
ValidatePath(...)0%342180%
GetDrives()100%210%
GetParentPath(...)0%7280%
GetDefaultDirectoryBrowser()100%210%

File(s)

/srv/git/jellyfin/Jellyfin.Api/Controllers/EnvironmentController.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.ComponentModel.DataAnnotations;
 4using System.IO;
 5using System.Linq;
 6using Jellyfin.Api.Models.EnvironmentDtos;
 7using MediaBrowser.Common.Api;
 8using MediaBrowser.Common.Extensions;
 9using MediaBrowser.Model.IO;
 10using Microsoft.AspNetCore.Authorization;
 11using Microsoft.AspNetCore.Http;
 12using Microsoft.AspNetCore.Mvc;
 13using Microsoft.Extensions.Logging;
 14
 15namespace Jellyfin.Api.Controllers;
 16
 17/// <summary>
 18/// Environment Controller.
 19/// </summary>
 20[Authorize(Policy = Policies.FirstTimeSetupOrElevated)]
 21public class EnvironmentController : BaseJellyfinApiController
 22{
 23    private const char UncSeparator = '\\';
 24    private const string UncStartPrefix = @"\\";
 25
 26    private readonly IFileSystem _fileSystem;
 27    private readonly ILogger<EnvironmentController> _logger;
 28
 29    /// <summary>
 30    /// Initializes a new instance of the <see cref="EnvironmentController"/> class.
 31    /// </summary>
 32    /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
 33    /// <param name="logger">Instance of the <see cref="ILogger{EnvironmentController}"/> interface.</param>
 034    public EnvironmentController(IFileSystem fileSystem, ILogger<EnvironmentController> logger)
 35    {
 036        _fileSystem = fileSystem;
 037        _logger = logger;
 038    }
 39
 40    /// <summary>
 41    /// Gets the contents of a given directory in the file system.
 42    /// </summary>
 43    /// <param name="path">The path.</param>
 44    /// <param name="includeFiles">An optional filter to include or exclude files from the results. true/false.</param>
 45    /// <param name="includeDirectories">An optional filter to include or exclude folders from the results. true/false.<
 46    /// <response code="200">Directory contents returned.</response>
 47    /// <returns>Directory contents.</returns>
 48    [HttpGet("DirectoryContents")]
 49    [ProducesResponseType(StatusCodes.Status200OK)]
 50    public IEnumerable<FileSystemEntryInfo> GetDirectoryContents(
 51        [FromQuery, Required] string path,
 52        [FromQuery] bool includeFiles = false,
 53        [FromQuery] bool includeDirectories = false)
 54    {
 055        if (path.StartsWith(UncStartPrefix, StringComparison.OrdinalIgnoreCase)
 056            && path.LastIndexOf(UncSeparator) == 1)
 57        {
 058            return Array.Empty<FileSystemEntryInfo>();
 59        }
 60
 061        var entries =
 062            _fileSystem.GetFileSystemEntries(path)
 063                .Where(i => (i.IsDirectory && includeDirectories) || (!i.IsDirectory && includeFiles))
 064                .OrderBy(i => i.FullName);
 65
 066        return entries.Select(f => new FileSystemEntryInfo(f.Name, f.FullName, f.IsDirectory ? FileSystemEntryType.Direc
 67    }
 68
 69    /// <summary>
 70    /// Validates path.
 71    /// </summary>
 72    /// <param name="validatePathDto">Validate request object.</param>
 73    /// <response code="204">Path validated.</response>
 74    /// <response code="404">Path not found.</response>
 75    /// <returns>Validation status.</returns>
 76    [HttpPost("ValidatePath")]
 77    [ProducesResponseType(StatusCodes.Status204NoContent)]
 78    [ProducesResponseType(StatusCodes.Status404NotFound)]
 79    public ActionResult ValidatePath([FromBody, Required] ValidatePathDto validatePathDto)
 80    {
 081        if (validatePathDto.IsFile.HasValue)
 82        {
 083            if (validatePathDto.IsFile.Value)
 84            {
 085                if (!System.IO.File.Exists(validatePathDto.Path))
 86                {
 087                    return NotFound();
 88                }
 89            }
 90            else
 91            {
 092                if (!Directory.Exists(validatePathDto.Path))
 93                {
 094                    return NotFound();
 95                }
 96            }
 97        }
 98        else
 99        {
 0100            if (!System.IO.File.Exists(validatePathDto.Path) && !Directory.Exists(validatePathDto.Path))
 101            {
 0102                return NotFound();
 103            }
 104
 0105            if (validatePathDto.ValidateWritable)
 106            {
 0107                if (validatePathDto.Path is null)
 108                {
 0109                    throw new ResourceNotFoundException(nameof(validatePathDto.Path));
 110                }
 111
 0112                var file = Path.Combine(validatePathDto.Path, Guid.NewGuid().ToString());
 113                try
 114                {
 0115                    System.IO.File.WriteAllText(file, string.Empty);
 0116                }
 117                finally
 118                {
 0119                    if (System.IO.File.Exists(file))
 120                    {
 0121                        System.IO.File.Delete(file);
 122                    }
 0123                }
 124            }
 125        }
 126
 0127        return NoContent();
 128    }
 129
 130    /// <summary>
 131    /// Gets available drives from the server's file system.
 132    /// </summary>
 133    /// <response code="200">List of entries returned.</response>
 134    /// <returns>List of entries.</returns>
 135    [HttpGet("Drives")]
 136    [ProducesResponseType(StatusCodes.Status200OK)]
 137    public IEnumerable<FileSystemEntryInfo> GetDrives()
 138    {
 0139        return _fileSystem.GetDrives().Select(d => new FileSystemEntryInfo(d.Name, d.FullName, FileSystemEntryType.Direc
 140    }
 141
 142    /// <summary>
 143    /// Gets the parent path of a given path.
 144    /// </summary>
 145    /// <param name="path">The path.</param>
 146    /// <returns>Parent path.</returns>
 147    [HttpGet("ParentPath")]
 148    [ProducesResponseType(StatusCodes.Status200OK)]
 149    public ActionResult<string?> GetParentPath([FromQuery, Required] string path)
 150    {
 0151        string? parent = Path.GetDirectoryName(path);
 0152        if (string.IsNullOrEmpty(parent))
 153        {
 154            // Check if unc share
 0155            var index = path.LastIndexOf(UncSeparator);
 156
 0157            if (index != -1 && path[0] == UncSeparator)
 158            {
 0159                parent = path.Substring(0, index);
 160
 0161                if (string.IsNullOrWhiteSpace(parent.TrimStart(UncSeparator)))
 162                {
 0163                    parent = null;
 164                }
 165            }
 166        }
 167
 0168        return parent;
 169    }
 170
 171    /// <summary>
 172    /// Get Default directory browser.
 173    /// </summary>
 174    /// <response code="200">Default directory browser returned.</response>
 175    /// <returns>Default directory browser.</returns>
 176    [HttpGet("DefaultDirectoryBrowser")]
 177    [ProducesResponseType(StatusCodes.Status200OK)]
 178    public ActionResult<DefaultDirectoryBrowserInfoDto> GetDefaultDirectoryBrowser()
 179    {
 0180        return new DefaultDirectoryBrowserInfoDto();
 181    }
 182}