diff --git a/src/Jackett.Server/Controllers/BlackholeController.cs b/src/Jackett.Server/Controllers/BlackholeController.cs index d802416b0..68fa777ea 100644 --- a/src/Jackett.Server/Controllers/BlackholeController.cs +++ b/src/Jackett.Server/Controllers/BlackholeController.cs @@ -1,39 +1,37 @@ -using Newtonsoft.Json.Linq; +using Jackett.Common.Models.Config; +using Jackett.Common.Services.Interfaces; +using Jackett.Common.Utils; +using Microsoft.AspNetCore.Mvc; +using Newtonsoft.Json.Linq; using NLog; using System; using System.IO; -using System.Text; +using System.Net; using System.Threading.Tasks; -using System.Web; -using System.Web.Http; -using Jackett.Common.Models.Config; -using Jackett.Common.Services.Interfaces; -using Jackett.Common.Utils; -namespace Jackett.Controllers +namespace Jackett.Server.Controllers { - [AllowAnonymous] - [JackettAPINoCache] - public class BlackholeController : ApiController + //[AllowAnonymous] + [ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)] + [Route("bh/{indexerID}")] + public class BlackholeController : Controller { private Logger logger; private IIndexerManagerService indexerService; private readonly ServerConfig serverConfig; - IProtectionService protectionService; + private IProtectionService protectionService; public BlackholeController(IIndexerManagerService i, Logger l, ServerConfig config, IProtectionService ps) { logger = l; indexerService = i; serverConfig = config; - protectionService = ps; } [HttpGet] - public async Task Blackhole(string indexerID, string path, string jackett_apikey, string file) + public async Task Blackhole(string indexerID, string path, string jackett_apikey, string file) { - var jsonReply = new JObject(); try { @@ -47,7 +45,7 @@ namespace Jackett.Controllers if (serverConfig.APIKey != jackett_apikey) throw new Exception("Incorrect API key"); - path = Encoding.UTF8.GetString(HttpServerUtility.UrlTokenDecode(path)); + path = WebUtility.UrlDecode(path); path = protectionService.UnProtect(path); var remoteFile = new Uri(path, UriKind.RelativeOrAbsolute); var fileExtension = ".torrent"; @@ -81,9 +79,9 @@ namespace Jackett.Controllers if (string.IsNullOrWhiteSpace(file)) fileName += fileExtension; else - fileName += "-"+StringUtil.MakeValidFileName(file + fileExtension, '_', false); // call MakeValidFileName() again to avoid any possibility of path traversal attacks + fileName += "-" + StringUtil.MakeValidFileName(file + fileExtension, '_', false); // call MakeValidFileName() again to avoid any possibility of path traversal attacks - File.WriteAllBytes(Path.Combine(serverConfig.BlackholeDir, fileName), downloadBytes); + System.IO.File.WriteAllBytes(Path.Combine(serverConfig.BlackholeDir, fileName), downloadBytes); jsonReply["result"] = "success"; } catch (Exception ex) diff --git a/src/Jackett.Server/Controllers/DownloadController.cs b/src/Jackett.Server/Controllers/DownloadController.cs index 00bf2bbe1..16da73ce8 100644 --- a/src/Jackett.Server/Controllers/DownloadController.cs +++ b/src/Jackett.Server/Controllers/DownloadController.cs @@ -1,26 +1,24 @@ -using System; -using System.Net; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Text; -using System.Threading.Tasks; -using System.Web; -using System.Web.Http; -using BencodeNET.Parsing; +using BencodeNET.Parsing; using Jackett.Common.Models.Config; using Jackett.Common.Services.Interfaces; using Jackett.Common.Utils; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.WebUtilities; using NLog; +using System; +using System.Text; +using System.Threading.Tasks; -namespace Jackett.Controllers +namespace Jackett.Server.Controllers { - [AllowAnonymous] - [JackettAPINoCache] - public class DownloadController : ApiController + //[AllowAnonymous] + [ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)] + [Route("dl/{indexerID}")] + public class DownloadController : Controller { private ServerConfig config; private Logger logger; - private IIndexerManagerService indexerService; + private IIndexerManagerService indexerService; private IProtectionService protectionService; public DownloadController(IIndexerManagerService i, Logger l, IProtectionService ps, ServerConfig serverConfig) @@ -32,7 +30,7 @@ namespace Jackett.Controllers } [HttpGet] - public async Task Download(string indexerID, string path, string jackett_apikey, string file) + public async Task Download(string indexerID, string path, string jackett_apikey, string file) { try { @@ -41,14 +39,14 @@ namespace Jackett.Controllers if (!indexer.IsConfigured) { logger.Warn(string.Format("Rejected a request to {0} which is unconfigured.", indexer.DisplayName)); - return Request.CreateResponse(HttpStatusCode.Forbidden, "This indexer is not configured."); + return Forbid("This indexer is not configured."); } - path = Encoding.UTF8.GetString(HttpServerUtility.UrlTokenDecode(path)); + path = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(path)); path = protectionService.UnProtect(path); if (config.APIKey != jackett_apikey) - return new HttpResponseMessage(HttpStatusCode.Unauthorized); + return Unauthorized(); var target = new Uri(path, UriKind.RelativeOrAbsolute); var downloadBytes = await indexer.Download(target); @@ -65,9 +63,7 @@ namespace Jackett.Controllers ) { var magneturi = Encoding.UTF8.GetString(downloadBytes); - var response = Request.CreateResponse(HttpStatusCode.Moved); - response.Headers.Location = new Uri(magneturi); - return response; + return Redirect(new Uri(magneturi).ToString()); } // This will fix torrents where the keys are not sorted, and thereby not supported by Sonarr. @@ -75,19 +71,14 @@ namespace Jackett.Controllers var torrentDictionary = parser.Parse(downloadBytes); byte[] sortedDownloadBytes = torrentDictionary.EncodeAsBytes(); - var result = new HttpResponseMessage(HttpStatusCode.OK); - result.Content = new ByteArrayContent(sortedDownloadBytes); - result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-bittorrent"); - result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") - { - FileName = StringUtil.MakeValidFileName(file, '_', false) + ".torrent" // call MakeValidFileName again to avoid any kind of injection attack - }; - return result; + string fileName = StringUtil.MakeValidFileName(file, '_', false) + ".torrent"; // call MakeValidFileName again to avoid any kind of injection attack + + return File(sortedDownloadBytes, "application/x-bittorrent", fileName); } catch (Exception e) { logger.Error(e, "Error downloading " + indexerID + " " + path); - return new HttpResponseMessage(HttpStatusCode.NotFound); + return NotFound(); } } } diff --git a/src/Jackett.Server/Controllers/IndexerApiController.cs b/src/Jackett.Server/Controllers/IndexerApiController.cs index 46703e1b5..382d88acf 100644 --- a/src/Jackett.Server/Controllers/IndexerApiController.cs +++ b/src/Jackett.Server/Controllers/IndexerApiController.cs @@ -1,21 +1,18 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using System.Web.Http; -using System.Web.Http.Controllers; -using System.Web.Http.Filters; -using Jackett.Common; -using Jackett.Common.Indexers; +using Jackett.Common.Indexers; using Jackett.Common.Models; using Jackett.Common.Services.Interfaces; using Jackett.Common.Utils; -using Jackett.Utils; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using NLog; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; -namespace Jackett.Controllers +namespace Jackett.Server.Controllers { public interface IIndexerController { @@ -23,19 +20,17 @@ namespace Jackett.Controllers IIndexer CurrentIndexer { get; set; } } - public class RequiresIndexerAttribute : ActionFilterAttribute + public class RequiresIndexer : IActionFilter { - public override void OnActionExecuting(HttpActionContext actionContext) + public void OnActionExecuting(ActionExecutingContext context) { - base.OnActionExecuting(actionContext); - - var controller = actionContext.ControllerContext.Controller; + var controller = context.Controller; if (!(controller is IIndexerController)) return; var indexerController = controller as IIndexerController; - var parameters = actionContext.RequestContext.RouteData.Values; + var parameters = context.RouteData.Values; if (!parameters.ContainsKey("indexerId")) { @@ -51,15 +46,23 @@ namespace Jackett.Controllers var indexer = indexerService.GetIndexer(indexerId); indexerController.CurrentIndexer = indexer; } + + public void OnActionExecuted(ActionExecutedContext context) + { + // do something after the action executes + } } - [RoutePrefix("api/v2.0/indexers")] - [JackettAuthorized] - [JackettAPINoCache] - public class IndexerApiController : ApiController, IIndexerController + [Route("api/v2.0/indexers")] + //[JackettAuthorized] + [ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)] + public class IndexerApiController : Controller, IIndexerController { public IIndexerManagerService IndexerService { get; private set; } public IIndexer CurrentIndexer { get; set; } + private Logger logger; + private IServerService serverService; + private ICacheService cacheService; public IndexerApiController(IIndexerManagerService indexerManagerService, IServerService ss, ICacheService c, Logger logger) { @@ -70,16 +73,17 @@ namespace Jackett.Controllers } [HttpGet] - [RequiresIndexer] - public async Task Config() + [TypeFilter(typeof(RequiresIndexer))] + [Route("{indexerId?}/Config")] + public async Task Config() { var config = await CurrentIndexer.GetConfigurationForSetup(); return Ok(config.ToJson(null)); } [HttpPost] - [ActionName("Config")] - [RequiresIndexer] + [Route("{indexerId?}/Config")] + [TypeFilter(typeof(RequiresIndexer))] public async Task UpdateConfig([FromBody]Common.Models.DTO.ConfigItem[] config) { try @@ -111,14 +115,16 @@ namespace Jackett.Controllers } [HttpPost] - [RequiresIndexer] - public async Task Test() + [Route("{indexerid}/[action]")] + [TypeFilter(typeof(RequiresIndexer))] + public async Task Test() { JToken jsonReply = new JObject(); try { await IndexerService.TestIndexer(CurrentIndexer.ID); CurrentIndexer.LastError = null; + return NoContent(); } catch (Exception ex) { @@ -134,8 +140,8 @@ namespace Jackett.Controllers } [HttpDelete] - [RequiresIndexer] - [Route("{indexerId}")] + [TypeFilter(typeof(RequiresIndexer))] + [Route("{indexerid}")] public void Delete() { IndexerService.DeleteIndexer(CurrentIndexer.ID); @@ -160,14 +166,10 @@ namespace Jackett.Controllers var link = result.Link; var file = StringUtil.MakeValidFileName(result.Title, '_', false); result.Link = serverService.ConvertToProxyLink(link, serverUrl, result.TrackerId, "dl", file); - if (result.Link != null && result.Link.Scheme != "magnet" && !string.IsNullOrWhiteSpace(Engine.ServerConfig.BlackholeDir)) + if (result.Link != null && result.Link.Scheme != "magnet" && !string.IsNullOrWhiteSpace(serverService.GetBlackholeDirectory())) result.BlackholeLink = serverService.ConvertToProxyLink(link, serverUrl, result.TrackerId, "bh", file); - } } - private Logger logger; - private IServerService serverService; - private ICacheService cacheService; } } diff --git a/src/Jackett.Server/Controllers/ResultsController.cs b/src/Jackett.Server/Controllers/ResultsController.cs index 8d139c8e1..4c27e24cc 100644 --- a/src/Jackett.Server/Controllers/ResultsController.cs +++ b/src/Jackett.Server/Controllers/ResultsController.cs @@ -1,59 +1,73 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Net; -using System.Net.Http; -using System.Text; -using System.Threading.Tasks; -using System.Web.Http; -using System.Web.Http.Controllers; -using System.Web.Http.Filters; -using System.Xml.Linq; -using Jackett.Common; +using Jackett.Common; using Jackett.Common.Indexers; using Jackett.Common.Indexers.Meta; using Jackett.Common.Models; using Jackett.Common.Models.DTO; using Jackett.Common.Services.Interfaces; using Jackett.Common.Utils; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; using NLog; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml.Linq; -namespace Jackett.Controllers +namespace Jackett.Server.Controllers { - public class RequiresApiKeyAttribute : AuthorizationFilterAttribute + public class RequiresApiKey : IActionFilter { - public override void OnAuthorization(HttpActionContext actionContext) + public IServerService serverService; + + public RequiresApiKey(IServerService ss) { - var validApiKey = Engine.ServerConfig.APIKey; - var queryParams = actionContext.Request.GetQueryNameValuePairs(); + serverService = ss; + } + + public void OnActionExecuting(ActionExecutingContext context) + { + var validApiKey = serverService.GetApiKey(); + var queryParams = context.HttpContext.Request.Query; var queryApiKey = queryParams.Where(x => x.Key == "apikey" || x.Key == "passkey").Select(x => x.Value).FirstOrDefault(); #if DEBUG if (Debugger.IsAttached) + { return; + } #endif if (queryApiKey != validApiKey) - actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized); + { + context.Result = new UnauthorizedResult(); + return; + } + } + + public void OnActionExecuted(ActionExecutedContext context) + { + // do something after the action executes } } - public class RequiresConfiguredIndexerAttribute : ActionFilterAttribute + public class RequiresConfiguredIndexer : IActionFilter { - public override void OnActionExecuting(HttpActionContext actionContext) + public void OnActionExecuting(ActionExecutingContext context) { - var controller = actionContext.ControllerContext.Controller; + var controller = context.Controller; if (!(controller is IIndexerController)) return; var indexerController = controller as IIndexerController; - var parameters = actionContext.RequestContext.RouteData.Values; + var parameters = context.RouteData.Values; if (!parameters.ContainsKey("indexerId")) { indexerController.CurrentIndexer = null; - actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "Invalid parameter"); + context.Result = new UnauthorizedResult(); return; } @@ -61,7 +75,7 @@ namespace Jackett.Controllers if (indexerId.IsNullOrEmptyOrWhitespace()) { indexerController.CurrentIndexer = null; - actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "Invalid parameter"); + context.Result = new UnauthorizedResult(); return; } @@ -71,63 +85,68 @@ namespace Jackett.Controllers if (indexer == null) { indexerController.CurrentIndexer = null; - actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "Invalid parameter"); + context.Result = new UnauthorizedResult(); return; } if (!indexer.IsConfigured) { indexerController.CurrentIndexer = null; - actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "Indexer is not configured"); + context.Result = new UnauthorizedResult(); return; } indexerController.CurrentIndexer = indexer; } + + public void OnActionExecuted(ActionExecutedContext context) + { + // do something after the action executes + } } - public class RequiresValidQueryAttribute : RequiresConfiguredIndexerAttribute + public class RequiresValidQuery : IActionFilter { - public override void OnActionExecuting(HttpActionContext actionContext) + public void OnActionExecuting(ActionExecutingContext context) { - base.OnActionExecuting(actionContext); - if (actionContext.Response != null) - return; + //TODO: Not sure what this is meant to do + //if (context.HttpContext.Response != null) + // return; - var controller = actionContext.ControllerContext.Controller; + var controller = context.Controller; if (!(controller is IResultController)) + { return; + } var resultController = controller as IResultController; - var query = actionContext.ActionArguments.First().Value; + var query = context.ActionArguments.First().Value; var queryType = query.GetType(); var converter = queryType.GetMethod("ToTorznabQuery", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public); if (converter == null) - actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, ""); + { + context.Result = new BadRequestResult(); + } + var converted = converter.Invoke(null, new object[] { query }); var torznabQuery = converted as TorznabQuery; resultController.CurrentQuery = torznabQuery; if (queryType == typeof(ApiSearch)) // Skip CanHandleQuery() check for manual search (CurrentIndexer isn't used during manul search) + { return; + } if (!resultController.CurrentIndexer.CanHandleQuery(resultController.CurrentQuery)) - actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, $"{resultController.CurrentIndexer.ID} does not support the requested query. Please check the capabilities (t=caps) and make sure the search mode and categories are supported."); + { + context.Result = new BadRequestObjectResult($"{resultController.CurrentIndexer.ID} does not support the requested query. Please check the capabilities (t=caps) and make sure the search mode and categories are supported."); + } } - } - public class JsonResponseAttribute : ActionFilterAttribute - { - public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) + public void OnActionExecuted(ActionExecutedContext context) { - base.OnActionExecuted(actionExecutedContext); - - if (actionExecutedContext.Exception != null) - throw new Exception("Error while executing request", actionExecutedContext.Exception); - - var content = actionExecutedContext.Response.Content as ObjectContent; - actionExecutedContext.Response.Content = new JsonContent(content.Value); + // do something after the action executes } } @@ -136,12 +155,13 @@ namespace Jackett.Controllers TorznabQuery CurrentQuery { get; set; } } - [AllowAnonymous] - [JackettAPINoCache] - [RoutePrefix("api/v2.0/indexers")] - [RequiresApiKey] - [RequiresValidQuery] - public class ResultsController : ApiController, IResultController + //[AllowAnonymous] + [ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)] + [Route("api/v2.0/indexers/{indexerId}/results")] + [TypeFilter(typeof(RequiresApiKey))] + [TypeFilter(typeof(RequiresConfiguredIndexer))] + [TypeFilter(typeof(RequiresValidQuery))] + public class ResultsController : Controller, IResultController { public IIndexerManagerService IndexerService { get; private set; } public IIndexer CurrentIndexer { get; set; } @@ -155,13 +175,39 @@ namespace Jackett.Controllers this.logger = logger; } + [Route("")] [HttpGet] - public async Task Results([FromUri]ApiSearch request) + public async Task Results([FromQuery] ApiSearch requestt) { + //TODO: Better way to parse querystring + + ApiSearch request = new ApiSearch(); + + foreach (var t in Request.Query) + { + if (t.Key == "Tracker[]") + { + request.Tracker = t.Value.ToString().Split(","); + } + + if (t.Key == "Category[]") + { + request.Category = t.Value.ToString().Split(",").Select(Int32.Parse).ToArray(); + } + + if (t.Key == "query") + { + request.Query = t.Value.ToString(); + } + } + var manualResult = new ManualSearchResult(); - var trackers = IndexerService.GetAllIndexers().Where(t => t.IsConfigured); + var trackers = IndexerService.GetAllIndexers().ToList().Where(t => t.IsConfigured); if (request.Tracker != null) + { trackers = trackers.Where(t => request.Tracker.Contains(t.ID)); + } + trackers = trackers.Where(t => t.CanHandleQuery(CurrentQuery)); var tasks = trackers.ToList().Select(t => t.ResultsForQuery(CurrentQuery)).ToList(); @@ -235,18 +281,16 @@ namespace Jackett.Controllers ConfigureCacheResults(manualResult.Results); logger.Info(string.Format("Manual search for \"{0}\" on {1} with {2} results.", CurrentQuery.SanitizedSearchTerm, string.Join(", ", manualResult.Indexers.Select(i => i.ID)), manualResult.Results.Count())); - return manualResult; + return Json(manualResult); } + [Route("[action]/{ignored?}")] [HttpGet] - public async Task Torznab([FromUri]Common.Models.DTO.TorznabRequest request) + public async Task Torznab([FromQuery]TorznabRequest request) { if (string.Equals(CurrentQuery.QueryType, "caps", StringComparison.InvariantCultureIgnoreCase)) { - return ResponseMessage(new HttpResponseMessage() - { - Content = new StringContent(CurrentIndexer.TorznabCaps.ToXml(), Encoding.UTF8, "application/xml") - }); + return Content(CurrentIndexer.TorznabCaps.ToXml(), "application/rss+xml", Encoding.UTF8); } // indexers - returns a list of all included indexers (meta indexers only) @@ -254,7 +298,7 @@ namespace Jackett.Controllers { if (!(CurrentIndexer is BaseMetaIndexer)) // shouldn't be needed because CanHandleQuery should return false { - logger.Warn($"A search request with t=indexers from {Request.GetOwinContext().Request.RemoteIpAddress} was made but the indexer {CurrentIndexer.DisplayName} isn't a meta indexer."); + logger.Warn($"A search request with t=indexers from {Request.HttpContext.Connection.RemoteIpAddress} was made but the indexer {CurrentIndexer.DisplayName} isn't a meta indexer."); return GetErrorXML(203, "Function Not Available: this isn't a meta indexer"); } var CurrentBaseMetaIndexer = (BaseMetaIndexer)CurrentIndexer; @@ -281,30 +325,27 @@ namespace Jackett.Controllers ) ); - return ResponseMessage(new HttpResponseMessage() - { - Content = new StringContent(xdoc.Declaration.ToString() + Environment.NewLine + xdoc.ToString(), Encoding.UTF8, "application/xml") - }); + return Content(xdoc.Declaration.ToString() + Environment.NewLine + xdoc.ToString(), "application/xml", Encoding.UTF8); } if (CurrentQuery.ImdbID != null) { if (!string.IsNullOrEmpty(CurrentQuery.SearchTerm)) { - logger.Warn($"A search request from {Request.GetOwinContext().Request.RemoteIpAddress} was made containing q and imdbid."); + logger.Warn($"A search request from {Request.HttpContext.Connection.RemoteIpAddress} was made containing q and imdbid."); return GetErrorXML(201, "Incorrect parameter: please specify either imdbid or q"); } CurrentQuery.ImdbID = ParseUtil.GetFullImdbID(CurrentQuery.ImdbID); // normalize ImdbID if (CurrentQuery.ImdbID == null) { - logger.Warn($"A search request from {Request.GetOwinContext().Request.RemoteIpAddress} was made with an invalid imdbid."); + logger.Warn($"A search request from {Request.HttpContext.Connection.RemoteIpAddress} was made with an invalid imdbid."); return GetErrorXML(201, "Incorrect parameter: invalid imdbid format"); } if (!CurrentIndexer.TorznabCaps.SupportsImdbSearch) { - logger.Warn($"A search request with imdbid from {Request.GetOwinContext().Request.RemoteIpAddress} was made but the indexer {CurrentIndexer.DisplayName} doesn't support it."); + logger.Warn($"A search request with imdbid from {Request.HttpContext.Connection.RemoteIpAddress} was made but the indexer {CurrentIndexer.DisplayName} doesn't support it."); return GetErrorXML(203, "Function Not Available: imdbid is not supported by this indexer"); } } @@ -361,13 +402,12 @@ namespace Jackett.Controllers var xml = resultPage.ToXml(new Uri(serverUrl)); // Force the return as XML - return ResponseMessage(new HttpResponseMessage() - { - Content = new StringContent(xml, Encoding.UTF8, "application/rss+xml") - }); + + return Content(xml, "application/rss+xml", Encoding.UTF8); } - public IHttpActionResult GetErrorXML(int code, string description) + [Route("[action]/{ignored?}")] + public IActionResult GetErrorXML(int code, string description) { var xdoc = new XDocument( new XDeclaration("1.0", "UTF-8", null), @@ -378,16 +418,12 @@ namespace Jackett.Controllers ); var xml = xdoc.Declaration.ToString() + Environment.NewLine + xdoc.ToString(); - - return ResponseMessage(new HttpResponseMessage() - { - Content = new StringContent(xml, Encoding.UTF8, "application/xml") - }); + return Content(xml, "application/xml", Encoding.UTF8); } + [Route("[action]/{ignored?}")] [HttpGet] - [JsonResponse] - public async Task Potato([FromUri]TorrentPotatoRequest request) + public async Task Potato([FromQuery]TorrentPotatoRequest request) { var result = await CurrentIndexer.ResultsForQuery(CurrentQuery); @@ -431,6 +467,7 @@ namespace Jackett.Controllers return potatoResponse; } + [Route("[action]/{ignored?}")] private void ConfigureCacheResults(IEnumerable results) { var serverUrl = serverService.GetServerUrl(Request); @@ -439,9 +476,8 @@ namespace Jackett.Controllers var link = result.Link; var file = StringUtil.MakeValidFileName(result.Title, '_', false); result.Link = serverService.ConvertToProxyLink(link, serverUrl, result.TrackerId, "dl", file); - if (result.Link != null && result.Link.Scheme != "magnet" && !string.IsNullOrWhiteSpace(Engine.ServerConfig.BlackholeDir)) + if (result.Link != null && result.Link.Scheme != "magnet" && !string.IsNullOrWhiteSpace(serverService.GetBlackholeDirectory())) result.BlackholeLink = serverService.ConvertToProxyLink(link, serverUrl, result.TrackerId, "bh", file); - } } diff --git a/src/Jackett.Server/Controllers/ServerConfigurationController.cs b/src/Jackett.Server/Controllers/ServerConfigurationController.cs index 04d7bf1b4..5d3a59579 100644 --- a/src/Jackett.Server/Controllers/ServerConfigurationController.cs +++ b/src/Jackett.Server/Controllers/ServerConfigurationController.cs @@ -1,23 +1,20 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using System.Web.Http; -using Jackett.Common; -using Jackett.Common.Models; +using Jackett.Common.Models; using Jackett.Common.Models.Config; using Jackett.Common.Services.Interfaces; using Jackett.Common.Utils; -using Jackett.Utils; +using Microsoft.AspNetCore.Mvc; using NLog; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; -namespace Jackett.Controllers +namespace Jackett.Server.Controllers { - [RoutePrefix("api/v2.0/server")] - [JackettAuthorized] - [JackettAPINoCache] - public class ServerConfigurationController : ApiController + [Route("api/v2.0/server/[action]")] + //[JackettAuthorized] + [ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)] + public class ServerConfigurationController : Controller { private readonly IConfigurationService configService; private ServerConfig serverConfig; @@ -29,7 +26,7 @@ namespace Jackett.Controllers private ILogCacheService logCache; private Logger logger; - public ServerConfigurationController(IConfigurationService c, IServerService s, IProcessService p, IIndexerManagerService i, ISecuityService ss, IUpdateService u, ILogCacheService lc, Logger l, ServerConfig sc) + public ServerConfigurationController(IConfigurationService c, IServerService s, IProcessService p, IIndexerManagerService i, ISecuityService ss, IUpdateService u, ILogCacheService lc, Logger l, ServerConfig sc) { configService = c; serverConfig = sc; @@ -65,14 +62,13 @@ namespace Jackett.Controllers [HttpGet] public Common.Models.DTO.ServerConfig Config() { - var dto = new Common.Models.DTO.ServerConfig(serverService.notices, serverConfig, configService.GetVersion()); return dto; } [ActionName("Config")] [HttpPost] - public void UpdateConfig([FromBody]Common.Models.DTO.ServerConfig config) + public IActionResult UpdateConfig([FromBody]Common.Models.DTO.ServerConfig config) { var originalPort = serverConfig.Port; var originalAllowExternal = serverConfig.AllowExternal; @@ -95,16 +91,16 @@ namespace Jackett.Controllers serverConfig.UpdateDisabled = updateDisabled; serverConfig.UpdatePrerelease = preRelease; serverConfig.BasePathOverride = basePathOverride; - serverConfig.RuntimeSettings.BasePath = Engine.Server.BasePath(); + serverConfig.RuntimeSettings.BasePath = serverService.BasePath(); configService.SaveConfig(serverConfig); - Engine.SetLogLevel(logging ? LogLevel.Debug : LogLevel.Info); + Initialisation.SetLogLevel(logging ? LogLevel.Debug : LogLevel.Info); serverConfig.RuntimeSettings.TracingEnabled = logging; if (omdbApiKey != serverConfig.OmdbApiKey) { serverConfig.OmdbApiKey = omdbApiKey; - configService.SaveConfig(serverConfig); + configService.SaveConfig(serverConfig); // HACK indexerService.InitAggregateIndexer(); } @@ -128,7 +124,6 @@ namespace Jackett.Controllers if (port != serverConfig.Port || external != serverConfig.AllowExternal) { - if (ServerUtil.RestrictedPorts.Contains(port)) throw new Exception("The port you have selected is restricted, try a different one."); @@ -147,7 +142,8 @@ namespace Jackett.Controllers { try { - processService.StartProcessAndLog(System.Windows.Forms.Application.ExecutablePath, "--ReserveUrls", true); + //TODO + //processService.StartProcessAndLog(System.Windows.Forms.Application.ExecutablePath, "--ReserveUrls", true); } catch { @@ -163,15 +159,15 @@ namespace Jackett.Controllers serverService.ReserveUrls(true); } } - - (new Thread(() => - { - Thread.Sleep(500); - serverService.Stop(); - Engine.BuildContainer(serverConfig.RuntimeSettings, new WebApi2Module()); - Engine.Server.Initalize(); - Engine.Server.Start(); - })).Start(); + //TODO + //(new Thread(() => + //{ + // Thread.Sleep(500); + // serverService.Stop(); + // Engine.BuildContainer(serverConfig.RuntimeSettings, new WebApi2Module()); + // Engine.Server.Initalize(); + // Engine.Server.Start(); + //})).Start(); } if (saveDir != serverConfig.BlackholeDir) @@ -187,8 +183,10 @@ namespace Jackett.Controllers serverConfig.BlackholeDir = saveDir; configService.SaveConfig(serverConfig); } - + serverConfig.ConfigChanged(); + + return Json(serverConfig); } [HttpGet] @@ -196,7 +194,5 @@ namespace Jackett.Controllers { return logCache.Logs; } - - } } diff --git a/src/Jackett.Server/Controllers/UIController.cs b/src/Jackett.Server/Controllers/UIController.cs index 3d0cca1f9..3269e1afc 100644 --- a/src/Jackett.Server/Controllers/UIController.cs +++ b/src/Jackett.Server/Controllers/UIController.cs @@ -1,21 +1,20 @@ -using System.IO; +using Jackett.Common.Models.Config; +using Jackett.Common.Services.Interfaces; +using Microsoft.AspNetCore.Mvc; +using MimeMapping; +using NLog; +using System.IO; using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Threading.Tasks; -using System.Web.Http; -using Jackett.Common.Models.Config; -using Jackett.Common.Services.Interfaces; -using Jackett.Utils; -using MimeMapping; -using NLog; -namespace Jackett.Controllers +namespace Jackett.Server.Controllers { - [RoutePrefix("UI")] - [JackettAuthorized] - [JackettAPINoCache] - public class WebUIController : ApiController + [Route("UI/[action]")] + //[JackettAuthorized] + [ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)] + public class WebUIController : Controller { private IConfigurationService config; private ServerConfig serverConfig; @@ -42,50 +41,50 @@ namespace Jackett.Controllers } [HttpGet] - [AllowAnonymous] - public IHttpActionResult Logout() + //[AllowAnonymous] + public IActionResult Logout() { - var ctx = Request.GetOwinContext(); - var authManager = ctx.Authentication; - authManager.SignOut("ApplicationCookie"); - return Redirect("UI/Dashboard"); + var ctx = Request.HttpContext; + //TODO + //var authManager = ctx.Authentication; + //authManager.SignOut("ApplicationCookie"); + return Redirect("Dashboard"); } [HttpGet] [HttpPost] - [AllowAnonymous] + //[AllowAnonymous] public async Task Dashboard() { - if (Request.RequestUri.Query != null && Request.RequestUri.Query.Contains("logout")) + if (Request.Path != null && Request.Path.ToString().Contains("logout")) { var file = GetFile("login.html"); securityService.Logout(file); return file; } + //TODO - if (securityService.CheckAuthorised(Request)) - { - return GetFile("index.html"); + //if (securityService.CheckAuthorised(Request)) + //{ + return GetFile("index.html"); - } - else - { - var formData = await Request.Content.ReadAsFormDataAsync(); + //} + //else + //{ + // var formData = await Request.ReadFormAsync(); - if (formData != null && securityService.HashPassword(formData["password"]) == serverConfig.AdminPassword) - { - var file = GetFile("index.html"); - securityService.Login(file); - return file; - } - else - { - return GetFile("login.html"); - } - } + // if (formData != null && securityService.HashPassword(formData["password"]) == serverConfig.AdminPassword) + // { + // var file = GetFile("index.html"); + // securityService.Login(file); + // return file; + // } + // else + // { + // return GetFile("login.html"); + // } + //} } - - } } diff --git a/src/Jackett.Server/Controllers/ValuesController.cs b/src/Jackett.Server/Controllers/ValuesController.cs deleted file mode 100644 index 928d9f8c8..000000000 --- a/src/Jackett.Server/Controllers/ValuesController.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Mvc; - -namespace Jackett.Server.Controllers -{ - [Route("api/[controller]")] - public class ValuesController : Controller - { - // GET api/values - [HttpGet] - public IEnumerable Get() - { - return new string[] { "value1", "value2" }; - } - - // GET api/values/5 - [HttpGet("{id}")] - public string Get(int id) - { - return "value"; - } - - // POST api/values - [HttpPost] - public void Post([FromBody]string value) - { - } - - // PUT api/values/5 - [HttpPut("{id}")] - public void Put(int id, [FromBody]string value) - { - } - - // DELETE api/values/5 - [HttpDelete("{id}")] - public void Delete(int id) - { - } - } -}