2015-07-24 19:15:08 +00:00
|
|
|
|
using Jackett.Utils;
|
|
|
|
|
using Newtonsoft.Json.Linq;
|
2015-07-19 13:22:50 +00:00
|
|
|
|
using NLog;
|
2015-07-19 00:27:41 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Reflection;
|
2015-07-24 21:38:31 +00:00
|
|
|
|
using System.Security.AccessControl;
|
|
|
|
|
using System.Security.Principal;
|
2015-07-19 00:27:41 +00:00
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using System.Windows.Forms;
|
2017-10-29 10:19:09 +00:00
|
|
|
|
using Jackett.Services.Interfaces;
|
2015-07-19 00:27:41 +00:00
|
|
|
|
|
|
|
|
|
namespace Jackett.Services
|
|
|
|
|
{
|
|
|
|
|
|
2015-07-19 16:35:56 +00:00
|
|
|
|
public class ConfigurationService : IConfigurationService
|
2015-07-19 00:27:41 +00:00
|
|
|
|
{
|
2015-07-19 13:22:50 +00:00
|
|
|
|
private ISerializeService serializeService;
|
|
|
|
|
private Logger logger;
|
2015-07-24 19:15:08 +00:00
|
|
|
|
private IProcessService processService;
|
2015-07-19 13:22:50 +00:00
|
|
|
|
|
2015-07-24 19:15:08 +00:00
|
|
|
|
public ConfigurationService(ISerializeService s, IProcessService p, Logger l)
|
2015-07-19 00:27:41 +00:00
|
|
|
|
{
|
2015-07-19 13:22:50 +00:00
|
|
|
|
serializeService = s;
|
|
|
|
|
logger = l;
|
2015-07-24 19:15:08 +00:00
|
|
|
|
processService = p;
|
2015-07-19 13:22:50 +00:00
|
|
|
|
CreateOrMigrateSettings();
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-24 19:15:08 +00:00
|
|
|
|
public void CreateOrMigrateSettings()
|
2015-07-19 13:22:50 +00:00
|
|
|
|
{
|
|
|
|
|
try
|
2015-07-19 00:27:41 +00:00
|
|
|
|
{
|
2015-07-19 13:22:50 +00:00
|
|
|
|
if (!Directory.Exists(GetAppDataFolder()))
|
|
|
|
|
{
|
2015-07-24 21:38:31 +00:00
|
|
|
|
var dir = Directory.CreateDirectory(GetAppDataFolder());
|
|
|
|
|
if (System.Environment.OSVersion.Platform != PlatformID.Unix)
|
|
|
|
|
{
|
|
|
|
|
var access = dir.GetAccessControl();
|
|
|
|
|
access.AddAccessRule(new FileSystemAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), FileSystemRights.FullControl, InheritanceFlags.ObjectInherit | InheritanceFlags.ContainerInherit, PropagationFlags.None, AccessControlType.Allow));
|
|
|
|
|
Directory.SetAccessControl(GetAppDataFolder(), access);
|
|
|
|
|
}
|
2015-07-19 13:22:50 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-02-03 13:34:34 +00:00
|
|
|
|
logger.Info("App config/log directory: " + GetAppDataFolder());
|
2015-07-19 00:27:41 +00:00
|
|
|
|
}
|
2015-07-19 13:22:50 +00:00
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
throw new Exception("Could not create settings directory. " + ex.Message);
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-24 21:38:31 +00:00
|
|
|
|
if (System.Environment.OSVersion.Platform != PlatformID.Unix)
|
2015-07-19 13:22:50 +00:00
|
|
|
|
{
|
2015-07-24 21:38:31 +00:00
|
|
|
|
try
|
2015-07-19 13:22:50 +00:00
|
|
|
|
{
|
2015-07-24 21:38:31 +00:00
|
|
|
|
string oldDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Jackett");
|
|
|
|
|
if (Directory.Exists(oldDir))
|
2015-07-19 13:22:50 +00:00
|
|
|
|
{
|
2015-07-24 21:38:31 +00:00
|
|
|
|
|
2015-07-24 19:15:08 +00:00
|
|
|
|
// On Windows we need admin permissions to migrate as they were made with admin permissions.
|
|
|
|
|
if (ServerUtil.IsUserAdministrator())
|
2015-07-19 13:22:50 +00:00
|
|
|
|
{
|
2015-07-24 19:15:08 +00:00
|
|
|
|
PerformMigration();
|
2015-07-19 13:22:50 +00:00
|
|
|
|
}
|
2015-07-24 19:15:08 +00:00
|
|
|
|
else
|
2015-07-19 16:35:56 +00:00
|
|
|
|
{
|
2015-07-24 19:15:08 +00:00
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
processService.StartProcessAndLog(Application.ExecutablePath, "--MigrateSettings", true);
|
|
|
|
|
}
|
|
|
|
|
catch
|
|
|
|
|
{
|
|
|
|
|
Engine.Logger.Error("Unable to migrate settings when not running as administrator.");
|
|
|
|
|
Environment.ExitCode = 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2015-07-19 16:35:56 +00:00
|
|
|
|
}
|
2015-07-24 21:38:31 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
2015-07-24 19:15:08 +00:00
|
|
|
|
{
|
|
|
|
|
PerformMigration();
|
2015-07-19 13:22:50 +00:00
|
|
|
|
}
|
2015-07-24 21:38:31 +00:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
logger.Error("ERROR could not migrate settings directory " + ex);
|
2015-07-19 13:22:50 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-24 19:15:08 +00:00
|
|
|
|
public void PerformMigration()
|
|
|
|
|
{
|
|
|
|
|
var oldDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Jackett");
|
2015-07-24 21:38:31 +00:00
|
|
|
|
if (Directory.Exists(oldDir))
|
2015-07-24 19:15:08 +00:00
|
|
|
|
{
|
2015-11-10 22:02:02 +00:00
|
|
|
|
foreach (var file in Directory.GetFiles(oldDir, "*", SearchOption.AllDirectories))
|
2015-07-24 19:15:08 +00:00
|
|
|
|
{
|
2015-07-24 21:38:31 +00:00
|
|
|
|
var path = file.Replace(oldDir, "");
|
|
|
|
|
var destPath = GetAppDataFolder() + path;
|
|
|
|
|
var destFolder = Path.GetDirectoryName(destPath);
|
|
|
|
|
if (!Directory.Exists(destFolder))
|
|
|
|
|
{
|
|
|
|
|
var dir = Directory.CreateDirectory(destFolder);
|
|
|
|
|
var access = dir.GetAccessControl();
|
|
|
|
|
access.AddAccessRule(new FileSystemAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), FileSystemRights.FullControl, InheritanceFlags.ObjectInherit | InheritanceFlags.ContainerInherit, PropagationFlags.None, AccessControlType.Allow));
|
|
|
|
|
Directory.SetAccessControl(destFolder, access);
|
|
|
|
|
}
|
|
|
|
|
if (!File.Exists(destPath))
|
|
|
|
|
{
|
|
|
|
|
File.Copy(file, destPath);
|
|
|
|
|
// The old files were created when running as admin so make sure they are editable by normal users / services.
|
|
|
|
|
if (System.Environment.OSVersion.Platform != PlatformID.Unix)
|
|
|
|
|
{
|
|
|
|
|
var access = File.GetAccessControl(destPath);
|
|
|
|
|
access.AddAccessRule(new FileSystemAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), FileSystemRights.FullControl, InheritanceFlags.None, PropagationFlags.None, AccessControlType.Allow));
|
|
|
|
|
File.SetAccessControl(destPath, access);
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-07-24 19:15:08 +00:00
|
|
|
|
}
|
2015-07-24 21:38:31 +00:00
|
|
|
|
Directory.Delete(oldDir, true);
|
2015-07-24 19:15:08 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-19 13:22:50 +00:00
|
|
|
|
public T GetConfig<T>()
|
|
|
|
|
{
|
|
|
|
|
var type = typeof(T);
|
|
|
|
|
var fullPath = Path.Combine(GetAppDataFolder(), type.Name + ".json");
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
if (!File.Exists(fullPath))
|
|
|
|
|
{
|
|
|
|
|
logger.Debug("Config file does not exist: " + fullPath);
|
|
|
|
|
return default(T);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return serializeService.DeSerialise<T>(File.ReadAllText(fullPath));
|
|
|
|
|
}
|
2015-07-19 16:35:56 +00:00
|
|
|
|
catch (Exception e)
|
2015-07-19 00:27:41 +00:00
|
|
|
|
{
|
2015-07-19 13:22:50 +00:00
|
|
|
|
logger.Error(e, "Error reading config file " + fullPath);
|
|
|
|
|
return default(T);
|
2015-07-19 00:27:41 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-19 13:22:50 +00:00
|
|
|
|
public void SaveConfig<T>(T config)
|
|
|
|
|
{
|
|
|
|
|
var type = typeof(T);
|
|
|
|
|
var fullPath = Path.Combine(GetAppDataFolder(), type.Name + ".json");
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var json = serializeService.Serialise(config);
|
|
|
|
|
if (!Directory.Exists(GetAppDataFolder()))
|
|
|
|
|
Directory.CreateDirectory(GetAppDataFolder());
|
|
|
|
|
File.WriteAllText(fullPath, json);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
2016-10-01 17:53:43 +00:00
|
|
|
|
logger.Error(e, "Error writing config file " + fullPath);
|
2015-07-19 13:22:50 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string ApplicationFolder()
|
|
|
|
|
{
|
|
|
|
|
return Path.GetDirectoryName(Application.ExecutablePath);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string GetContentFolder()
|
|
|
|
|
{
|
|
|
|
|
// If we are debugging we can use the non copied content.
|
2015-07-23 20:36:23 +00:00
|
|
|
|
string dir = Path.Combine(ApplicationFolder(), "Content"); ;
|
|
|
|
|
|
|
|
|
|
#if DEBUG
|
|
|
|
|
// When we are running in debug use the source files
|
|
|
|
|
var sourcePath = Path.GetFullPath(Path.Combine(ApplicationFolder(), "..\\..\\..\\Jackett\\Content"));
|
|
|
|
|
if (Directory.Exists(sourcePath))
|
2015-07-19 13:22:50 +00:00
|
|
|
|
{
|
2015-07-23 20:36:23 +00:00
|
|
|
|
dir = sourcePath;
|
2015-07-19 13:22:50 +00:00
|
|
|
|
}
|
2016-10-27 07:30:03 +00:00
|
|
|
|
#endif
|
|
|
|
|
return dir;
|
2017-04-15 08:45:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-10-30 18:34:48 +00:00
|
|
|
|
public List<string> GetCardigannDefinitionsFolders()
|
2016-10-27 07:30:03 +00:00
|
|
|
|
{
|
2016-10-30 18:34:48 +00:00
|
|
|
|
List<string> dirs = new List<string>();
|
|
|
|
|
|
|
|
|
|
if (System.Environment.OSVersion.Platform == PlatformID.Unix)
|
|
|
|
|
{
|
2016-11-10 17:24:35 +00:00
|
|
|
|
dirs.Add(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "cardigann/definitions/"));
|
2016-10-30 18:34:48 +00:00
|
|
|
|
dirs.Add("/etc/xdg/cardigan/definitions/");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
dirs.Add(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "cardigann\\definitions\\"));
|
|
|
|
|
dirs.Add(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "cardigann\\definitions\\"));
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-27 07:30:03 +00:00
|
|
|
|
// If we are debugging we can use the non copied definitions.
|
|
|
|
|
string dir = Path.Combine(ApplicationFolder(), "Definitions"); ;
|
|
|
|
|
|
|
|
|
|
#if DEBUG
|
|
|
|
|
// When we are running in debug use the source files
|
|
|
|
|
var sourcePath = Path.GetFullPath(Path.Combine(ApplicationFolder(), "..\\..\\..\\Jackett\\Definitions"));
|
|
|
|
|
if (Directory.Exists(sourcePath))
|
|
|
|
|
{
|
|
|
|
|
dir = sourcePath;
|
|
|
|
|
}
|
2015-07-23 20:36:23 +00:00
|
|
|
|
#endif
|
2016-10-30 18:34:48 +00:00
|
|
|
|
dirs.Add(dir);
|
|
|
|
|
return dirs;
|
2015-07-19 13:22:50 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-07-19 00:27:41 +00:00
|
|
|
|
public string GetVersion()
|
|
|
|
|
{
|
|
|
|
|
return Assembly.GetExecutingAssembly().GetName().Version.ToString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string GetAppDataFolder()
|
|
|
|
|
{
|
2015-07-19 13:22:50 +00:00
|
|
|
|
return GetAppDataFolderStatic();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// This is needed for the logger prior to ioc setup.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public static string GetAppDataFolderStatic()
|
|
|
|
|
{
|
2016-05-28 09:40:55 +00:00
|
|
|
|
if (!string.IsNullOrWhiteSpace(Startup.CustomDataFolder))
|
|
|
|
|
{
|
|
|
|
|
return Startup.CustomDataFolder;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-22 22:00:52 +00:00
|
|
|
|
if (System.Environment.OSVersion.Platform == PlatformID.Unix)
|
|
|
|
|
{
|
|
|
|
|
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Jackett");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Jackett");
|
|
|
|
|
}
|
2015-07-19 00:27:41 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string GetIndexerConfigDir()
|
|
|
|
|
{
|
2015-07-19 16:35:56 +00:00
|
|
|
|
return Path.Combine(GetAppDataFolder(), "Indexers");
|
2015-07-19 00:27:41 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string GetConfigFile()
|
|
|
|
|
{
|
|
|
|
|
return Path.Combine(GetAppDataFolder(), "config.json");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string GetSonarrConfigFile()
|
|
|
|
|
{
|
|
|
|
|
return Path.Combine(GetAppDataFolder(), "sonarr_api.json");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|