2020-02-09 18:08:34 +00:00
using System ;
using System.IO ;
using System.Text ;
using System.Threading.Tasks ;
using Jackett.Common.Models.Config ;
2018-05-01 12:55:09 +00:00
using Jackett.Common.Services.Interfaces ;
using Jackett.Common.Utils ;
2018-05-12 02:44:47 +00:00
using Microsoft.AspNetCore.Authorization ;
2018-05-01 12:55:09 +00:00
using Microsoft.AspNetCore.Mvc ;
2018-07-14 04:42:46 +00:00
using Microsoft.AspNetCore.WebUtilities ;
2018-05-01 12:55:09 +00:00
using Newtonsoft.Json.Linq ;
2018-05-01 12:03:16 +00:00
using NLog ;
2018-05-01 12:55:09 +00:00
namespace Jackett.Server.Controllers
2018-05-01 12:03:16 +00:00
{
2018-05-12 02:44:47 +00:00
[AllowAnonymous]
2018-05-01 12:55:09 +00:00
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
[Route("bh/{indexerID}")]
public class BlackholeController : Controller
2018-05-01 12:03:16 +00:00
{
private Logger logger ;
private IIndexerManagerService indexerService ;
2020-01-05 06:41:01 +00:00
private ServerConfig serverConfig ;
2018-05-01 12:55:09 +00:00
private IProtectionService protectionService ;
2018-05-01 12:03:16 +00:00
2020-01-05 06:41:01 +00:00
public BlackholeController ( IIndexerManagerService i , Logger l , ServerConfig sConfig , IProtectionService ps )
2018-05-01 12:03:16 +00:00
{
logger = l ;
indexerService = i ;
2020-01-05 06:41:01 +00:00
serverConfig = sConfig ;
2018-05-01 12:03:16 +00:00
protectionService = ps ;
}
[HttpGet]
2018-05-01 12:55:09 +00:00
public async Task < IActionResult > Blackhole ( string indexerID , string path , string jackett_apikey , string file )
2018-05-01 12:03:16 +00:00
{
var jsonReply = new JObject ( ) ;
try
{
2020-01-05 06:41:01 +00:00
if ( serverConfig . APIKey ! = jackett_apikey )
return Unauthorized ( ) ;
2018-05-01 12:03:16 +00:00
var indexer = indexerService . GetWebIndexer ( indexerID ) ;
if ( ! indexer . IsConfigured )
{
logger . Warn ( string . Format ( "Rejected a request to {0} which is unconfigured." , indexer . DisplayName ) ) ;
throw new Exception ( "This indexer is not configured." ) ;
}
2018-07-14 04:42:46 +00:00
path = Encoding . UTF8 . GetString ( WebEncoders . Base64UrlDecode ( path ) ) ;
2018-05-01 12:03:16 +00:00
path = protectionService . UnProtect ( path ) ;
var remoteFile = new Uri ( path , UriKind . RelativeOrAbsolute ) ;
var fileExtension = ".torrent" ;
2019-08-24 07:08:37 +00:00
byte [ ] downloadBytes ;
2020-02-01 18:29:17 +00:00
if ( remoteFile . OriginalString . StartsWith ( "magnet" ) )
2019-08-24 07:08:37 +00:00
downloadBytes = Encoding . UTF8 . GetBytes ( remoteFile . OriginalString ) ;
else
downloadBytes = await indexer . Download ( remoteFile ) ;
2018-05-01 12:03:16 +00:00
// handle magnet URLs
if ( downloadBytes . Length > = 7
& & downloadBytes [ 0 ] = = 0x6d // m
& & downloadBytes [ 1 ] = = 0x61 // a
& & downloadBytes [ 2 ] = = 0x67 // g
& & downloadBytes [ 3 ] = = 0x6e // n
& & downloadBytes [ 4 ] = = 0x65 // e
& & downloadBytes [ 5 ] = = 0x74 // t
& & downloadBytes [ 6 ] = = 0x3a // :
)
{
fileExtension = ".magnet" ;
}
if ( string . IsNullOrWhiteSpace ( serverConfig . BlackholeDir ) )
{
throw new Exception ( "Blackhole directory not set!" ) ;
}
if ( ! Directory . Exists ( serverConfig . BlackholeDir ) )
{
throw new Exception ( "Blackhole directory does not exist: " + serverConfig . BlackholeDir ) ;
}
var fileName = DateTime . Now . Ticks . ToString ( ) + "-" + StringUtil . MakeValidFileName ( indexer . DisplayName , '_' , false ) ;
if ( string . IsNullOrWhiteSpace ( file ) )
fileName + = fileExtension ;
else
2018-05-01 12:55:09 +00:00
fileName + = "-" + StringUtil . MakeValidFileName ( file + fileExtension , '_' , false ) ; // call MakeValidFileName() again to avoid any possibility of path traversal attacks
2018-05-01 12:03:16 +00:00
2018-05-01 12:55:09 +00:00
System . IO . File . WriteAllBytes ( Path . Combine ( serverConfig . BlackholeDir , fileName ) , downloadBytes ) ;
2018-05-01 12:03:16 +00:00
jsonReply [ "result" ] = "success" ;
}
catch ( Exception ex )
{
logger . Error ( ex , "Error downloading to blackhole " + indexerID + " " + path ) ;
jsonReply [ "result" ] = "error" ;
jsonReply [ "error" ] = ex . Message ;
}
return Json ( jsonReply ) ;
}
}
}