Beispiel #1
0
        public async Task <HttpResponseMessage> Download(string indexerID, string path, string jackett_apikey, string file)
        {
            try
            {
                var indexer = indexerService.GetWebIndexer(indexerID);

                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."));
                }

                path = Encoding.UTF8.GetString(HttpServerUtility.UrlTokenDecode(path));
                path = protectionService.UnProtect(path);

                if (config.APIKey != jackett_apikey)
                {
                    return(new HttpResponseMessage(HttpStatusCode.Unauthorized));
                }

                var target        = new Uri(path, UriKind.RelativeOrAbsolute);
                var downloadBytes = await indexer.Download(target);

                // 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    // :
                    )
                {
                    var magneturi = Encoding.UTF8.GetString(downloadBytes);
                    var response  = Request.CreateResponse(HttpStatusCode.Moved);
                    response.Headers.Location = new Uri(magneturi);
                    return(response);
                }

                // This will fix torrents where the keys are not sorted, and thereby not supported by Sonarr.
                var    parser              = new BencodeParser();
                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);
            }
            catch (Exception e)
            {
                logger.Error(e, "Error downloading " + indexerID + " " + path);
                return(new HttpResponseMessage(HttpStatusCode.NotFound));
            }
        }
Beispiel #2
0
        public async Task <IHttpActionResult> Blackhole(string indexerID, string path, string jackett_apikey, string file)
        {
            var jsonReply = new JObject();

            try
            {
                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.");
                }

                if (serverConfig.APIKey != jackett_apikey)
                {
                    throw new Exception("Incorrect API key");
                }

                path = Encoding.UTF8.GetString(HttpServerUtility.UrlTokenDecode(path));
                path = protectionService.UnProtect(path);
                var remoteFile    = new Uri(path, UriKind.RelativeOrAbsolute);
                var downloadBytes = await indexer.Download(remoteFile);

                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 += ".torrent";
                }
                else
                {
                    fileName += "-" + StringUtil.MakeValidFileName(file, '_', false); // call MakeValidFileName() again to avoid any possibility of path traversal attacks
                }
                File.WriteAllBytes(Path.Combine(serverConfig.BlackholeDir, fileName), downloadBytes);
                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));
        }
Beispiel #3
0
        public async Task <HttpResponseMessage> Download(string indexerID, string path, string jackett_apikey, string file)
        {
            try
            {
                var indexer = indexerService.GetWebIndexer(indexerID);

                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."));
                }

                path = Encoding.UTF8.GetString(HttpServerUtility.UrlTokenDecode(path));
                path = protectionService.UnProtect(path);

                if (serverService.Config.APIKey != jackett_apikey)
                {
                    return(new HttpResponseMessage(HttpStatusCode.Unauthorized));
                }

                var target        = new Uri(path, UriKind.RelativeOrAbsolute);
                var downloadBytes = await indexer.Download(target);

                // This will fix torrents where the keys are not sorted, and thereby not supported by Sonarr.
                var torrentDictionary = BEncodedDictionary.DecodeTorrent(downloadBytes);
                downloadBytes = torrentDictionary.Encode();

                var result = new HttpResponseMessage(HttpStatusCode.OK);
                result.Content = new ByteArrayContent(downloadBytes);
                result.Content.Headers.ContentType        = new MediaTypeHeaderValue("application/x-bittorrent");
                result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
                {
                    FileName = StringUtil.MakeValidFileName(file, '_', false) // call MakeValidFileName again to avoid any kind of injection attack
                };
                return(result);
            }
            catch (Exception e)
            {
                logger.Error(e, "Error downloading " + indexerID + " " + path);
                return(new HttpResponseMessage(HttpStatusCode.NotFound));
            }
        }
Beispiel #4
0
        public async Task <IActionResult> DownloadImage(string indexerID, string path, string jackett_apikey, string file)
        {
            try
            {
                if (serverConfig.APIKey != jackett_apikey)
                {
                    return(Unauthorized());
                }

                var indexer = indexerService.GetWebIndexer(indexerID);
                if (!indexer.IsConfigured)
                {
                    logger.Warn($"Rejected a request to {indexer.DisplayName} which is unconfigured.");
                    return(Forbid("This indexer is not configured."));
                }

                path = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(path));
                path = protectionService.UnProtect(path);

                var target   = new Uri(path, UriKind.RelativeOrAbsolute);
                var response = await indexer.DownloadImage(target);

                if (response.Status != System.Net.HttpStatusCode.OK &&
                    response.Status != System.Net.HttpStatusCode.Continue &&
                    response.Status != System.Net.HttpStatusCode.PartialContent)
                {
                    return(new StatusCodeResult((int)response.Status));
                }

                var contentType = response.Headers.ContainsKey("content-type") ?
                                  response.Headers["content-type"].First() :
                                  "image/jpeg";
                return(File(response.ContentBytes, contentType));
            }
            catch (Exception e)
            {
                logger.Debug($"Error downloading image. indexer: {indexerID} path: {path}\n{e}");
                return(new StatusCodeResult((int)System.Net.HttpStatusCode.InternalServerError));
            }
        }
Beispiel #5
0
        public async Task <IActionResult> Blackhole(string indexerID, string path, string jackett_apikey, string file)
        {
            var jsonReply = new JObject();

            try
            {
                if (serverConfig.APIKey != jackett_apikey)
                {
                    return(Unauthorized());
                }

                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.");
                }

                path = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(path));
                path = protectionService.UnProtect(path);
                var remoteFile    = new Uri(path, UriKind.RelativeOrAbsolute);
                var fileExtension = ".torrent";

                byte[] downloadBytes;
                if (remoteFile.OriginalString.StartsWith("magnet"))
                {
                    downloadBytes = Encoding.UTF8.GetBytes(remoteFile.OriginalString);
                }
                else
                {
                    downloadBytes = await indexer.Download(remoteFile);
                }

                // 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
                {
                    fileName += "-" + StringUtil.MakeValidFileName(file + fileExtension, '_', false); // call MakeValidFileName() again to avoid any possibility of path traversal attacks
                }
                System.IO.File.WriteAllBytes(Path.Combine(serverConfig.BlackholeDir, fileName), downloadBytes);
                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));
        }
        public async Task <IActionResult> Download(string indexerID, string path, string jackett_apikey, string file)
        {
            try
            {
                if (serverConfig.APIKey != jackett_apikey)
                {
                    return(Unauthorized());
                }

                var indexer = indexerService.GetWebIndexer(indexerID);

                if (!indexer.IsConfigured)
                {
                    logger.Warn(string.Format("Rejected a request to {0} which is unconfigured.", indexer.DisplayName));
                    return(Forbid("This indexer is not configured."));
                }

                path = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(path));
                path = protectionService.UnProtect(path);

                var target        = new Uri(path, UriKind.RelativeOrAbsolute);
                var downloadBytes = await indexer.Download(target);

                // 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    // :
                    )
                {
                    // some sites provide magnet links with non-ascii characters, the only way to be sure the url
                    // is well encoded is to unscape and escape again
                    // https://github.com/Jackett/Jackett/issues/5372
                    // https://github.com/Jackett/Jackett/issues/4761
                    var magneturi = Uri.EscapeUriString(Uri.UnescapeDataString(Encoding.UTF8.GetString(downloadBytes)));
                    return(Redirect(magneturi));
                }

                // This will fix torrents where the keys are not sorted, and thereby not supported by Sonarr.
                byte[] sortedDownloadBytes = null;
                try
                {
                    var parser            = new BencodeParser();
                    var torrentDictionary = parser.Parse(downloadBytes);
                    sortedDownloadBytes = torrentDictionary.EncodeAsBytes();
                }
                catch (Exception e)
                {
                    var content = indexer.Encoding.GetString(downloadBytes);
                    logger.Error(content);
                    throw new Exception("BencodeParser failed", e);
                }

                var 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(NotFound());
            }
        }
        public async Task <IActionResult> Download(string indexerID, string path, string jackett_apikey, string file)
        {
            try
            {
                if (serverConfig.APIKey != jackett_apikey)
                {
                    return(Unauthorized());
                }

                var indexer = indexerService.GetWebIndexer(indexerID);

                if (!indexer.IsConfigured)
                {
                    logger.Warn($"Rejected a request to {indexer.DisplayName} which is unconfigured.");
                    return(Forbid("This indexer is not configured."));
                }

                path = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(path));
                path = protectionService.UnProtect(path);

                var target        = new Uri(path, UriKind.RelativeOrAbsolute);
                var downloadBytes = await indexer.Download(target);

                // 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    // :
                    )
                {
                    var magnetUrl = Encoding.UTF8.GetString(downloadBytes);
                    return(Redirect(magnetUrl));
                }

                // This will fix torrents where the keys are not sorted, and thereby not supported by Sonarr.
                byte[] sortedDownloadBytes = null;
                try
                {
                    var parser            = new BencodeParser();
                    var torrentDictionary = parser.Parse(downloadBytes);
                    sortedDownloadBytes = torrentDictionary.EncodeAsBytes();
                }
                catch (Exception e)
                {
                    var content = indexer.Encoding.GetString(downloadBytes);
                    logger.Error(content);
                    throw new Exception("BencodeParser failed", e);
                }

                var 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($"Error downloading. indexer: {indexerID} path: {path}\n{e}");
                return(NotFound());
            }
        }