diff --git a/src/Jackett.Test/Jackett.Test.csproj b/src/Jackett.Test/Jackett.Test.csproj
index 234f876d1..1f07527e6 100644
--- a/src/Jackett.Test/Jackett.Test.csproj
+++ b/src/Jackett.Test/Jackett.Test.csproj
@@ -54,6 +54,10 @@
..\packages\Autofac.WebApi2.Owin.3.2.0\lib\net45\Autofac.Integration.WebApi.Owin.dll
True
+
+ ..\packages\AutoMapper.4.0.4\lib\net45\AutoMapper.dll
+ True
+
..\packages\CsQuery.1.3.4\lib\net40\CsQuery.dll
True
@@ -70,6 +74,7 @@
..\packages\Microsoft.AspNet.Identity.Core.2.2.1\lib\net45\Microsoft.AspNet.Identity.Core.dll
True
+
..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll
True
@@ -155,6 +160,7 @@
+
@@ -162,7 +168,9 @@
-
+
+ Designer
+
diff --git a/src/Jackett.Test/Services/ProtectionServiceTests.cs b/src/Jackett.Test/Services/ProtectionServiceTests.cs
new file mode 100644
index 000000000..e8fb274d5
--- /dev/null
+++ b/src/Jackett.Test/Services/ProtectionServiceTests.cs
@@ -0,0 +1,30 @@
+using Jackett.Services;
+using NUnit.Framework;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Autofac;
+
+namespace JackettTest.Services
+{
+ [TestFixture]
+ class ProtectionServiceTests : TestBase
+ {
+
+ [Test]
+ public void Should_be_able_to_encrypt_and_decrypt()
+ {
+ var ss = TestUtil.Container.Resolve();
+ ss.Config.InstanceId = "12345678";
+ var ps = TestUtil.Container.Resolve();
+ var input = "test123";
+ var protectedInput = ps.Protect(input);
+ var output = ps.UnProtect(protectedInput);
+
+ Assert.AreEqual(output, input);
+ Assert.AreNotEqual(input, protectedInput);
+ }
+ }
+}
diff --git a/src/Jackett.Test/app.config b/src/Jackett.Test/app.config
index eda8c8545..c88a03853 100644
--- a/src/Jackett.Test/app.config
+++ b/src/Jackett.Test/app.config
@@ -22,6 +22,10 @@
+
+
+
+
diff --git a/src/Jackett.Test/packages.config b/src/Jackett.Test/packages.config
index 3813a8d52..b1b814859 100644
--- a/src/Jackett.Test/packages.config
+++ b/src/Jackett.Test/packages.config
@@ -4,6 +4,7 @@
+
diff --git a/src/Jackett/Controllers/AdminController.cs b/src/Jackett/Controllers/AdminController.cs
index b6b9514b4..04f215dbd 100644
--- a/src/Jackett/Controllers/AdminController.cs
+++ b/src/Jackett/Controllers/AdminController.cs
@@ -153,7 +153,7 @@ namespace Jackett.Controllers
var postData = await ReadPostDataJson();
var indexer = indexerService.GetIndexer((string)postData["indexer"]);
var config = await indexer.GetConfigurationForSetup();
- jsonReply["config"] = config.ToJson();
+ jsonReply["config"] = config.ToJson(null);
jsonReply["caps"] = indexer.TorznabCaps.CapsToJson();
jsonReply["name"] = indexer.DisplayName;
jsonReply["result"] = "success";
@@ -192,7 +192,7 @@ namespace Jackett.Controllers
baseIndexer.ResetBaseConfig();
if (ex is ExceptionWithConfigData)
{
- jsonReply["config"] = ((ExceptionWithConfigData)ex).ConfigData.ToJson();
+ jsonReply["config"] = ((ExceptionWithConfigData)ex).ConfigData.ToJson(null);
} else
{
logger.Error(ex, "Exception in Configure");
diff --git a/src/Jackett/Indexers/AlphaRatio.cs b/src/Jackett/Indexers/AlphaRatio.cs
index 4be8a70d7..19e5f5065 100644
--- a/src/Jackett/Indexers/AlphaRatio.cs
+++ b/src/Jackett/Indexers/AlphaRatio.cs
@@ -25,7 +25,7 @@ namespace Jackett.Indexers
private string DownloadUrl { get { return SiteLink + "torrents.php?action=download&id="; } }
private string GuidUrl { get { return SiteLink + "torrents.php?torrentid="; } }
- public AlphaRatio(IIndexerManagerService i, IWebClient w, Logger l)
+ public AlphaRatio(IIndexerManagerService i, IWebClient w, Logger l, IProtectionService ps)
: base(name: "AlphaRatio",
description: "Legendary",
link: "https://alpharatio.cc/",
@@ -33,6 +33,7 @@ namespace Jackett.Indexers
manager: i,
client: w,
logger: l,
+ p: ps,
configData: new ConfigurationDataBasicLogin())
{
webclient = w;
diff --git a/src/Jackett/Indexers/AnimeBytes.cs b/src/Jackett/Indexers/AnimeBytes.cs
index e9822e95d..b9908c9a7 100644
--- a/src/Jackett/Indexers/AnimeBytes.cs
+++ b/src/Jackett/Indexers/AnimeBytes.cs
@@ -33,7 +33,7 @@ namespace Jackett.Indexers
set { base.configData = value; }
}
- public AnimeBytes(IIndexerManagerService i, IWebClient client, Logger l)
+ public AnimeBytes(IIndexerManagerService i, IWebClient client, Logger l, IProtectionService ps)
: base(name: "AnimeBytes",
link: "https://animebytes.tv/",
description: "Powered by Tentacles",
@@ -41,6 +41,7 @@ namespace Jackett.Indexers
client: client,
caps: new TorznabCapabilities(TorznabCatType.Anime),
logger: l,
+ p: ps,
configData: new ConfigurationDataAnimeBytes())
{
}
diff --git a/src/Jackett/Indexers/BB.cs b/src/Jackett/Indexers/BB.cs
index 8dc1293e8..65edb1901 100644
--- a/src/Jackett/Indexers/BB.cs
+++ b/src/Jackett/Indexers/BB.cs
@@ -32,7 +32,7 @@ namespace Jackett.Indexers
set { base.configData = value; }
}
- public BB(IIndexerManagerService i, Logger l, IWebClient w)
+ public BB(IIndexerManagerService i, Logger l, IWebClient w, IProtectionService ps)
: base(name: "bB",
description: "bB",
link: "http://www.reddit.com/r/baconbits/",
@@ -40,6 +40,7 @@ namespace Jackett.Indexers
manager: i,
client: w,
logger: l,
+ p: ps,
configData: new ConfigurationDataBasicLogin())
{
}
diff --git a/src/Jackett/Indexers/BakaBT.cs b/src/Jackett/Indexers/BakaBT.cs
index 0416014a5..484650666 100644
--- a/src/Jackett/Indexers/BakaBT.cs
+++ b/src/Jackett/Indexers/BakaBT.cs
@@ -28,7 +28,7 @@ namespace Jackett.Indexers
set { base.configData = value; }
}
- public BakaBT(IIndexerManagerService i, IWebClient wc, Logger l)
+ public BakaBT(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
: base(name: "BakaBT",
description: "Anime Community",
link: "http://bakabt.me/",
@@ -36,6 +36,7 @@ namespace Jackett.Indexers
manager: i,
client: wc,
logger: l,
+ p: ps,
configData: new ConfigurationDataBasicLogin())
{
}
diff --git a/src/Jackett/Indexers/BaseIndexer.cs b/src/Jackett/Indexers/BaseIndexer.cs
index 7c951004e..c2b217c65 100644
--- a/src/Jackett/Indexers/BaseIndexer.cs
+++ b/src/Jackett/Indexers/BaseIndexer.cs
@@ -29,6 +29,8 @@ namespace Jackett.Indexers
protected static List cache = new List();
protected static readonly TimeSpan cacheTime = new TimeSpan(0, 9, 0);
protected IWebClient webclient;
+ protected IProtectionService protectionService;
+
protected string CookieHeader
{
get { return configData.CookieHeader.Value; }
@@ -39,7 +41,7 @@ namespace Jackett.Indexers
private List categoryMapping = new List();
- public BaseIndexer(string name, string link, string description, IIndexerManagerService manager, IWebClient client, Logger logger, ConfigurationData configData, TorznabCapabilities caps = null)
+ public BaseIndexer(string name, string link, string description, IIndexerManagerService manager, IWebClient client, Logger logger, ConfigurationData configData, IProtectionService p, TorznabCapabilities caps = null)
{
if (!link.EndsWith("/"))
throw new Exception("Site link must end with a slash.");
@@ -50,6 +52,7 @@ namespace Jackett.Indexers
this.logger = logger;
indexerService = manager;
webclient = client;
+ protectionService = p;
this.configData = configData;
@@ -91,7 +94,7 @@ namespace Jackett.Indexers
protected virtual void SaveConfig()
{
- indexerService.SaveConfig(this as IIndexer, configData.ToJson(forDisplay: false));
+ indexerService.SaveConfig(this as IIndexer, configData.ToJson(protectionService,forDisplay: false));
}
protected void OnParseError(string results, Exception ex)
@@ -182,7 +185,7 @@ namespace Jackett.Indexers
{
if (jsonConfig is JArray)
{
- configData.LoadValuesFromJson(jsonConfig);
+ configData.LoadValuesFromJson(jsonConfig, protectionService);
IsConfigured = true;
}
// read and upgrade old settings file format
diff --git a/src/Jackett/Indexers/BeyondHD.cs b/src/Jackett/Indexers/BeyondHD.cs
index 9c885fd97..4e7c0830f 100644
--- a/src/Jackett/Indexers/BeyondHD.cs
+++ b/src/Jackett/Indexers/BeyondHD.cs
@@ -28,7 +28,7 @@ namespace Jackett.Indexers
set { base.configData = value; }
}
- public BeyondHD(IIndexerManagerService i, Logger l, IWebClient w)
+ public BeyondHD(IIndexerManagerService i, Logger l, IWebClient w, IProtectionService ps)
: base(name: "BeyondHD",
description: "Without BeyondHD, your HDTV is just a TV",
link: "https://beyondhd.me/",
@@ -36,6 +36,7 @@ namespace Jackett.Indexers
manager: i,
client: w,
logger: l,
+ p: ps,
configData: new ConfigurationDataCookie())
{
}
diff --git a/src/Jackett/Indexers/BitHdtv.cs b/src/Jackett/Indexers/BitHdtv.cs
index 5f6b32a85..f3910a312 100644
--- a/src/Jackett/Indexers/BitHdtv.cs
+++ b/src/Jackett/Indexers/BitHdtv.cs
@@ -30,7 +30,7 @@ namespace Jackett.Indexers
set { base.configData = value; }
}
- public BitHdtv(IIndexerManagerService i, Logger l, IWebClient w)
+ public BitHdtv(IIndexerManagerService i, Logger l, IWebClient w, IProtectionService ps)
: base(name: "BIT-HDTV",
description: "Home of high definition invites",
link: "https://www.bit-hdtv.com/",
@@ -38,6 +38,7 @@ namespace Jackett.Indexers
manager: i,
client: w,
logger: l,
+ p: ps,
configData: new ConfigurationDataBasicLogin())
{
}
diff --git a/src/Jackett/Indexers/BitMeTV.cs b/src/Jackett/Indexers/BitMeTV.cs
index 47180b9fb..fd555cd72 100644
--- a/src/Jackett/Indexers/BitMeTV.cs
+++ b/src/Jackett/Indexers/BitMeTV.cs
@@ -32,7 +32,7 @@ namespace Jackett.Indexers
set { base.configData = value; }
}
- public BitMeTV(IIndexerManagerService i, Logger l, IWebClient c)
+ public BitMeTV(IIndexerManagerService i, Logger l, IWebClient c, IProtectionService ps)
: base(name: "BitMeTV",
description: "TV Episode specialty tracker",
link: "http://www.bitmetv.org/",
@@ -40,6 +40,7 @@ namespace Jackett.Indexers
manager: i,
client: c,
logger: l,
+ p: ps,
configData: new ConfigurationDataCaptchaLogin())
{
}
diff --git a/src/Jackett/Indexers/Demonoid.cs b/src/Jackett/Indexers/Demonoid.cs
index bd0da646b..44e5d68fe 100644
--- a/src/Jackett/Indexers/Demonoid.cs
+++ b/src/Jackett/Indexers/Demonoid.cs
@@ -27,7 +27,7 @@ namespace Jackett.Indexers
set { base.configData = value; }
}
- public Demonoid(IIndexerManagerService i, Logger l, IWebClient wc)
+ public Demonoid(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps)
: base(name: "Demonoid",
description: "Demonoid",
link: "http://www.demonoid.pw/",
@@ -35,6 +35,7 @@ namespace Jackett.Indexers
manager: i,
client: wc,
logger: l,
+ p: ps,
configData: new ConfigurationDataBasicLogin())
{
}
diff --git a/src/Jackett/Indexers/FrenchTorrentDb.cs b/src/Jackett/Indexers/FrenchTorrentDb.cs
index 85c631fb9..b3e3d67b8 100644
--- a/src/Jackett/Indexers/FrenchTorrentDb.cs
+++ b/src/Jackett/Indexers/FrenchTorrentDb.cs
@@ -24,7 +24,7 @@ namespace Jackett.Indexers
set { base.configData = value; }
}
- public FrenchTorrentDb(IIndexerManagerService i, Logger l, IWebClient c)
+ public FrenchTorrentDb(IIndexerManagerService i, Logger l, IWebClient c, IProtectionService ps)
: base(name: "FrenchTorrentDb",
description: "One the biggest French Torrent Tracker",
link: "http://www.frenchtorrentdb.com/",
@@ -32,6 +32,7 @@ namespace Jackett.Indexers
manager: i,
client: c,
logger: l,
+ p: ps,
configData: new ConfigurationDataCookie())
{
}
diff --git a/src/Jackett/Indexers/Freshon.cs b/src/Jackett/Indexers/Freshon.cs
index fcf01f75d..a6b025b44 100644
--- a/src/Jackett/Indexers/Freshon.cs
+++ b/src/Jackett/Indexers/Freshon.cs
@@ -33,7 +33,7 @@ namespace Jackett.Indexers
set { base.configData = value; }
}
- public Freshon(IIndexerManagerService i, Logger l, IWebClient c)
+ public Freshon(IIndexerManagerService i, Logger l, IWebClient c, IProtectionService ps)
: base(name: "FreshOnTV",
description: "Our goal is to provide the latest stuff in the TV show domain",
link: "https://freshon.tv/",
@@ -41,6 +41,7 @@ namespace Jackett.Indexers
manager: i,
client: c,
logger: l,
+ p: ps,
configData: new ConfigurationDataBasicLogin())
{
}
diff --git a/src/Jackett/Indexers/HDSpace.cs b/src/Jackett/Indexers/HDSpace.cs
index 3c5e6aaad..3cc7012dd 100644
--- a/src/Jackett/Indexers/HDSpace.cs
+++ b/src/Jackett/Indexers/HDSpace.cs
@@ -28,7 +28,7 @@ namespace Jackett.Indexers
set { base.configData = value; }
}
- public HDSpace(IIndexerManagerService i, IWebClient wc, Logger l)
+ public HDSpace(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
: base(name: "HD-Space",
description: "Sharing The Universe",
link: "https://hd-space.org/",
@@ -36,6 +36,7 @@ namespace Jackett.Indexers
manager: i,
client: wc,
logger: l,
+ p: ps,
configData: new ConfigurationDataBasicLogin())
{
}
diff --git a/src/Jackett/Indexers/HDTorrents.cs b/src/Jackett/Indexers/HDTorrents.cs
index 1a4a9073b..c11771d9a 100644
--- a/src/Jackett/Indexers/HDTorrents.cs
+++ b/src/Jackett/Indexers/HDTorrents.cs
@@ -30,7 +30,7 @@ namespace Jackett.Indexers
set { base.configData = value; }
}
- public HDTorrents(IIndexerManagerService i, Logger l, IWebClient w)
+ public HDTorrents(IIndexerManagerService i, Logger l, IWebClient w, IProtectionService ps)
: base(name: "HD-Torrents",
description: "HD-Torrents is a private torrent website with HD torrents and strict rules on their content.",
link: "http://hdts.ru/",// Of the accessible domains the .ru seems the most reliable. https://hdts.ru | https://hd-torrents.org | https://hd-torrents.net | https://hd-torrents.me
@@ -38,6 +38,7 @@ namespace Jackett.Indexers
manager: i,
client: w,
logger: l,
+ p: ps,
configData: new ConfigurationDataBasicLogin())
{
}
diff --git a/src/Jackett/Indexers/IPTorrents.cs b/src/Jackett/Indexers/IPTorrents.cs
index 289cd2dee..ed844114f 100644
--- a/src/Jackett/Indexers/IPTorrents.cs
+++ b/src/Jackett/Indexers/IPTorrents.cs
@@ -29,7 +29,7 @@ namespace Jackett.Indexers
set { base.configData = value; }
}
- public IPTorrents(IIndexerManagerService i, IWebClient wc, Logger l)
+ public IPTorrents(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
: base(name: "IPTorrents",
description: "Always a step ahead.",
link: "https://iptorrents.com/",
@@ -37,6 +37,7 @@ namespace Jackett.Indexers
manager: i,
client: wc,
logger: l,
+ p: ps,
configData: new ConfigurationDataBasicLogin())
{
AddCategoryMapping(72, TorznabCatType.Movies);
diff --git a/src/Jackett/Indexers/ImmortalSeed.cs b/src/Jackett/Indexers/ImmortalSeed.cs
index 078e44264..f00a3849f 100644
--- a/src/Jackett/Indexers/ImmortalSeed.cs
+++ b/src/Jackett/Indexers/ImmortalSeed.cs
@@ -30,7 +30,7 @@ namespace Jackett.Indexers
set { base.configData = value; }
}
- public ImmortalSeed(IIndexerManagerService i, IWebClient wc, Logger l)
+ public ImmortalSeed(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
: base(name: "ImmortalSeed",
description: "ImmortalSeed",
link: "http://immortalseed.me/",
@@ -38,6 +38,7 @@ namespace Jackett.Indexers
manager: i,
client: wc,
logger: l,
+ p: ps,
configData: new ConfigurationDataBasicLogin())
{
AddCategoryMapping(32, TorznabCatType.Anime);
diff --git a/src/Jackett/Indexers/MoreThanTV.cs b/src/Jackett/Indexers/MoreThanTV.cs
index c1a59a1b9..ebfe674b5 100644
--- a/src/Jackett/Indexers/MoreThanTV.cs
+++ b/src/Jackett/Indexers/MoreThanTV.cs
@@ -31,7 +31,7 @@ namespace Jackett.Indexers
set { base.configData = value; }
}
- public MoreThanTV(IIndexerManagerService i, IWebClient c, Logger l)
+ public MoreThanTV(IIndexerManagerService i, IWebClient c, Logger l, IProtectionService ps)
: base(name: "MoreThanTV",
description: "ROMANIAN Private Torrent Tracker for TV / MOVIES, and the internal tracker for the release group DRACULA.",
link: "https://www.morethan.tv/",
@@ -39,6 +39,7 @@ namespace Jackett.Indexers
manager: i,
client: c,
logger: l,
+ p: ps,
configData: new ConfigurationDataBasicLogin())
{
}
diff --git a/src/Jackett/Indexers/Pretome.cs b/src/Jackett/Indexers/Pretome.cs
index 92cbf4282..6b84e3b28 100644
--- a/src/Jackett/Indexers/Pretome.cs
+++ b/src/Jackett/Indexers/Pretome.cs
@@ -27,7 +27,7 @@ namespace Jackett.Indexers
set { base.configData = value; }
}
- public Pretome(IIndexerManagerService i, IWebClient wc, Logger l)
+ public Pretome(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
: base(name: "PreToMe",
description: "BitTorrent site for High Quality, High Definition (HD) movies and TV Shows",
link: "https://pretome.info/",
@@ -35,6 +35,7 @@ namespace Jackett.Indexers
client: wc,
manager: i,
logger: l,
+ p: ps,
configData: new ConfigurationDataPinNumber())
{
}
diff --git a/src/Jackett/Indexers/PrivateHD.cs b/src/Jackett/Indexers/PrivateHD.cs
index 7707f2e57..0b60f3333 100644
--- a/src/Jackett/Indexers/PrivateHD.cs
+++ b/src/Jackett/Indexers/PrivateHD.cs
@@ -29,7 +29,7 @@ namespace Jackett.Indexers
set { base.configData = value; }
}
- public PrivateHD(IIndexerManagerService i, IWebClient wc, Logger l)
+ public PrivateHD(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
: base(name: "PrivateHD",
description: "BitTorrent site for High Quality, High Definition (HD) movies and TV Shows",
link: "https://privatehd.to/",
@@ -37,6 +37,7 @@ namespace Jackett.Indexers
manager: i,
client: wc,
logger: l,
+ p: ps,
configData: new ConfigurationDataBasicLogin())
{
AddCategoryMapping(1, TorznabCatType.Movies);
diff --git a/src/Jackett/Indexers/RUTor.cs b/src/Jackett/Indexers/RUTor.cs
index 063676461..aaf194c73 100644
--- a/src/Jackett/Indexers/RUTor.cs
+++ b/src/Jackett/Indexers/RUTor.cs
@@ -32,7 +32,7 @@ namespace Jackett.Indexers
set { base.configData = value; }
}
- public RuTor(IIndexerManagerService i, Logger l, IWebClient wc)
+ public RuTor(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps)
: base(name: "RUTor",
description: "Свободный торрент трекер",
link: "http://rutor.org/",
@@ -40,6 +40,7 @@ namespace Jackett.Indexers
manager: i,
client: wc,
logger: l,
+ p: ps,
configData: new ConfigurationDataRuTor(defaultSiteLink))
{
TorznabCaps.Categories.Add(TorznabCatType.Anime);
diff --git a/src/Jackett/Indexers/SceneAccess.cs b/src/Jackett/Indexers/SceneAccess.cs
index b73901192..624dbc10a 100644
--- a/src/Jackett/Indexers/SceneAccess.cs
+++ b/src/Jackett/Indexers/SceneAccess.cs
@@ -27,7 +27,7 @@ namespace Jackett.Indexers
set { base.configData = value; }
}
- public SceneAccess(IIndexerManagerService i, IWebClient c, Logger l)
+ public SceneAccess(IIndexerManagerService i, IWebClient c, Logger l, IProtectionService ps)
: base(name: "SceneAccess",
description: "Your gateway to the scene",
link: "https://sceneaccess.eu/",
@@ -35,6 +35,7 @@ namespace Jackett.Indexers
manager: i,
client: c,
logger: l,
+ p: ps,
configData: new ConfigurationDataBasicLogin())
{
}
diff --git a/src/Jackett/Indexers/SceneTime.cs b/src/Jackett/Indexers/SceneTime.cs
index 2de2accf1..bb3a67115 100644
--- a/src/Jackett/Indexers/SceneTime.cs
+++ b/src/Jackett/Indexers/SceneTime.cs
@@ -30,7 +30,7 @@ namespace Jackett.Indexers
set { base.configData = value; }
}
- public SceneTime(IIndexerManagerService i, Logger l, IWebClient w)
+ public SceneTime(IIndexerManagerService i, Logger l, IWebClient w, IProtectionService ps)
: base(name: "SceneTime",
description: "Always on time",
link: "https://www.scenetime.com/",
@@ -38,6 +38,7 @@ namespace Jackett.Indexers
manager: i,
client: w,
logger: l,
+ p: ps,
configData: new ConfigurationDataBasicLogin())
{
}
diff --git a/src/Jackett/Indexers/ShowRSS.cs b/src/Jackett/Indexers/ShowRSS.cs
index 730ee62cb..3e87ed81c 100644
--- a/src/Jackett/Indexers/ShowRSS.cs
+++ b/src/Jackett/Indexers/ShowRSS.cs
@@ -36,7 +36,7 @@ namespace Jackett.Indexers
set { base.configData = value; }
}
- public ShowRSS(IIndexerManagerService i, Logger l, IWebClient wc)
+ public ShowRSS(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps)
: base(name: "ShowRSS",
description: "showRSS is a service that allows you to keep track of your favorite TV shows",
link: defaultSiteLink,
@@ -44,6 +44,7 @@ namespace Jackett.Indexers
manager: i,
client: wc,
logger: l,
+ p: ps,
configData: new ConfigurationDataUrl(defaultSiteLink))
{
}
diff --git a/src/Jackett/Indexers/SpeedCD.cs b/src/Jackett/Indexers/SpeedCD.cs
index ab7e442a0..0e9ee5333 100644
--- a/src/Jackett/Indexers/SpeedCD.cs
+++ b/src/Jackett/Indexers/SpeedCD.cs
@@ -33,7 +33,7 @@ namespace Jackett.Indexers
set { base.configData = value; }
}
- public SpeedCD(IIndexerManagerService i, Logger l, IWebClient wc)
+ public SpeedCD(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps)
: base(name: "Speed.cd",
description: "Your home now!",
link: "http://speed.cd/",
@@ -41,6 +41,7 @@ namespace Jackett.Indexers
manager: i,
client: wc,
logger: l,
+ p: ps,
configData: new ConfigurationDataBasicLogin())
{
}
diff --git a/src/Jackett/Indexers/Strike.cs b/src/Jackett/Indexers/Strike.cs
index 5bc4f55d2..508727aa2 100644
--- a/src/Jackett/Indexers/Strike.cs
+++ b/src/Jackett/Indexers/Strike.cs
@@ -37,7 +37,7 @@ namespace Jackett.Indexers
}
- public Strike(IIndexerManagerService i, Logger l, IWebClient wc)
+ public Strike(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps)
: base(name: "Strike",
description: "Torrent search engine",
link: defaultSiteLink,
@@ -45,6 +45,7 @@ namespace Jackett.Indexers
manager: i,
client: wc,
logger: l,
+ p: ps,
configData: new ConfigurationDataUrl(defaultSiteLink))
{
}
diff --git a/src/Jackett/Indexers/T411.cs b/src/Jackett/Indexers/T411.cs
index d2d49f1bb..bd9caabb7 100644
--- a/src/Jackett/Indexers/T411.cs
+++ b/src/Jackett/Indexers/T411.cs
@@ -35,7 +35,7 @@ namespace Jackett.Indexers
set { base.configData = value; }
}
- public T411(IIndexerManagerService i, Logger l, IWebClient wc)
+ public T411(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps)
: base(name: "T411",
description: "French Torrent Tracker",
link: "http://www.t411.io/",
@@ -43,6 +43,7 @@ namespace Jackett.Indexers
manager: i,
client: wc,
logger: l,
+ p: ps,
configData: new ConfigurationDataLoginTokin())
{
CommentsUrl = SiteLink + "/torrents/{0}";
diff --git a/src/Jackett/Indexers/ThePirateBay.cs b/src/Jackett/Indexers/ThePirateBay.cs
index 8115a62b0..86f6bc3c9 100644
--- a/src/Jackett/Indexers/ThePirateBay.cs
+++ b/src/Jackett/Indexers/ThePirateBay.cs
@@ -37,7 +37,7 @@ namespace Jackett.Indexers
set { base.configData = value; }
}
- public ThePirateBay(IIndexerManagerService i, Logger l, IWebClient wc)
+ public ThePirateBay(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps)
: base(name: "The Pirate Bay",
description: "The worlds largest bittorrent indexer",
link: defaultSiteLink,
@@ -45,6 +45,7 @@ namespace Jackett.Indexers
manager: i,
client: wc,
logger: l,
+ p: ps,
configData: new ConfigurationDataUrl(defaultSiteLink))
{
}
diff --git a/src/Jackett/Indexers/TorrentBytes.cs b/src/Jackett/Indexers/TorrentBytes.cs
index d58d567ba..fbaad6a8b 100644
--- a/src/Jackett/Indexers/TorrentBytes.cs
+++ b/src/Jackett/Indexers/TorrentBytes.cs
@@ -30,7 +30,7 @@ namespace Jackett.Indexers
set { base.configData = value; }
}
- public TorrentBytes(IIndexerManagerService i, IWebClient wc, Logger l)
+ public TorrentBytes(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
: base(name: "TorrentBytes",
description: "A decade of torrentbytes",
link: "https://www.torrentbytes.net/",
@@ -38,6 +38,7 @@ namespace Jackett.Indexers
manager: i,
client: wc,
logger: l,
+ p: ps,
configData: new ConfigurationDataBasicLogin())
{
diff --git a/src/Jackett/Indexers/TorrentDay.cs b/src/Jackett/Indexers/TorrentDay.cs
index 6e40c808a..ce74a39f9 100644
--- a/src/Jackett/Indexers/TorrentDay.cs
+++ b/src/Jackett/Indexers/TorrentDay.cs
@@ -31,7 +31,7 @@ namespace Jackett.Indexers
set { base.configData = value; }
}
- public TorrentDay(IIndexerManagerService i, Logger l, IWebClient wc)
+ public TorrentDay(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps)
: base(name: "TorrentDay",
description: "TorrentDay",
link: "https://torrentday.eu/",
@@ -39,6 +39,7 @@ namespace Jackett.Indexers
manager: i,
client: wc,
logger: l,
+ p: ps,
configData: new ConfigurationDataBasicLogin())
{
diff --git a/src/Jackett/Indexers/TorrentLeech.cs b/src/Jackett/Indexers/TorrentLeech.cs
index 4284d68e4..6e99e639e 100644
--- a/src/Jackett/Indexers/TorrentLeech.cs
+++ b/src/Jackett/Indexers/TorrentLeech.cs
@@ -29,7 +29,7 @@ namespace Jackett.Indexers
set { base.configData = value; }
}
- public TorrentLeech(IIndexerManagerService i, Logger l, IWebClient wc)
+ public TorrentLeech(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps)
: base(name: "TorrentLeech",
description: "This is what happens when you seed",
link: "http://www.torrentleech.org/",
@@ -37,6 +37,7 @@ namespace Jackett.Indexers
manager: i,
client: wc,
logger: l,
+ p: ps,
configData: new ConfigurationDataBasicLogin())
{
}
diff --git a/src/Jackett/Indexers/TorrentShack.cs b/src/Jackett/Indexers/TorrentShack.cs
index 31327f932..69765cf2a 100644
--- a/src/Jackett/Indexers/TorrentShack.cs
+++ b/src/Jackett/Indexers/TorrentShack.cs
@@ -29,7 +29,7 @@ namespace Jackett.Indexers
set { base.configData = value; }
}
- public TorrentShack(IIndexerManagerService i, Logger l, IWebClient wc)
+ public TorrentShack(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps)
: base(name: "TorrentShack",
description: "TorrentShack",
link: "http://torrentshack.me/",
@@ -37,6 +37,7 @@ namespace Jackett.Indexers
client: wc,
manager: i,
logger: l,
+ p: ps,
configData: new ConfigurationDataBasicLogin())
{
}
diff --git a/src/Jackett/Indexers/Torrentz.cs b/src/Jackett/Indexers/Torrentz.cs
index d54b2d17d..ca540a2dd 100644
--- a/src/Jackett/Indexers/Torrentz.cs
+++ b/src/Jackett/Indexers/Torrentz.cs
@@ -37,7 +37,7 @@ namespace Jackett.Indexers
}
- public Torrentz(IIndexerManagerService i, Logger l, IWebClient wc)
+ public Torrentz(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps)
: base(name: "Torrentz",
description: "Torrentz is a meta-search engine and a Multisearch. This means we just search other search engines.",
link: defaultSiteLink,
@@ -45,6 +45,7 @@ namespace Jackett.Indexers
manager: i,
client: wc,
logger: l,
+ p: ps,
configData: new ConfigurationDataUrl(defaultSiteLink))
{
}
diff --git a/src/Jackett/Indexers/nCore.cs b/src/Jackett/Indexers/nCore.cs
index c26be2b15..05d6d1b34 100644
--- a/src/Jackett/Indexers/nCore.cs
+++ b/src/Jackett/Indexers/nCore.cs
@@ -30,7 +30,7 @@ namespace Jackett.Indexers
set { base.configData = value; }
}
- public NCore(IIndexerManagerService i, IWebClient wc, Logger l)
+ public NCore(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
: base(name: "nCore",
description: "A Hungarian private torrent site.",
link: "https://ncore.cc/",
@@ -38,6 +38,7 @@ namespace Jackett.Indexers
manager: i,
client: wc,
logger: l,
+ p: ps,
configData: new ConfigurationDataNCore())
{
}
diff --git a/src/Jackett/Jackett.csproj b/src/Jackett/Jackett.csproj
index ad391b285..89b91340a 100644
--- a/src/Jackett/Jackett.csproj
+++ b/src/Jackett/Jackett.csproj
@@ -148,6 +148,7 @@
True
+
@@ -207,6 +208,7 @@
+
@@ -228,6 +230,7 @@
+
diff --git a/src/Jackett/JackettProtectedAttribute.cs b/src/Jackett/JackettProtectedAttribute.cs
new file mode 100644
index 000000000..a4e0d521d
--- /dev/null
+++ b/src/Jackett/JackettProtectedAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Jackett
+{
+ public class JackettProtectedAttribute : Attribute
+ {
+ }
+}
diff --git a/src/Jackett/Models/Config/ServerConfig.cs b/src/Jackett/Models/Config/ServerConfig.cs
index 36f8e1d39..d2c1b3fc0 100644
--- a/src/Jackett/Models/Config/ServerConfig.cs
+++ b/src/Jackett/Models/Config/ServerConfig.cs
@@ -19,6 +19,7 @@ namespace Jackett.Models.Config
public bool AllowExternal { get; set; }
public string APIKey { get; set; }
public string AdminPassword { get; set; }
+ public string InstanceId { get; set; }
public string[] GetListenAddresses(bool? external = null)
{
@@ -38,19 +39,5 @@ namespace Jackett.Models.Config
};
}
}
-
- public string GenerateApi()
- {
- var chars = "abcdefghijklmnopqrstuvwxyz0123456789";
- var randBytes = new byte[32];
- var rngCsp = new RNGCryptoServiceProvider();
- rngCsp.GetBytes(randBytes);
- var key = "";
- foreach (var b in randBytes)
- {
- key += chars[b % chars.Length];
- }
- return key;
- }
}
}
diff --git a/src/Jackett/Models/IndexerConfig/ConfigurationData.cs b/src/Jackett/Models/IndexerConfig/ConfigurationData.cs
index d8cdd75c5..360909642 100644
--- a/src/Jackett/Models/IndexerConfig/ConfigurationData.cs
+++ b/src/Jackett/Models/IndexerConfig/ConfigurationData.cs
@@ -1,4 +1,5 @@
-using Jackett.Utils;
+using Jackett.Services;
+using Jackett.Utils;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
@@ -11,6 +12,8 @@ namespace Jackett.Models.IndexerConfig
{
public abstract class ConfigurationData
{
+ const string PASSWORD_REPLACEMENT = "|||%%PREVJACKPASSWD%%|||";
+
public enum ItemType
{
InputString,
@@ -27,12 +30,12 @@ namespace Jackett.Models.IndexerConfig
}
- public ConfigurationData(JToken json)
+ public ConfigurationData(JToken json, IProtectionService ps)
{
- LoadValuesFromJson(json);
+ LoadValuesFromJson(json, ps);
}
- public void LoadValuesFromJson(JToken json)
+ public void LoadValuesFromJson(JToken json, IProtectionService ps= null)
{
var arr = (JArray)json;
foreach (var item in GetItems(forDisplay: false))
@@ -44,7 +47,21 @@ namespace Jackett.Models.IndexerConfig
switch (item.ItemType)
{
case ItemType.InputString:
- ((StringItem)item).Value = arrItem.Value("value");
+ var sItem = (StringItem)item;
+ var newValue = arrItem.Value("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("value");
@@ -56,7 +73,7 @@ namespace Jackett.Models.IndexerConfig
}
}
- public JToken ToJson(bool forDisplay = true)
+ public JToken ToJson(IProtectionService ps, bool forDisplay = true)
{
var items = GetItems(forDisplay);
var jArray = new JArray();
@@ -71,7 +88,18 @@ namespace Jackett.Models.IndexerConfig
case ItemType.InputString:
case ItemType.HiddenData:
case ItemType.DisplayInfo:
- jObject["value"] = ((StringItem)item).Value;
+ var value = ((StringItem)item).Value;
+ if (string.Equals(item.Name, "password", StringComparison.InvariantCultureIgnoreCase))
+ {
+ if (string.IsNullOrEmpty(value))
+ value = string.Empty;
+ else if (forDisplay)
+ value = PASSWORD_REPLACEMENT;
+ else if (ps != null)
+ value = ps.Protect(value);
+ }
+
+ jObject["value"] = value;
break;
case ItemType.InputBool:
jObject["value"] = ((BoolItem)item).Value;
diff --git a/src/Jackett/Services/ProtectionService.cs b/src/Jackett/Services/ProtectionService.cs
new file mode 100644
index 000000000..710b4f154
--- /dev/null
+++ b/src/Jackett/Services/ProtectionService.cs
@@ -0,0 +1,150 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Security.Cryptography;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Jackett.Services
+{
+ public interface IProtectionService
+ {
+ string Protect(string plainText);
+ string UnProtect(string plainText);
+ }
+
+ public class ProtectionService : IProtectionService
+ {
+ DataProtectionScope PROTECTION_SCOPE = DataProtectionScope.LocalMachine;
+ const string APPLICATION_KEY = "Dvz66r3n8vhTGip2/quiw5ISyM37f7L2iOdupzdKmzkvXGhAgQiWK+6F+4qpxjPVNks1qO7LdWuVqRlzgLzeW8mChC6JnBMUS1Fin4N2nS9lh4XPuCZ1che75xO92Nk2vyXUo9KSFG1hvEszAuLfG2Mcg1r0sVyVXd2gQDU/TbY=";
+
+ IServerService serverService;
+
+ public ProtectionService(IServerService s)
+ {
+ serverService = s;
+
+ if (System.Environment.OSVersion.Platform == PlatformID.Unix)
+ {
+ // We should not be running as root and will only have access to the local store.
+ PROTECTION_SCOPE = DataProtectionScope.CurrentUser;
+ }
+ }
+
+ public string Protect(string plainText)
+ {
+ if (string.IsNullOrEmpty(plainText))
+ return string.Empty;
+
+ var plainBytes = Encoding.UTF8.GetBytes(plainText);
+ var appKey = Convert.FromBase64String(APPLICATION_KEY);
+ var instanceKey = Encoding.UTF8.GetBytes(serverService.Config.InstanceId);
+ var entropy = new byte[appKey.Length + instanceKey.Length];
+ Buffer.BlockCopy(instanceKey, 0, entropy, 0, instanceKey.Length);
+ Buffer.BlockCopy(appKey, 0, entropy, instanceKey.Length, appKey.Length);
+
+ var protectedBytes = ProtectedData.Protect(plainBytes, entropy, PROTECTION_SCOPE);
+
+ using (MemoryStream ms = new MemoryStream())
+ {
+ using (RijndaelManaged AES = new RijndaelManaged())
+ {
+ AES.KeySize = 256;
+ AES.BlockSize = 128;
+
+ var key = new Rfc2898DeriveBytes(instanceKey, instanceKey.Reverse().ToArray(), 64);
+ AES.Key = key.GetBytes(AES.KeySize / 8);
+ AES.IV = key.GetBytes(AES.BlockSize / 8);
+
+ AES.Mode = CipherMode.CBC;
+
+ using (var cs = new CryptoStream(ms, AES.CreateEncryptor(), CryptoStreamMode.Write))
+ {
+ cs.Write(protectedBytes, 0, protectedBytes.Length);
+ cs.Close();
+ }
+ protectedBytes = ms.ToArray();
+ }
+ }
+
+ return Convert.ToBase64String(protectedBytes);
+ }
+
+ public string UnProtect(string plainText)
+ {
+ if (string.IsNullOrEmpty(plainText))
+ return string.Empty;
+
+ var protectedBytes = Convert.FromBase64String(plainText);
+ var instanceKey = Encoding.UTF8.GetBytes(serverService.Config.InstanceId);
+
+ using (MemoryStream ms = new MemoryStream())
+ {
+ using (RijndaelManaged AES = new RijndaelManaged())
+ {
+ AES.KeySize = 256;
+ AES.BlockSize = 128;
+
+ var key = new Rfc2898DeriveBytes(instanceKey, instanceKey.Reverse().ToArray(), 64);
+ AES.Key = key.GetBytes(AES.KeySize / 8);
+ AES.IV = key.GetBytes(AES.BlockSize / 8);
+
+ AES.Mode = CipherMode.CBC;
+
+ using (var cs = new CryptoStream(ms, AES.CreateDecryptor(), CryptoStreamMode.Write))
+ {
+ cs.Write(protectedBytes, 0, protectedBytes.Length);
+ cs.Close();
+ }
+ protectedBytes = ms.ToArray();
+ }
+ }
+
+ var appKey = Convert.FromBase64String(APPLICATION_KEY);
+ var entropy = new byte[appKey.Length + instanceKey.Length];
+ Buffer.BlockCopy(instanceKey, 0, entropy, 0, instanceKey.Length);
+ Buffer.BlockCopy(appKey, 0, entropy, instanceKey.Length, appKey.Length);
+
+ var unprotectedBytes = ProtectedData.Unprotect(protectedBytes, entropy, PROTECTION_SCOPE);
+ return Encoding.UTF8.GetString(unprotectedBytes);
+ }
+
+ public void Protect(T obj)
+ {
+ var type = obj.GetType();
+
+ foreach(var property in type.GetProperties(BindingFlags.SetProperty |BindingFlags.GetProperty | BindingFlags.Public))
+ {
+ if(property.GetCustomAttributes(typeof(JackettProtectedAttribute), false).Count() > 0)
+ {
+ var value = property.GetValue(obj);
+ if(value is string)
+ {
+ var protectedString = Protect(value as string);
+ property.SetValue(obj, protectedString);
+ }
+ }
+ }
+ }
+
+ public void UnProtect(T obj)
+ {
+ var type = obj.GetType();
+
+ foreach (var property in type.GetProperties(BindingFlags.SetProperty | BindingFlags.GetProperty | BindingFlags.Public))
+ {
+ if (property.GetCustomAttributes(typeof(JackettProtectedAttribute), false).Count() > 0)
+ {
+ var value = property.GetValue(obj);
+ if (value is string)
+ {
+ var unprotectedString = UnProtect(value as string);
+ property.SetValue(obj, unprotectedString);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/Jackett/Services/ServerService.cs b/src/Jackett/Services/ServerService.cs
index cdd82b782..1bf2dd6d4 100644
--- a/src/Jackett/Services/ServerService.cs
+++ b/src/Jackett/Services/ServerService.cs
@@ -1,6 +1,7 @@
using Autofac;
using Jackett.Models.Config;
using Jackett.Services;
+using Jackett.Utils;
using Jackett.Utils.Clients;
using Microsoft.Owin.Hosting;
using Newtonsoft.Json.Linq;
@@ -16,6 +17,7 @@ using System.IO;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
+using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
@@ -91,12 +93,16 @@ namespace Jackett.Services
}
if (string.IsNullOrWhiteSpace(config.APIKey))
- {
- config.APIKey = config.GenerateApi();
- }
+ config.APIKey = StringUtil.GenerateRandom(32);
configService.SaveConfig(config);
}
+
+ if (string.IsNullOrWhiteSpace(config.InstanceId))
+ {
+ config.InstanceId = StringUtil.GenerateRandom(64);
+ configService.SaveConfig(config);
+ }
}
public void SaveConfig()
diff --git a/src/Jackett/Utils/StringUtil.cs b/src/Jackett/Utils/StringUtil.cs
index ad024effa..2e6765c3f 100644
--- a/src/Jackett/Utils/StringUtil.cs
+++ b/src/Jackett/Utils/StringUtil.cs
@@ -51,7 +51,6 @@ namespace Jackett.Utils
return sb.ToString();
}
-
public static string GetExceptionDetails(this Exception exception)
{
var properties = exception.GetType()
@@ -74,5 +73,21 @@ namespace Jackett.Utils
{
return string.Join("&", collection.AllKeys.Select(a => a + "=" + HttpUtility.UrlEncode(collection[a])));
}
+
+ public static string GenerateRandom(int length)
+ {
+ var chars = "abcdefghijklmnopqrstuvwxyz0123456789";
+ var randBytes = new byte[length];
+ using (var rngCsp = new RNGCryptoServiceProvider())
+ {
+ rngCsp.GetBytes(randBytes);
+ var key = "";
+ foreach (var b in randBytes)
+ {
+ key += chars[b % chars.Length];
+ }
+ return key;
+ }
+ }
}
}