EnvironmentService.cs 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. using MediaBrowser.Common.Net;
  2. using MediaBrowser.Model.IO;
  3. using MediaBrowser.Model.Net;
  4. using ServiceStack.ServiceHost;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Globalization;
  8. using System.IO;
  9. using System.Linq;
  10. namespace MediaBrowser.Api
  11. {
  12. /// <summary>
  13. /// Class GetDirectoryContents
  14. /// </summary>
  15. [Route("/Environment/DirectoryContents", "GET")]
  16. [Api(Description = "Gets the contents of a given directory in the file system")]
  17. public class GetDirectoryContents : IReturn<List<FileSystemEntryInfo>>
  18. {
  19. /// <summary>
  20. /// Gets or sets the path.
  21. /// </summary>
  22. /// <value>The path.</value>
  23. [ApiMember(Name = "Path", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
  24. public string Path { get; set; }
  25. /// <summary>
  26. /// Gets or sets a value indicating whether [include files].
  27. /// </summary>
  28. /// <value><c>true</c> if [include files]; otherwise, <c>false</c>.</value>
  29. [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")]
  30. public bool IncludeFiles { get; set; }
  31. /// <summary>
  32. /// Gets or sets a value indicating whether [include directories].
  33. /// </summary>
  34. /// <value><c>true</c> if [include directories]; otherwise, <c>false</c>.</value>
  35. [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")]
  36. public bool IncludeDirectories { get; set; }
  37. /// <summary>
  38. /// Gets or sets a value indicating whether [include hidden].
  39. /// </summary>
  40. /// <value><c>true</c> if [include hidden]; otherwise, <c>false</c>.</value>
  41. [ApiMember(Name = "IncludeHidden", Description = "An optional filter to include or exclude hidden files and folders. true/false", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
  42. public bool IncludeHidden { get; set; }
  43. }
  44. /// <summary>
  45. /// Class GetDrives
  46. /// </summary>
  47. [Route("/Environment/Drives", "GET")]
  48. [Api(Description = "Gets available drives from the server's file system")]
  49. public class GetDrives : IReturn<List<FileSystemEntryInfo>>
  50. {
  51. }
  52. /// <summary>
  53. /// Class GetNetworkComputers
  54. /// </summary>
  55. [Route("/Environment/NetworkDevices", "GET")]
  56. [Api(Description = "Gets a list of devices on the network")]
  57. public class GetNetworkDevices : IReturn<List<FileSystemEntryInfo>>
  58. {
  59. }
  60. /// <summary>
  61. /// Class EnvironmentService
  62. /// </summary>
  63. public class EnvironmentService : BaseApiService
  64. {
  65. /// <summary>
  66. /// The _network manager
  67. /// </summary>
  68. private readonly INetworkManager _networkManager;
  69. /// <summary>
  70. /// Initializes a new instance of the <see cref="EnvironmentService" /> class.
  71. /// </summary>
  72. /// <param name="networkManager">The network manager.</param>
  73. /// <exception cref="System.ArgumentNullException">networkManager</exception>
  74. public EnvironmentService(INetworkManager networkManager)
  75. {
  76. if (networkManager == null)
  77. {
  78. throw new ArgumentNullException("networkManager");
  79. }
  80. _networkManager = networkManager;
  81. }
  82. /// <summary>
  83. /// Gets the specified request.
  84. /// </summary>
  85. /// <param name="request">The request.</param>
  86. /// <returns>System.Object.</returns>
  87. /// <exception cref="System.ArgumentNullException">Path</exception>
  88. /// <exception cref="System.ArgumentException"></exception>
  89. public object Get(GetDirectoryContents request)
  90. {
  91. var path = request.Path;
  92. if (string.IsNullOrEmpty(path))
  93. {
  94. throw new ArgumentNullException("Path");
  95. }
  96. if (path.StartsWith(NetworkPrefix, StringComparison.OrdinalIgnoreCase) && path.LastIndexOf('\\') == 1)
  97. {
  98. return ToOptimizedResult(GetNetworkShares(path).OrderBy(i => i.Path).ToList());
  99. }
  100. // Reject invalid input
  101. if (!Path.IsPathRooted(path))
  102. {
  103. throw new ArgumentException(string.Format("Invalid path: {0}", path));
  104. }
  105. return ToOptimizedResult(GetFileSystemEntries(request).OrderBy(i => i.Path).ToList());
  106. }
  107. /// <summary>
  108. /// Gets the specified request.
  109. /// </summary>
  110. /// <param name="request">The request.</param>
  111. /// <returns>System.Object.</returns>
  112. public object Get(GetDrives request)
  113. {
  114. var result = GetDrives().ToList();
  115. return ToOptimizedResult(result);
  116. }
  117. /// <summary>
  118. /// Gets the list that is returned when an empty path is supplied
  119. /// </summary>
  120. /// <returns>IEnumerable{FileSystemEntryInfo}.</returns>
  121. private IEnumerable<FileSystemEntryInfo> GetDrives()
  122. {
  123. // Only include drives in the ready state or this method could end up being very slow, waiting for drives to timeout
  124. return DriveInfo.GetDrives().Where(d => d.IsReady).Select(d => new FileSystemEntryInfo
  125. {
  126. Name = GetName(d),
  127. Path = d.RootDirectory.FullName,
  128. Type = FileSystemEntryType.Directory
  129. });
  130. }
  131. /// <summary>
  132. /// Gets the specified request.
  133. /// </summary>
  134. /// <param name="request">The request.</param>
  135. /// <returns>System.Object.</returns>
  136. public object Get(GetNetworkDevices request)
  137. {
  138. var result = GetNetworkDevices().OrderBy(i => i.Path).ToList();
  139. return ToOptimizedResult(result);
  140. }
  141. /// <summary>
  142. /// Gets the network computers.
  143. /// </summary>
  144. /// <returns>IEnumerable{FileSystemEntryInfo}.</returns>
  145. private IEnumerable<FileSystemEntryInfo> GetNetworkDevices()
  146. {
  147. return _networkManager.GetNetworkDevices().Select(c => new FileSystemEntryInfo
  148. {
  149. Name = c,
  150. Path = NetworkPrefix + c,
  151. Type = FileSystemEntryType.NetworkComputer
  152. });
  153. }
  154. /// <summary>
  155. /// Gets the name.
  156. /// </summary>
  157. /// <param name="drive">The drive.</param>
  158. /// <returns>System.String.</returns>
  159. private string GetName(DriveInfo drive)
  160. {
  161. return drive.Name;
  162. }
  163. /// <summary>
  164. /// Gets the network shares.
  165. /// </summary>
  166. /// <param name="path">The path.</param>
  167. /// <returns>IEnumerable{FileSystemEntryInfo}.</returns>
  168. private IEnumerable<FileSystemEntryInfo> GetNetworkShares(string path)
  169. {
  170. return _networkManager.GetNetworkShares(path).Where(s => s.ShareType == NetworkShareType.Disk).Select(c => new FileSystemEntryInfo
  171. {
  172. Name = c.Name,
  173. Path = Path.Combine(path, c.Name),
  174. Type = FileSystemEntryType.NetworkShare
  175. });
  176. }
  177. /// <summary>
  178. /// Gets the file system entries.
  179. /// </summary>
  180. /// <param name="request">The request.</param>
  181. /// <returns>IEnumerable{FileSystemEntryInfo}.</returns>
  182. private IEnumerable<FileSystemEntryInfo> GetFileSystemEntries(GetDirectoryContents request)
  183. {
  184. var entries = new DirectoryInfo(request.Path).EnumerateFileSystemInfos().Where(i =>
  185. {
  186. if (!request.IncludeHidden && i.Attributes.HasFlag(FileAttributes.Hidden))
  187. {
  188. return false;
  189. }
  190. var isDirectory = i.Attributes.HasFlag(FileAttributes.Directory);
  191. if (!request.IncludeFiles && !isDirectory)
  192. {
  193. return false;
  194. }
  195. if (!request.IncludeDirectories && isDirectory)
  196. {
  197. return false;
  198. }
  199. return true;
  200. });
  201. return entries.Select(f => new FileSystemEntryInfo
  202. {
  203. Name = f.Name,
  204. Path = f.FullName,
  205. Type = f.Attributes.HasFlag(FileAttributes.Directory) ? FileSystemEntryType.Directory : FileSystemEntryType.File
  206. }).ToList();
  207. }
  208. /// <summary>
  209. /// Gets the network prefix.
  210. /// </summary>
  211. /// <value>The network prefix.</value>
  212. private string NetworkPrefix
  213. {
  214. get { return Path.DirectorySeparatorChar.ToString(CultureInfo.InvariantCulture) + Path.DirectorySeparatorChar.ToString(CultureInfo.InvariantCulture); }
  215. }
  216. }
  217. }