diff options
| author | Luke Pulverenti <luke.pulverenti@gmail.com> | 2016-10-25 15:02:04 -0400 |
|---|---|---|
| committer | Luke Pulverenti <luke.pulverenti@gmail.com> | 2016-10-25 15:02:04 -0400 |
| commit | ef6b90b8e6e6c317fcda85a392c79324f91250db (patch) | |
| tree | 570c78c0915d3608399f003038b66d56e5e29e84 /MediaBrowser.Model | |
| parent | edbe28d9fc3091121b7e2323fe42d62a70c9e351 (diff) | |
make controller project portable
Diffstat (limited to 'MediaBrowser.Model')
| -rw-r--r-- | MediaBrowser.Model/Globalization/ILocalizationManager.cs | 2 | ||||
| -rw-r--r-- | MediaBrowser.Model/IO/FileSystemMetadata.cs | 56 | ||||
| -rw-r--r-- | MediaBrowser.Model/IO/IFileSystem.cs | 414 | ||||
| -rw-r--r-- | MediaBrowser.Model/IO/IShortcutHandler.cs | 25 | ||||
| -rw-r--r-- | MediaBrowser.Model/MediaBrowser.Model.csproj | 15 | ||||
| -rw-r--r-- | MediaBrowser.Model/Services/ApiMemberAttribute.cs | 61 | ||||
| -rw-r--r-- | MediaBrowser.Model/Services/IAsyncStreamWriter.cs | 11 | ||||
| -rw-r--r-- | MediaBrowser.Model/Services/IHasHeaders.cs | 9 | ||||
| -rw-r--r-- | MediaBrowser.Model/Services/IHasRequestFilter.cs | 32 | ||||
| -rw-r--r-- | MediaBrowser.Model/Services/IHttpRequest.cs | 46 | ||||
| -rw-r--r-- | MediaBrowser.Model/Services/IHttpResponse.cs | 25 | ||||
| -rw-r--r-- | MediaBrowser.Model/Services/IRequest.cs | 200 | ||||
| -rw-r--r-- | MediaBrowser.Model/Services/IRequiresRequestStream.cs | 12 | ||||
| -rw-r--r-- | MediaBrowser.Model/Services/IService.cs | 12 | ||||
| -rw-r--r-- | MediaBrowser.Model/Services/IStreamWriter.cs | 9 | ||||
| -rw-r--r-- | MediaBrowser.Model/Services/QueryParamCollection.cs | 164 | ||||
| -rw-r--r-- | MediaBrowser.Model/Services/RouteAttribute.cs | 144 |
17 files changed, 1237 insertions, 0 deletions
diff --git a/MediaBrowser.Model/Globalization/ILocalizationManager.cs b/MediaBrowser.Model/Globalization/ILocalizationManager.cs index 6bac81805..b0e1d7fa6 100644 --- a/MediaBrowser.Model/Globalization/ILocalizationManager.cs +++ b/MediaBrowser.Model/Globalization/ILocalizationManager.cs @@ -50,5 +50,7 @@ namespace MediaBrowser.Model.Globalization /// </summary> /// <returns>IEnumerable{LocalizatonOption}.</returns> IEnumerable<LocalizatonOption> GetLocalizationOptions(); + + string RemoveDiacritics(string text); } } diff --git a/MediaBrowser.Model/IO/FileSystemMetadata.cs b/MediaBrowser.Model/IO/FileSystemMetadata.cs new file mode 100644 index 000000000..2aae4bb54 --- /dev/null +++ b/MediaBrowser.Model/IO/FileSystemMetadata.cs @@ -0,0 +1,56 @@ +using System; + +namespace MediaBrowser.Model.IO +{ + public class FileSystemMetadata + { + /// <summary> + /// Gets or sets a value indicating whether this <see cref="FileSystemMetadata"/> is exists. + /// </summary> + /// <value><c>true</c> if exists; otherwise, <c>false</c>.</value> + public bool Exists { get; set; } + /// <summary> + /// Gets or sets the full name. + /// </summary> + /// <value>The full name.</value> + public string FullName { get; set; } + /// <summary> + /// Gets or sets the name. + /// </summary> + /// <value>The name.</value> + public string Name { get; set; } + /// <summary> + /// Gets or sets the extension. + /// </summary> + /// <value>The extension.</value> + public string Extension { get; set; } + /// <summary> + /// Gets or sets the length. + /// </summary> + /// <value>The length.</value> + public long Length { get; set; } + /// <summary> + /// Gets or sets the name of the directory. + /// </summary> + /// <value>The name of the directory.</value> + public string DirectoryName { get; set; } + + /// <summary> + /// Gets or sets the last write time UTC. + /// </summary> + /// <value>The last write time UTC.</value> + public DateTime LastWriteTimeUtc { get; set; } + /// <summary> + /// Gets or sets the creation time UTC. + /// </summary> + /// <value>The creation time UTC.</value> + public DateTime CreationTimeUtc { get; set; } + /// <summary> + /// Gets a value indicating whether this instance is directory. + /// </summary> + /// <value><c>true</c> if this instance is directory; otherwise, <c>false</c>.</value> + public bool IsDirectory { get; set; } + public bool IsHidden { get; set; } + public bool IsReadOnly { get; set; } + } +} diff --git a/MediaBrowser.Model/IO/IFileSystem.cs b/MediaBrowser.Model/IO/IFileSystem.cs new file mode 100644 index 000000000..4ff4fc604 --- /dev/null +++ b/MediaBrowser.Model/IO/IFileSystem.cs @@ -0,0 +1,414 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace MediaBrowser.Model.IO +{ + /// <summary> + /// Interface IFileSystem + /// </summary> + public interface IFileSystem + { + /// <summary> + /// Determines whether the specified filename is shortcut. + /// </summary> + /// <param name="filename">The filename.</param> + /// <returns><c>true</c> if the specified filename is shortcut; otherwise, <c>false</c>.</returns> + bool IsShortcut(string filename); + + /// <summary> + /// Resolves the shortcut. + /// </summary> + /// <param name="filename">The filename.</param> + /// <returns>System.String.</returns> + string ResolveShortcut(string filename); + + /// <summary> + /// Creates the shortcut. + /// </summary> + /// <param name="shortcutPath">The shortcut path.</param> + /// <param name="target">The target.</param> + void CreateShortcut(string shortcutPath, string target); + + /// <summary> + /// Returns a <see cref="FileSystemMetadata"/> object for the specified file or directory path. + /// </summary> + /// <param name="path">A path to a file or directory.</param> + /// <returns>A <see cref="FileSystemMetadata"/> object.</returns> + /// <remarks>If the specified path points to a directory, the returned <see cref="FileSystemMetadata"/> object's + /// <see cref="FileSystemMetadata.IsDirectory"/> property will be set to true and all other properties will reflect the properties of the directory.</remarks> + FileSystemMetadata GetFileSystemInfo(string path); + + /// <summary> + /// Returns a <see cref="FileSystemMetadata"/> object for the specified file path. + /// </summary> + /// <param name="path">A path to a file.</param> + /// <returns>A <see cref="FileSystemMetadata"/> object.</returns> + /// <remarks><para>If the specified path points to a directory, the returned <see cref="FileSystemMetadata"/> object's + /// <see cref="FileSystemMetadata.IsDirectory"/> property and the <see cref="FileSystemMetadata.Exists"/> property will both be set to false.</para> + /// <para>For automatic handling of files <b>and</b> directories, use <see cref="GetFileSystemInfo"/>.</para></remarks> + FileSystemMetadata GetFileInfo(string path); + + /// <summary> + /// Returns a <see cref="FileSystemMetadata"/> object for the specified directory path. + /// </summary> + /// <param name="path">A path to a directory.</param> + /// <returns>A <see cref="FileSystemMetadata"/> object.</returns> + /// <remarks><para>If the specified path points to a file, the returned <see cref="FileSystemMetadata"/> object's + /// <see cref="FileSystemMetadata.IsDirectory"/> property will be set to true and the <see cref="FileSystemMetadata.Exists"/> property will be set to false.</para> + /// <para>For automatic handling of files <b>and</b> directories, use <see cref="GetFileSystemInfo"/>.</para></remarks> + FileSystemMetadata GetDirectoryInfo(string path); + + /// <summary> + /// Gets the valid filename. + /// </summary> + /// <param name="filename">The filename.</param> + /// <returns>System.String.</returns> + string GetValidFilename(string filename); + + /// <summary> + /// Gets the creation time UTC. + /// </summary> + /// <param name="info">The information.</param> + /// <returns>DateTime.</returns> + DateTime GetCreationTimeUtc(FileSystemMetadata info); + + /// <summary> + /// Gets the creation time UTC. + /// </summary> + /// <param name="path">The path.</param> + /// <returns>DateTime.</returns> + DateTime GetCreationTimeUtc(string path); + + /// <summary> + /// Gets the last write time UTC. + /// </summary> + /// <param name="info">The information.</param> + /// <returns>DateTime.</returns> + DateTime GetLastWriteTimeUtc(FileSystemMetadata info); + + /// <summary> + /// Gets the last write time UTC. + /// </summary> + /// <param name="path">The path.</param> + /// <returns>DateTime.</returns> + DateTime GetLastWriteTimeUtc(string path); + + /// <summary> + /// Gets the file stream. + /// </summary> + /// <param name="path">The path.</param> + /// <param name="mode">The mode.</param> + /// <param name="access">The access.</param> + /// <param name="share">The share.</param> + /// <param name="isAsync">if set to <c>true</c> [is asynchronous].</param> + /// <returns>FileStream.</returns> + Stream GetFileStream(string path, FileOpenMode mode, FileAccessMode access, FileShareMode share, bool isAsync = false); + + /// <summary> + /// Opens the read. + /// </summary> + /// <param name="path">The path.</param> + /// <returns>Stream.</returns> + Stream OpenRead(String path); + + /// <summary> + /// Swaps the files. + /// </summary> + /// <param name="file1">The file1.</param> + /// <param name="file2">The file2.</param> + void SwapFiles(string file1, string file2); + + /// <summary> + /// Determines whether [contains sub path] [the specified parent path]. + /// </summary> + /// <param name="parentPath">The parent path.</param> + /// <param name="path">The path.</param> + /// <returns><c>true</c> if [contains sub path] [the specified parent path]; otherwise, <c>false</c>.</returns> + bool ContainsSubPath(string parentPath, string path); + + /// <summary> + /// Determines whether [is root path] [the specified path]. + /// </summary> + /// <param name="path">The path.</param> + /// <returns><c>true</c> if [is root path] [the specified path]; otherwise, <c>false</c>.</returns> + bool IsRootPath(string path); + + /// <summary> + /// Normalizes the path. + /// </summary> + /// <param name="path">The path.</param> + /// <returns>System.String.</returns> + string NormalizePath(string path); + + /// <summary> + /// Gets the file name without extension. + /// </summary> + /// <param name="info">The information.</param> + /// <returns>System.String.</returns> + string GetFileNameWithoutExtension(FileSystemMetadata info); + + /// <summary> + /// Gets the file name without extension. + /// </summary> + /// <param name="path">The path.</param> + /// <returns>System.String.</returns> + string GetFileNameWithoutExtension(string path); + + /// <summary> + /// Determines whether [is path file] [the specified path]. + /// </summary> + /// <param name="path">The path.</param> + /// <returns><c>true</c> if [is path file] [the specified path]; otherwise, <c>false</c>.</returns> + bool IsPathFile(string path); + + /// <summary> + /// Deletes the file. + /// </summary> + /// <param name="path">The path.</param> + void DeleteFile(string path); + + /// <summary> + /// Deletes the directory. + /// </summary> + /// <param name="path">The path.</param> + /// <param name="recursive">if set to <c>true</c> [recursive].</param> + void DeleteDirectory(string path, bool recursive); + + /// <summary> + /// Gets the directories. + /// </summary> + /// <param name="path">The path.</param> + /// <param name="recursive">if set to <c>true</c> [recursive].</param> + /// <returns>IEnumerable<DirectoryInfo>.</returns> + IEnumerable<FileSystemMetadata> GetDirectories(string path, bool recursive = false); + + /// <summary> + /// Gets the files. + /// </summary> + /// <param name="path">The path.</param> + /// <param name="recursive">if set to <c>true</c> [recursive].</param> + /// <returns>IEnumerable<FileInfo>.</returns> + IEnumerable<FileSystemMetadata> GetFiles(string path, bool recursive = false); + + /// <summary> + /// Gets the file system entries. + /// </summary> + /// <param name="path">The path.</param> + /// <param name="recursive">if set to <c>true</c> [recursive].</param> + /// <returns>IEnumerable<FileSystemMetadata>.</returns> + IEnumerable<FileSystemMetadata> GetFileSystemEntries(string path, bool recursive = false); + + /// <summary> + /// Creates the directory. + /// </summary> + /// <param name="path">The path.</param> + void CreateDirectory(string path); + + /// <summary> + /// Copies the file. + /// </summary> + /// <param name="source">The source.</param> + /// <param name="target">The target.</param> + /// <param name="overwrite">if set to <c>true</c> [overwrite].</param> + void CopyFile(string source, string target, bool overwrite); + + /// <summary> + /// Moves the file. + /// </summary> + /// <param name="source">The source.</param> + /// <param name="target">The target.</param> + void MoveFile(string source, string target); + + /// <summary> + /// Moves the directory. + /// </summary> + /// <param name="source">The source.</param> + /// <param name="target">The target.</param> + void MoveDirectory(string source, string target); + + /// <summary> + /// Directories the exists. + /// </summary> + /// <param name="path">The path.</param> + /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns> + bool DirectoryExists(string path); + + /// <summary> + /// Files the exists. + /// </summary> + /// <param name="path">The path.</param> + /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns> + bool FileExists(string path); + + /// <summary> + /// Reads all text. + /// </summary> + /// <param name="path">The path.</param> + /// <returns>System.String.</returns> + string ReadAllText(string path); + + /// <summary> + /// Writes all text. + /// </summary> + /// <param name="path">The path.</param> + /// <param name="text">The text.</param> + void WriteAllText(string path, string text); + + /// <summary> + /// Writes all text. + /// </summary> + /// <param name="path">The path.</param> + /// <param name="text">The text.</param> + /// <param name="encoding">The encoding.</param> + void WriteAllText(string path, string text, Encoding encoding); + + /// <summary> + /// Reads all text. + /// </summary> + /// <param name="path">The path.</param> + /// <param name="encoding">The encoding.</param> + /// <returns>System.String.</returns> + string ReadAllText(string path, Encoding encoding); + + /// <summary> + /// Gets the directory paths. + /// </summary> + /// <param name="path">The path.</param> + /// <param name="recursive">if set to <c>true</c> [recursive].</param> + /// <returns>IEnumerable<System.String>.</returns> + IEnumerable<string> GetDirectoryPaths(string path, bool recursive = false); + + /// <summary> + /// Gets the file paths. + /// </summary> + /// <param name="path">The path.</param> + /// <param name="recursive">if set to <c>true</c> [recursive].</param> + /// <returns>IEnumerable<System.String>.</returns> + IEnumerable<string> GetFilePaths(string path, bool recursive = false); + + /// <summary> + /// Gets the file system entry paths. + /// </summary> + /// <param name="path">The path.</param> + /// <param name="recursive">if set to <c>true</c> [recursive].</param> + /// <returns>IEnumerable<System.String>.</returns> + IEnumerable<string> GetFileSystemEntryPaths(string path, bool recursive = false); + + void SetHidden(string path, bool isHidden); + } + + public enum FileOpenMode + { + // + // Summary: + // Specifies that the operating system should create a new file. This requires System.Security.Permissions.FileIOPermissionAccess.Write + // permission. If the file already exists, an System.IO.IOException exception is + // thrown. + CreateNew = 1, + // + // Summary: + // Specifies that the operating system should create a new file. If the file already + // exists, it will be overwritten. This requires System.Security.Permissions.FileIOPermissionAccess.Write + // permission. FileMode.Create is equivalent to requesting that if the file does + // not exist, use System.IO.FileMode.CreateNew; otherwise, use System.IO.FileMode.Truncate. + // If the file already exists but is a hidden file, an System.UnauthorizedAccessException + // exception is thrown. + Create = 2, + // + // Summary: + // Specifies that the operating system should open an existing file. The ability + // to open the file is dependent on the value specified by the System.IO.FileAccess + // enumeration. A System.IO.FileNotFoundException exception is thrown if the file + // does not exist. + Open = 3, + // + // Summary: + // Specifies that the operating system should open a file if it exists; otherwise, + // a new file should be created. If the file is opened with FileAccess.Read, System.Security.Permissions.FileIOPermissionAccess.Read + // permission is required. If the file access is FileAccess.Write, System.Security.Permissions.FileIOPermissionAccess.Write + // permission is required. If the file is opened with FileAccess.ReadWrite, both + // System.Security.Permissions.FileIOPermissionAccess.Read and System.Security.Permissions.FileIOPermissionAccess.Write + // permissions are required. + OpenOrCreate = 4, + // + // Summary: + // Specifies that the operating system should open an existing file. When the file + // is opened, it should be truncated so that its size is zero bytes. This requires + // System.Security.Permissions.FileIOPermissionAccess.Write permission. Attempts + // to read from a file opened with FileMode.Truncate cause an System.ArgumentException + // exception. + Truncate = 5, + // + // Summary: + // Opens the file if it exists and seeks to the end of the file, or creates a new + // file. This requires System.Security.Permissions.FileIOPermissionAccess.Append + // permission. FileMode.Append can be used only in conjunction with FileAccess.Write. + // Trying to seek to a position before the end of the file throws an System.IO.IOException + // exception, and any attempt to read fails and throws a System.NotSupportedException + // exception. + Append = 6 + } + + [Flags] + public enum FileAccessMode + { + // + // Summary: + // Read access to the file. Data can be read from the file. Combine with Write for + // read/write access. + Read = 1, + // + // Summary: + // Write access to the file. Data can be written to the file. Combine with Read + // for read/write access. + Write = 2, + // + // Summary: + // Read and write access to the file. Data can be written to and read from the file. + ReadWrite = 3 + } + + [Flags] + public enum FileShareMode + { + // + // Summary: + // Declines sharing of the current file. Any request to open the file (by this process + // or another process) will fail until the file is closed. + None = 0, + // + // Summary: + // Allows subsequent opening of the file for reading. If this flag is not specified, + // any request to open the file for reading (by this process or another process) + // will fail until the file is closed. However, even if this flag is specified, + // additional permissions might still be needed to access the file. + Read = 1, + // + // Summary: + // Allows subsequent opening of the file for writing. If this flag is not specified, + // any request to open the file for writing (by this process or another process) + // will fail until the file is closed. However, even if this flag is specified, + // additional permissions might still be needed to access the file. + Write = 2, + // + // Summary: + // Allows subsequent opening of the file for reading or writing. If this flag is + // not specified, any request to open the file for reading or writing (by this process + // or another process) will fail until the file is closed. However, even if this + // flag is specified, additional permissions might still be needed to access the + // file. + ReadWrite = 3, + // + // Summary: + // Allows subsequent deleting of a file. + Delete = 4, + // + // Summary: + // Makes the file handle inheritable by child processes. This is not directly supported + // by Win32. + Inheritable = 16 + } + +} diff --git a/MediaBrowser.Model/IO/IShortcutHandler.cs b/MediaBrowser.Model/IO/IShortcutHandler.cs new file mode 100644 index 000000000..16255e51f --- /dev/null +++ b/MediaBrowser.Model/IO/IShortcutHandler.cs @@ -0,0 +1,25 @@ + +namespace MediaBrowser.Model.IO +{ + public interface IShortcutHandler + { + /// <summary> + /// Gets the extension. + /// </summary> + /// <value>The extension.</value> + string Extension { get; } + /// <summary> + /// Resolves the specified shortcut path. + /// </summary> + /// <param name="shortcutPath">The shortcut path.</param> + /// <returns>System.String.</returns> + string Resolve(string shortcutPath); + /// <summary> + /// Creates the specified shortcut path. + /// </summary> + /// <param name="shortcutPath">The shortcut path.</param> + /// <param name="targetPath">The target path.</param> + /// <returns>System.String.</returns> + void Create(string shortcutPath, string targetPath); + } +} diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index d21529ddc..2d8c4263a 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -136,7 +136,10 @@ <Compile Include="Extensions\LinqExtensions.cs" /> <Compile Include="FileOrganization\SmartMatchInfo.cs" /> <Compile Include="Health\IHealthMonitor.cs" /> + <Compile Include="IO\FileSystemMetadata.cs" /> + <Compile Include="IO\IFileSystem.cs" /> <Compile Include="IO\IMemoryStreamProvider.cs" /> + <Compile Include="IO\IShortcutHandler.cs" /> <Compile Include="IO\StreamDefaults.cs" /> <Compile Include="Globalization\ILocalizationManager.cs" /> <Compile Include="MediaInfo\LiveStreamRequest.cs" /> @@ -163,6 +166,15 @@ <Compile Include="MediaInfo\SubtitleTrackInfo.cs" /> <Compile Include="Net\EndPointInfo.cs" /> <Compile Include="Net\HttpResponse.cs" /> + <Compile Include="Services\ApiMemberAttribute.cs" /> + <Compile Include="Services\IAsyncStreamWriter.cs" /> + <Compile Include="Services\IHasHeaders.cs" /> + <Compile Include="Services\IHasRequestFilter.cs" /> + <Compile Include="Services\IHttpRequest.cs" /> + <Compile Include="Services\IHttpResponse.cs" /> + <Compile Include="Services\IRequest.cs" /> + <Compile Include="Services\IRequiresRequestStream.cs" /> + <Compile Include="Services\IService.cs" /> <Compile Include="Net\MimeTypes.cs" /> <Compile Include="News\INewsService.cs" /> <Compile Include="Notifications\NotificationOption.cs" /> @@ -310,6 +322,9 @@ <Compile Include="Registration\RegistrationInfo.cs" /> <Compile Include="Search\SearchQuery.cs" /> <Compile Include="Serialization\IgnoreDataMemberAttribute.cs" /> + <Compile Include="Services\IStreamWriter.cs" /> + <Compile Include="Services\QueryParamCollection.cs" /> + <Compile Include="Services\RouteAttribute.cs" /> <Compile Include="Session\BrowseRequest.cs" /> <Compile Include="Session\ClientCapabilities.cs" /> <Compile Include="Session\GeneralCommand.cs" /> diff --git a/MediaBrowser.Model/Services/ApiMemberAttribute.cs b/MediaBrowser.Model/Services/ApiMemberAttribute.cs new file mode 100644 index 000000000..4a2831775 --- /dev/null +++ b/MediaBrowser.Model/Services/ApiMemberAttribute.cs @@ -0,0 +1,61 @@ +using System; + +namespace MediaBrowser.Model.Services +{ + [AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = true)] + public class ApiMemberAttribute : Attribute + { + /// <summary> + /// Gets or sets verb to which applies attribute. By default applies to all verbs. + /// </summary> + public string Verb { get; set; } + + /// <summary> + /// Gets or sets parameter type: It can be only one of the following: path, query, body, form, or header. + /// </summary> + public string ParameterType { get; set; } + + /// <summary> + /// Gets or sets unique name for the parameter. Each name must be unique, even if they are associated with different paramType values. + /// </summary> + /// <remarks> + /// <para> + /// Other notes on the name field: + /// If paramType is body, the name is used only for UI and codegeneration. + /// If paramType is path, the name field must correspond to the associated path segment from the path field in the api object. + /// If paramType is query, the name field corresponds to the query param name. + /// </para> + /// </remarks> + public string Name { get; set; } + + /// <summary> + /// Gets or sets the human-readable description for the parameter. + /// </summary> + public string Description { get; set; } + + /// <summary> + /// For path, query, and header paramTypes, this field must be a primitive. For body, this can be a complex or container datatype. + /// </summary> + public string DataType { get; set; } + + /// <summary> + /// For path, this is always true. Otherwise, this field tells the client whether or not the field must be supplied. + /// </summary> + public bool IsRequired { get; set; } + + /// <summary> + /// For query params, this specifies that a comma-separated list of values can be passed to the API. For path and body types, this field cannot be true. + /// </summary> + public bool AllowMultiple { get; set; } + + /// <summary> + /// Gets or sets route to which applies attribute, matches using StartsWith. By default applies to all routes. + /// </summary> + public string Route { get; set; } + + /// <summary> + /// Whether to exclude this property from being included in the ModelSchema + /// </summary> + public bool ExcludeInSchema { get; set; } + } +} diff --git a/MediaBrowser.Model/Services/IAsyncStreamWriter.cs b/MediaBrowser.Model/Services/IAsyncStreamWriter.cs new file mode 100644 index 000000000..b10e12813 --- /dev/null +++ b/MediaBrowser.Model/Services/IAsyncStreamWriter.cs @@ -0,0 +1,11 @@ +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Model.Services +{ + public interface IAsyncStreamWriter + { + Task WriteToAsync(Stream responseStream, CancellationToken cancellationToken); + } +} diff --git a/MediaBrowser.Model/Services/IHasHeaders.cs b/MediaBrowser.Model/Services/IHasHeaders.cs new file mode 100644 index 000000000..35e652b0f --- /dev/null +++ b/MediaBrowser.Model/Services/IHasHeaders.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; + +namespace MediaBrowser.Model.Services +{ + public interface IHasHeaders + { + IDictionary<string, string> Headers { get; } + } +} diff --git a/MediaBrowser.Model/Services/IHasRequestFilter.cs b/MediaBrowser.Model/Services/IHasRequestFilter.cs new file mode 100644 index 000000000..c5c6ccf59 --- /dev/null +++ b/MediaBrowser.Model/Services/IHasRequestFilter.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MediaBrowser.Model.Services +{ + public interface IHasRequestFilter + { + /// <summary> + /// Order in which Request Filters are executed. + /// <0 Executed before global request filters + /// >0 Executed after global request filters + /// </summary> + int Priority { get; } + + /// <summary> + /// The request filter is executed before the service. + /// </summary> + /// <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); + + /// <summary> + /// A new shallow copy of this filter is used on every request. + /// </summary> + /// <returns></returns> + IHasRequestFilter Copy(); + } +} diff --git a/MediaBrowser.Model/Services/IHttpRequest.cs b/MediaBrowser.Model/Services/IHttpRequest.cs new file mode 100644 index 000000000..46c0240cd --- /dev/null +++ b/MediaBrowser.Model/Services/IHttpRequest.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MediaBrowser.Model.Services +{ + public interface IHttpRequest : IRequest + { + /// <summary> + /// The HttpResponse + /// </summary> + IHttpResponse HttpResponse { get; } + + /// <summary> + /// The HTTP Verb + /// </summary> + string HttpMethod { get; } + + /// <summary> + /// The IP Address of the X-Forwarded-For header, null if null or empty + /// </summary> + string XForwardedFor { get; } + + /// <summary> + /// The Port number of the X-Forwarded-Port header, null if null or empty + /// </summary> + int? XForwardedPort { get; } + + /// <summary> + /// The http or https scheme of the X-Forwarded-Proto header, null if null or empty + /// </summary> + string XForwardedProtocol { get; } + + /// <summary> + /// The value of the X-Real-IP header, null if null or empty + /// </summary> + string XRealIp { get; } + + /// <summary> + /// The value of the Accept HTTP Request Header + /// </summary> + string Accept { get; } + } +} diff --git a/MediaBrowser.Model/Services/IHttpResponse.cs b/MediaBrowser.Model/Services/IHttpResponse.cs new file mode 100644 index 000000000..377f303a7 --- /dev/null +++ b/MediaBrowser.Model/Services/IHttpResponse.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading.Tasks; + +namespace MediaBrowser.Model.Services +{ + public interface IHttpResponse : IResponse + { + //ICookies Cookies { get; } + + /// <summary> + /// Adds a new Set-Cookie instruction to Response + /// </summary> + /// <param name="cookie"></param> + void SetCookie(Cookie cookie); + + /// <summary> + /// Removes all pending Set-Cookie instructions + /// </summary> + void ClearCookies(); + } +} diff --git a/MediaBrowser.Model/Services/IRequest.cs b/MediaBrowser.Model/Services/IRequest.cs new file mode 100644 index 000000000..45dc97b76 --- /dev/null +++ b/MediaBrowser.Model/Services/IRequest.cs @@ -0,0 +1,200 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; + +namespace MediaBrowser.Model.Services +{ + public interface IRequest + { + /// <summary> + /// The underlying ASP.NET or HttpListener HttpRequest + /// </summary> + object OriginalRequest { get; } + + IResponse Response { get; } + + /// <summary> + /// The name of the service being called (e.g. Request DTO Name) + /// </summary> + string OperationName { get; set; } + + /// <summary> + /// The Verb / HttpMethod or Action for this request + /// </summary> + string Verb { get; } + + /// <summary> + /// The Request DTO, after it has been deserialized. + /// </summary> + object Dto { get; set; } + + /// <summary> + /// The request ContentType + /// </summary> + string ContentType { get; } + + bool IsLocal { get; } + + string UserAgent { get; } + + IDictionary<string, Cookie> Cookies { get; } + + /// <summary> + /// The expected Response ContentType for this request + /// </summary> + string ResponseContentType { get; set; } + + /// <summary> + /// Whether the ResponseContentType has been explicitly overrided or whether it was just the default + /// </summary> + bool HasExplicitResponseContentType { get; } + + /// <summary> + /// Attach any data to this request that all filters and services can access. + /// </summary> + Dictionary<string, object> Items { get; } + + QueryParamCollection Headers { get; } + + QueryParamCollection QueryString { get; } + + QueryParamCollection FormData { get; } + /// <summary> + /// Buffer the Request InputStream so it can be re-read + /// </summary> + bool UseBufferedStream { get; set; } + + /// <summary> + /// The entire string contents of Request.InputStream + /// </summary> + /// <returns></returns> + string GetRawBody(); + + string RawUrl { get; } + + string AbsoluteUri { get; } + + /// <summary> + /// The Remote Ip as reported by Request.UserHostAddress + /// </summary> + string UserHostAddress { get; } + + /// <summary> + /// The Remote Ip as reported by X-Forwarded-For, X-Real-IP or Request.UserHostAddress + /// </summary> + string RemoteIp { get; } + + /// <summary> + /// The value of the Authorization Header used to send the Api Key, null if not available + /// </summary> + string Authorization { get; } + + /// <summary> + /// e.g. is https or not + /// </summary> + bool IsSecureConnection { get; } + + string[] AcceptTypes { get; } + + string PathInfo { get; } + + Stream InputStream { get; } + + 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> + Uri UrlReferrer { get; } + } + + public interface IHttpFile + { + string Name { get; } + string FileName { get; } + long ContentLength { get; } + string ContentType { get; } + Stream InputStream { get; } + } + + public interface IRequiresRequest + { + IRequest Request { get; set; } + } + + public interface IResponse + { + /// <summary> + /// The underlying ASP.NET or HttpListener HttpResponse + /// </summary> + object OriginalResponse { get; } + + IRequest Request { get; } + + int StatusCode { get; set; } + + string StatusDescription { get; set; } + + string ContentType { get; set; } + + void AddHeader(string name, string value); + + string GetHeader(string name); + + void Redirect(string url); + + Stream OutputStream { get; } + + /// <summary> + /// The Response DTO + /// </summary> + object Dto { get; set; } + + /// <summary> + /// Write once to the Response Stream then close it. + /// </summary> + /// <param name="text"></param> + void Write(string text); + + /// <summary> + /// Buffer the Response OutputStream so it can be written in 1 batch + /// </summary> + bool UseBufferedStream { get; set; } + + /// <summary> + /// Signal that this response has been handled and no more processing should be done. + /// When used in a request or response filter, no more filters or processing is done on this request. + /// </summary> + void Close(); + + /// <summary> + /// Calls Response.End() on ASP.NET HttpResponse otherwise is an alias for Close(). + /// Useful when you want to prevent ASP.NET to provide it's own custom error page. + /// </summary> + void End(); + + /// <summary> + /// Response.Flush() and OutputStream.Flush() seem to have different behaviour in ASP.NET + /// </summary> + void Flush(); + + /// <summary> + /// Gets a value indicating whether this instance is closed. + /// </summary> + bool IsClosed { get; } + + void SetContentLength(long contentLength); + + bool KeepAlive { get; set; } + + //Add Metadata to Response + Dictionary<string, object> Items { get; } + } + +} diff --git a/MediaBrowser.Model/Services/IRequiresRequestStream.cs b/MediaBrowser.Model/Services/IRequiresRequestStream.cs new file mode 100644 index 000000000..0b8ac3ed3 --- /dev/null +++ b/MediaBrowser.Model/Services/IRequiresRequestStream.cs @@ -0,0 +1,12 @@ +using System.IO; + +namespace MediaBrowser.Model.Services +{ + public interface IRequiresRequestStream + { + /// <summary> + /// The raw Http Request Input Stream + /// </summary> + Stream RequestStream { get; set; } + } +} diff --git a/MediaBrowser.Model/Services/IService.cs b/MediaBrowser.Model/Services/IService.cs new file mode 100644 index 000000000..3e0ff280b --- /dev/null +++ b/MediaBrowser.Model/Services/IService.cs @@ -0,0 +1,12 @@ + +namespace MediaBrowser.Model.Services +{ + // marker interface + public interface IService + { + } + + public interface IReturn { } + public interface IReturn<T> : IReturn { } + public interface IReturnVoid : IReturn { } +} diff --git a/MediaBrowser.Model/Services/IStreamWriter.cs b/MediaBrowser.Model/Services/IStreamWriter.cs new file mode 100644 index 000000000..1fc11049e --- /dev/null +++ b/MediaBrowser.Model/Services/IStreamWriter.cs @@ -0,0 +1,9 @@ +using System.IO; + +namespace MediaBrowser.Model.Services +{ + public interface IStreamWriter + { + void WriteTo(Stream responseStream); + } +} diff --git a/MediaBrowser.Model/Services/QueryParamCollection.cs b/MediaBrowser.Model/Services/QueryParamCollection.cs new file mode 100644 index 000000000..6393a87fb --- /dev/null +++ b/MediaBrowser.Model/Services/QueryParamCollection.cs @@ -0,0 +1,164 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using MediaBrowser.Model.Dto; + +namespace MediaBrowser.Model.Services +{ + public class QueryParamCollection : List<NameValuePair> + { + public QueryParamCollection() + { + + } + + public QueryParamCollection(IDictionary<string, string> headers) + { + foreach (var pair in headers) + { + Add(pair.Key, pair.Value); + } + } + + private StringComparison GetStringComparison() + { + return StringComparison.OrdinalIgnoreCase; + } + + private StringComparer GetStringComparer() + { + return StringComparer.OrdinalIgnoreCase; + } + + /// <summary> + /// Adds a new query parameter. + /// </summary> + public void Add(string key, string value) + { + Add(new NameValuePair(key, value)); + } + + public void Set(string key, string value) + { + if (string.IsNullOrWhiteSpace(value)) + { + var stringComparison = GetStringComparison(); + + var parameters = this.Where(p => string.Equals(key, p.Name, stringComparison)).ToArray(); + + foreach (var p in parameters) + { + Remove(p); + } + + return; + } + + foreach (var pair in this) + { + var stringComparison = GetStringComparison(); + + if (string.Equals(key, pair.Name, stringComparison)) + { + pair.Value = value; + return; + } + } + + Add(key, value); + } + + /// <summary> + /// True if the collection contains a query parameter with the given name. + /// </summary> + public bool ContainsKey(string name) + { + return this.Any(p => p.Name == name); + } + + /// <summary> + /// Removes all parameters of the given name. + /// </summary> + /// <returns>The number of parameters that were removed</returns> + /// <exception cref="ArgumentNullException"><paramref name="name" /> is null.</exception> + public int Remove(string name) + { + return RemoveAll(p => p.Name == name); + } + + public string Get(string name) + { + return GetValues(name).FirstOrDefault(); + } + + public string[] GetValues(string name) + { + var stringComparison = GetStringComparison(); + + return this.Where(p => string.Equals(p.Name, name, stringComparison)).Select(p => p.Value).ToArray(); + } + + public Dictionary<string, string> ToDictionary() + { + var stringComparer = GetStringComparer(); + + var headers = new Dictionary<string, string>(stringComparer); + + foreach (var pair in this) + { + headers[pair.Name] = pair.Value; + } + + return headers; + } + + public IEnumerable<string> Keys + { + get { return this.Select(i => i.Name); } + } + + /// <summary> + /// Gets or sets a query parameter value by name. A query may contain multiple values of the same name + /// (i.e. "x=1&x=2"), in which case the value is an array, which works for both getting and setting. + /// </summary> + /// <param name="name">The query parameter name</param> + /// <returns>The query parameter value or array of values</returns> + public string this[string name] + { + get { return Get(name); } + set + { + Set(name, value); + //var parameters = this.Where(p => p.Name == name).ToArray(); + //var values = new[] { value }; + + //for (int i = 0; ; i++) + //{ + // if (i < parameters.Length && i < values.Length) + // { + // if (values[i] == null) + // Remove(parameters[i]); + // else if (values[i] is NameValuePair) + // this[IndexOf(parameters[i])] = (NameValuePair)values[i]; + // else + // parameters[i].Value = values[i]; + // } + // else if (i < parameters.Length) + // Remove(parameters[i]); + // else if (i < values.Length) + // { + // if (values[i] != null) + // { + // if (values[i] is NameValuePair) + // Add((NameValuePair)values[i]); + // else + // Add(name, values[i]); + // } + // } + // else + // break; + //} + } + } + } +} diff --git a/MediaBrowser.Model/Services/RouteAttribute.cs b/MediaBrowser.Model/Services/RouteAttribute.cs new file mode 100644 index 000000000..5a39688da --- /dev/null +++ b/MediaBrowser.Model/Services/RouteAttribute.cs @@ -0,0 +1,144 @@ +using System; + +namespace MediaBrowser.Model.Services +{ + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)] + public class RouteAttribute : Attribute + { + /// <summary> + /// <para>Initializes an instance of the <see cref="RouteAttribute"/> class.</para> + /// </summary> + /// <param name="path"> + /// <para>The path template to map to the request. See + /// <see cref="Path">RouteAttribute.Path</see> + /// for details on the correct format.</para> + /// </param> + public RouteAttribute(string path) + : this(path, null) + { + } + + /// <summary> + /// <para>Initializes an instance of the <see cref="RouteAttribute"/> class.</para> + /// </summary> + /// <param name="path"> + /// <para>The path template to map to the request. See + /// <see cref="Path">RouteAttribute.Path</see> + /// for details on the correct format.</para> + /// </param> + /// <param name="verbs">A comma-delimited list of HTTP verbs supported by the + /// service. If unspecified, all verbs are assumed to be supported.</param> + public RouteAttribute(string path, string verbs) + { + Path = path; + Verbs = verbs; + } + + /// <summary> + /// Gets or sets the path template to be mapped to the request. + /// </summary> + /// <value> + /// A <see cref="String"/> value providing the path mapped to + /// the request. Never <see langword="null"/>. + /// </value> + /// <remarks> + /// <para>Some examples of valid paths are:</para> + /// + /// <list> + /// <item>"/Inventory"</item> + /// <item>"/Inventory/{Category}/{ItemId}"</item> + /// <item>"/Inventory/{ItemPath*}"</item> + /// </list> + /// + /// <para>Variables are specified within "{}" + /// brackets. Each variable in the path is mapped to the same-named property + /// on the request DTO. At runtime, ServiceStack will parse the + /// request URL, extract the variable values, instantiate the request DTO, + /// and assign the variable values into the corresponding request properties, + /// prior to passing the request DTO to the service object for processing.</para> + /// + /// <para>It is not necessary to specify all request properties as + /// variables in the path. For unspecified properties, callers may provide + /// values in the query string. For example: the URL + /// "http://services/Inventory?Category=Books&ItemId=12345" causes the same + /// request DTO to be processed as "http://services/Inventory/Books/12345", + /// provided that the paths "/Inventory" (which supports the first URL) and + /// "/Inventory/{Category}/{ItemId}" (which supports the second URL) + /// are both mapped to the request DTO.</para> + /// + /// <para>Please note that while it is possible to specify property values + /// in the query string, it is generally considered to be less RESTful and + /// less desirable than to specify them as variables in the path. Using the + /// query string to specify property values may also interfere with HTTP + /// caching.</para> + /// + /// <para>The final variable in the path may contain a "*" suffix + /// to grab all remaining segments in the path portion of the request URL and assign + /// them to a single property on the request DTO. + /// For example, if the path "/Inventory/{ItemPath*}" is mapped to the request DTO, + /// then the request URL "http://services/Inventory/Books/12345" will result + /// in a request DTO whose ItemPath property contains "Books/12345". + /// You may only specify one such variable in the path, and it must be positioned at + /// the end of the path.</para> + /// </remarks> + public string Path { get; set; } + + /// <summary> + /// Gets or sets short summary of what the route does. + /// </summary> + public string Summary { get; set; } + + /// <summary> + /// Gets or sets longer text to explain the behaviour of the route. + /// </summary> + public string Notes { get; set; } + + /// <summary> + /// Gets or sets a comma-delimited list of HTTP verbs supported by the service, such as + /// "GET,PUT,POST,DELETE". + /// </summary> + /// <value> + /// A <see cref="String"/> providing a comma-delimited list of HTTP verbs supported + /// by the service, <see langword="null"/> or empty if all verbs are supported. + /// </value> + public string Verbs { get; set; } + + /// <summary> + /// Used to rank the precedences of route definitions in reverse routing. + /// i.e. Priorities below 0 are auto-generated have less precedence. + /// </summary> + public int Priority { get; set; } + + protected bool Equals(RouteAttribute other) + { + return base.Equals(other) + && string.Equals(Path, other.Path) + && string.Equals(Summary, other.Summary) + && string.Equals(Notes, other.Notes) + && string.Equals(Verbs, other.Verbs) + && Priority == other.Priority; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != this.GetType()) return false; + return Equals((RouteAttribute)obj); + } + + public override int GetHashCode() + { + unchecked + { + var hashCode = base.GetHashCode(); + hashCode = (hashCode * 397) ^ (Path != null ? Path.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ (Summary != null ? Summary.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ (Notes != null ? Notes.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ (Verbs != null ? Verbs.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ Priority; + return hashCode; + } + } + } +} |
