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)); } }
public string ConvertToNormalLink(string link) { var encodedLink = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(link)); var decryptedLink = _protectionService.UnProtect(encodedLink); return(decryptedLink); }
public void LoadValuesFromJson(JToken json, IProtectionService ps = null) { if (json == null) { return; } var arr = (JArray)json; foreach (var item in GetItems(forDisplay: false)) { var arrItem = arr.FirstOrDefault(f => f.Value <string>("id") == item.ID); if (arrItem == null) { continue; } switch (item.ItemType) { case ItemType.InputString: var sItem = (StringItem)item; var newValue = arrItem.Value <string>("value"); if (string.Equals(item.Name, "password", StringComparison.InvariantCultureIgnoreCase)) { if (newValue != PASSWORD_REPLACEMENT) { sItem.Value = newValue; if (ps != null) { sItem.Value = ps.UnProtect(newValue); } } } else { sItem.Value = newValue; } break; case ItemType.HiddenData: ((HiddenItem)item).Value = arrItem.Value <string>("value"); break; case ItemType.InputBool: ((BoolItem)item).Value = arrItem.Value <bool>("value"); break; case ItemType.Recaptcha: ((RecaptchaItem)item).Value = arrItem.Value <string>("value"); ((RecaptchaItem)item).Cookie = arrItem.Value <string>("cookie"); ((RecaptchaItem)item).Version = arrItem.Value <string>("version"); ((RecaptchaItem)item).Challenge = arrItem.Value <string>("challenge"); break; } } }
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)); }
public override void FromJson(JToken jsonToken, IProtectionService ps = null) { if (HasPasswordValue(this)) { var pw = ReadValueAs <string>(jsonToken); if (pw != PASSWORD_REPLACEMENT) { Value = ps != null?ps.UnProtect(pw) : pw; } } else { Value = ReadValueAs <string>(jsonToken); } }
public void LoadValuesFromJson(JToken json, IProtectionService ps= null) { if (json == null) return; var arr = (JArray)json; foreach (var item in GetItems(forDisplay: false)) { var arrItem = arr.FirstOrDefault(f => f.Value<string>("id") == item.ID); if (arrItem == null) continue; switch (item.ItemType) { case ItemType.InputString: var sItem = (StringItem)item; var newValue = arrItem.Value<string>("value"); if (string.Equals(item.Name, "password", StringComparison.InvariantCultureIgnoreCase)) { if (newValue != PASSWORD_REPLACEMENT) { sItem.Value = newValue; if (ps != null) sItem.Value = ps.UnProtect(newValue); } } else { sItem.Value = newValue; } break; case ItemType.HiddenData: ((HiddenItem)item).Value = arrItem.Value<string>("value"); break; case ItemType.InputBool: ((BoolItem)item).Value = arrItem.Value<bool>("value"); break; case ItemType.Recaptcha: ((RecaptchaItem)item).Value = arrItem.Value<string>("value"); ((RecaptchaItem)item).Cookie = arrItem.Value<string>("cookie"); ((RecaptchaItem)item).Version = arrItem.Value<string>("version"); ((RecaptchaItem)item).Challenge = arrItem.Value<string>("challenge"); break; } } }
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)); } }
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)); } }
//TODO: Remove this section once users have moved off DPAPI private bool MigratedFromDPAPI(JToken jsonConfig) { bool isWindows = Environment.OSVersion.Platform == PlatformID.Win32NT; if (!isWindows && DotNetCoreUtil.IsRunningOnDotNetCore) { // User isn't running Windows, but is running on .NET Core framework, no access to the DPAPI, so don't bother trying to migrate return(false); } LoadValuesFromJson(jsonConfig, false); StringItem passwordPropertyValue = null; string passwordValue = ""; try { // try dynamic items first (e.g. all cardigann indexers) passwordPropertyValue = (StringItem)configData.GetDynamicByName("password"); if (passwordPropertyValue == null) // if there's no dynamic password try the static property { passwordPropertyValue = (StringItem)configData.GetType().GetProperty("Password").GetValue(configData, null); // protection is based on the item.Name value (property name might be different, example: Abnormal), so check the Name again if (!string.Equals(passwordPropertyValue.Name, "password", StringComparison.InvariantCultureIgnoreCase)) { logger.Debug($"Skipping non default password property (unencrpyted password) for [{ID}] while attempting migration"); return(false); } } passwordValue = passwordPropertyValue.Value; } catch (Exception) { logger.Debug($"Unable to source password for [{ID}] while attempting migration, likely a tracker without a password setting"); return(false); } if (!string.IsNullOrEmpty(passwordValue)) { try { protectionService.UnProtect(passwordValue); //Password successfully unprotected using Microsoft.AspNetCore.DataProtection, no further action needed as we've already converted the password previously return(false); } catch (Exception ex) { if (ex.Message != "The provided payload cannot be decrypted because it was not protected with this protection provider.") { logger.Info($"Password could not be unprotected using Microsoft.AspNetCore.DataProtection - {ID} : " + ex); } logger.Info($"Attempting legacy Unprotect - {ID} : "); try { string unprotectedPassword = protectionService.LegacyUnProtect(passwordValue); //Password successfully unprotected using Windows/Mono DPAPI passwordPropertyValue.Value = unprotectedPassword; SaveConfig(); IsConfigured = true; logger.Info($"Password successfully migrated for {ID}"); return(true); } catch (Exception exception) { logger.Info($"Password could not be unprotected using legacy DPAPI - {ID} : " + exception); } } } return(false); }
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)); }
//TODO: Remove this section once users have moved off DPAPI private bool MigratedFromDPAPI(JToken jsonConfig) { if (EnvironmentUtil.IsRunningLegacyOwin) { //Still running legacy Owin and using the DPAPI, we don't want to migrate logger.Debug(ID + " - Running Owin, no need to migrate from DPAPI"); return(false); } Version dotNetVersion = Microsoft.Extensions.PlatformAbstractions.PlatformServices.Default.Application.RuntimeFramework.Version; bool isWindows = Environment.OSVersion.Platform == PlatformID.Win32NT; if (!isWindows && dotNetVersion.Major < 4) { // User isn't running Windows, but is running on .NET Core framework, no access to the DPAPI, so don't bother trying to migrate return(false); } LoadValuesFromJson(jsonConfig, false); object passwordPropertyValue = null; string passwordValue = ""; try { passwordPropertyValue = configData.GetType().GetProperty("Password").GetValue(configData, null); passwordValue = passwordPropertyValue.GetType().GetProperty("Value").GetValue(passwordPropertyValue, null).ToString(); } catch (Exception) { logger.Debug($"Unable to source password for [{ID}] while attempting migration, likely a public tracker"); return(false); } if (!string.IsNullOrEmpty(passwordValue)) { try { protectionService.UnProtect(passwordValue); //Password successfully unprotected using Microsoft.AspNetCore.DataProtection, no further action needed as we've already converted the password previously return(false); } catch (Exception ex) { if (ex.Message != "The provided payload cannot be decrypted because it was not protected with this protection provider.") { logger.Info($"Password could not be unprotected using Microsoft.AspNetCore.DataProtection - {ID} : " + ex); } logger.Info($"Attempting legacy Unprotect - {ID} : "); try { string unprotectedPassword = protectionService.LegacyUnProtect(passwordValue); //Password successfully unprotected using Windows/Mono DPAPI passwordPropertyValue.GetType().GetProperty("Value").SetValue(passwordPropertyValue, unprotectedPassword); SaveConfig(); IsConfigured = true; logger.Info($"Password successfully migrated for {ID}"); return(true); } catch (Exception exception) { logger.Info($"Password could not be unprotected using legacy DPAPI - {ID} : " + exception); } } } return(false); }
public void LoadValuesFromJson(JToken json, IProtectionService ps = null) { if (json == null) { return; } var arr = (JArray)json; // transistion from alternatelink to sitelink var alternatelinkItem = arr.FirstOrDefault(f => f.Value <string>("id") == "alternatelink"); if (alternatelinkItem != null && !string.IsNullOrEmpty(alternatelinkItem.Value <string>("value"))) { //SiteLink.Value = alternatelinkItem.Value<string>("value"); } foreach (var item in GetItems(forDisplay: false)) { var arrItem = arr.FirstOrDefault(f => f.Value <string>("id") == item.ID); if (arrItem == null) { continue; } switch (item.ItemType) { case ItemType.InputString: var sItem = (StringItem)item; var newValue = arrItem.Value <string>("value"); if (string.Equals(item.Name, "password", StringComparison.InvariantCultureIgnoreCase)) { if (newValue != PASSWORD_REPLACEMENT) { sItem.Value = newValue; if (ps != null) { sItem.Value = ps.UnProtect(newValue); } } } else { sItem.Value = newValue; } break; case ItemType.HiddenData: ((HiddenItem)item).Value = arrItem.Value <string>("value"); break; case ItemType.InputBool: ((BoolItem)item).Value = arrItem.Value <bool>("value"); break; case ItemType.InputCheckbox: var values = arrItem.Value <JArray>("values"); if (values != null) { ((CheckboxItem)item).Values = values.Values <string>().ToArray(); } break; case ItemType.InputSelect: ((SelectItem)item).Value = arrItem.Value <string>("value"); break; case ItemType.Recaptcha: ((RecaptchaItem)item).Value = arrItem.Value <string>("value"); ((RecaptchaItem)item).Cookie = arrItem.Value <string>("cookie"); ((RecaptchaItem)item).Version = arrItem.Value <string>("version"); ((RecaptchaItem)item).Challenge = arrItem.Value <string>("challenge"); break; } } }
//TODO: Remove this section once users have moved off DPAPI private bool MigratedFromDPAPI(JToken jsonConfig) { var currentAssembly = Assembly.GetExecutingAssembly(); bool runningLegacyOwin = new StackTrace().GetFrames() .Select(x => x.GetMethod().ReflectedType.Assembly).Distinct() .Where(x => x.GetReferencedAssemblies().Any(y => y.FullName == currentAssembly.FullName)) .Where(x => x.ManifestModule.Name == "Jackett.dll" || x.ManifestModule.Name == "JackettConsole.exe") .Count() == 2; if (runningLegacyOwin) { //Still running legacy Owin and using the DPAPI, we don't want to migrate logger.Debug(ID + " - Running Owin, no need to migrate from DPAPI"); return(false); } Version dotNetVersion = Microsoft.Extensions.PlatformAbstractions.PlatformServices.Default.Application.RuntimeFramework.Version; bool isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); if (!isWindows && dotNetVersion.Major < 4) { // User isn't running Windows, but is running on .NET Core framewrok, no access to the DPAPI, so don't bother trying to migrate return(false); } LoadValuesFromJson(jsonConfig, false); object passwordPropertyValue = null; string passwordValue = ""; try { passwordPropertyValue = configData.GetType().GetProperty("Password").GetValue(configData, null); passwordValue = passwordPropertyValue.GetType().GetProperty("Value").GetValue(passwordPropertyValue, null).ToString(); } catch (Exception ex) { logger.Warn($"Attempt to source password from json failed - {ID} : " + ex.ToString()); return(false); } if (!string.IsNullOrEmpty(passwordValue)) { try { protectionService.UnProtect(passwordValue); //Password successfully unprotected using Microsoft.AspNetCore.DataProtection, no further action needed as we've already converted the password previously return(false); } catch (Exception ex) { if (ex.Message != "The provided payload cannot be decrypted because it was not protected with this protection provider.") { logger.Info($"Password could not be unprotected using Microsoft.AspNetCore.DataProtection - {ID} : " + ex.ToString()); } logger.Info($"Attempting legacy Unprotect - {ID} : "); try { string unprotectedPassword = protectionService.LegacyUnProtect(passwordValue); //Password successfully unprotected using Windows/Mono DPAPI passwordPropertyValue.GetType().GetProperty("Value").SetValue(passwordPropertyValue, unprotectedPassword); SaveConfig(); IsConfigured = true; logger.Info($"Password successfully migrated for {ID}"); return(true); } catch (Exception exception) { logger.Info($"Password could not be unprotected using legacy DPAPI - {ID} : " + exception.ToString()); } } } return(false); }
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()); } }
public void LoadValuesFromJson(JToken json, IProtectionService ps = null) { if (json == null) { return; } var arr = (JArray)json; foreach (var item in GetItems(false)) { var arrItem = arr.FirstOrDefault(f => f.Value <string>("id") == item.ID); if (arrItem == null) { continue; } switch (item) { case HiddenItem hiddenItem: hiddenItem.Value = arrItem.Value <string>("value"); break; case BoolItem boolItem: boolItem.Value = arrItem.Value <bool>("value"); break; case CheckboxItem checkboxItem: var values = arrItem.Value <JArray>("values"); if (values != null) { checkboxItem.Values = values.Values <string>().ToArray(); } break; case SelectItem selectItem: selectItem.Value = arrItem.Value <string>("value"); break; case RecaptchaItem recaptcha: recaptcha.Value = arrItem.Value <string>("value"); recaptcha.Cookie = arrItem.Value <string>("cookie"); recaptcha.Version = arrItem.Value <string>("version"); recaptcha.Challenge = arrItem.Value <string>("challenge"); break; case StringItem sItem: var newValue = arrItem.Value <string>("value"); if (string.Equals(item.Name, "password", StringComparison.InvariantCultureIgnoreCase)) { if (newValue != _PasswordReplacement) { sItem.Value = newValue; if (ps != null) { sItem.Value = ps.UnProtect(newValue); } } } else { sItem.Value = newValue; } break; } } }
/// <summary> /// Loads all JSON values into the matching properties. /// </summary> public void LoadConfigDataValuesFromJson(JToken json, IProtectionService ps = null) { if (json == null) { return; } var jsonArray = (JArray)json; foreach (var item in GetAllConfigurationItems().Where(x => x.CanBeSavedToFile)) { var jsonToken = jsonArray.FirstOrDefault(f => f.Value <string>("id") == item.ID); if (jsonToken == null) { continue; } switch (item) { case StringConfigurationItem stringItem: { if (HasPasswordValue(item)) { var pw = ReadValueAs <string>(jsonToken); if (pw != PASSWORD_REPLACEMENT) { stringItem.Value = ps != null?ps.UnProtect(pw) : pw; } } else { stringItem.Value = ReadValueAs <string>(jsonToken); } break; } case HiddenStringConfigurationItem hiddenStringItem: { hiddenStringItem.Value = ReadValueAs <string>(jsonToken); break; } case BoolConfigurationItem boolItem: { boolItem.Value = ReadValueAs <bool>(jsonToken); break; } case SingleSelectConfigurationItem singleSelectItem: { singleSelectItem.Value = ReadValueAs <string>(jsonToken); break; } case MultiSelectConfigurationItem multiSelectItem: { var values = jsonToken.Value <JArray>("values"); if (values != null) { multiSelectItem.Values = values.Values <string>().ToArray(); } break; } case PasswordConfigurationItem passwordItem: { var pw = ReadValueAs <string>(jsonToken); if (pw != PASSWORD_REPLACEMENT) { passwordItem.Value = ps != null?ps.UnProtect(pw) : pw; } break; } } } }