Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Removes obsolete network settings from system.xml #5482

Open
wants to merge 25 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
8348145
New xml migration
BaronGreenback Mar 11, 2021
e96671b
Moved to program.cs
BaronGreenback Mar 11, 2021
6d4e544
Moved migration
BaronGreenback Mar 15, 2021
a9f4cf8
Update ApplicationHost.cs
BaronGreenback Mar 15, 2021
08aeb4f
Update ApplicationHost.cs
BaronGreenback Mar 15, 2021
d5051d7
Update Program.cs
BaronGreenback Mar 15, 2021
1b9b775
Changed to xmlTextReader
BaronGreenback Mar 15, 2021
a43ffc1
reworking
BaronGreenback Mar 22, 2021
14ce842
Simplified
BaronGreenback Mar 22, 2021
5d28ac0
removed unused file.
BaronGreenback Mar 22, 2021
6617fc3
sln correction
BaronGreenback Mar 22, 2021
72b3684
Merge branch 'master' into SettingsMigration
BaronGreenback Mar 23, 2021
23aad2d
Updated from master
BaronGreenback Apr 15, 2021
1bd8259
Used fixed config.
BaronGreenback Apr 15, 2021
1c95184
Merge branch 'master' into SettingsMigration
BaronGreenback Apr 21, 2021
26c6d90
fixed merge
BaronGreenback Apr 21, 2021
ed638d2
Update MigrationRunner.cs
BaronGreenback May 6, 2021
1fd43bc
Create delete me
BaronGreenback May 6, 2021
0d4e0bf
Rename Jellyfin.Server/Migrations/Legacy/V703/NetworkConfiguration.cs…
BaronGreenback May 6, 2021
b12443a
Update and rename Jellyfin.Server/Migrations/Legacy/V703/ServerConfig…
BaronGreenback May 6, 2021
13a8616
Delete delete me
BaronGreenback May 6, 2021
d391257
Update NetworkConfiguration.cs
BaronGreenback May 6, 2021
2d1452e
Improved
BaronGreenback May 7, 2021
6de8c96
changed path to configuration folder
BaronGreenback May 7, 2021
c09b0f7
Merge branch 'master' into SettingsMigration
BaronGreenback May 29, 2021
File filter
Filter file types
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.

Always

Just for now

reworking
  • Loading branch information
BaronGreenback committed Mar 22, 2021
commit a43ffc1ed8030b51b24a37dbafc0fb43f41a2166
@@ -0,0 +1,173 @@
#pragma warning disable CA1819 // Properties should not return arrays

using System;

namespace Jellyfin.Server.Migrations.Legacy
{
/// <summary>
/// Defines the <see cref="NetworkConfiguration" />.
/// This is a point in time snapshot when the network configuration (network.xml) was removed from system.xml.
/// </summary>
public class NetworkConfiguration
{
/// <summary>
/// The default value for <see cref="HttpServerPortNumber"/>.
/// </summary>
public const int DefaultHttpPort = 8096;

/// <summary>
/// The default value for <see cref="PublicHttpsPort"/> and <see cref="HttpsPortNumber"/>.
/// </summary>
public const int DefaultHttpsPort = 8920;

private string _baseUrl = string.Empty;

/// <summary>
/// Gets or sets a value indicating whether the server should force connections over HTTPS.
/// </summary>
public bool RequireHttps { get; set; }

/// <summary>
/// Gets or sets the filesystem path of an X.509 certificate to use for SSL.
/// </summary>
public string CertificatePath { get; set; } = string.Empty;

/// <summary>
/// Gets or sets the password required to access the X.509 certificate data in the file specified by <see cref="CertificatePath"/>.
/// </summary>
public string CertificatePassword { get; set; } = string.Empty;

/// <summary>
/// Gets or sets a value used to specify the URL prefix that your Jellyfin instance can be accessed at.
/// </summary>
public string BaseUrl
{
get => _baseUrl;
set
{
// Normalize the start of the string
if (string.IsNullOrWhiteSpace(value))
{
// If baseUrl is empty, set an empty prefix string
_baseUrl = string.Empty;
return;
}

if (value[0] != '/')
{
// If baseUrl was not configured with a leading slash, append one for consistency
value = "/" + value;
}

// Normalize the end of the string
if (value[^1] == '/')
{
// If baseUrl was configured with a trailing slash, remove it for consistency
value = value.Remove(value.Length - 1);
}

_baseUrl = value;
}
}

/// <summary>
/// Gets or sets the public HTTPS port.
/// </summary>
/// <value>The public HTTPS port.</value>
public int PublicHttpsPort { get; set; } = DefaultHttpsPort;

/// <summary>
/// Gets or sets the HTTP server port number.
/// </summary>
/// <value>The HTTP server port number.</value>
public int HttpServerPortNumber { get; set; } = DefaultHttpPort;

/// <summary>
/// Gets or sets the HTTPS server port number.
/// </summary>
/// <value>The HTTPS server port number.</value>
public int HttpsPortNumber { get; set; } = DefaultHttpsPort;

/// <summary>
/// Gets or sets a value indicating whether to use HTTPS.
/// </summary>
/// <remarks>
/// In order for HTTPS to be used, in addition to setting this to true, valid values must also be
/// provided for <see cref="CertificatePath"/> and <see cref="CertificatePassword"/>.
/// </remarks>
public bool EnableHttps { get; set; }

/// <summary>
/// Gets or sets the public mapped port.
/// </summary>
/// <value>The public mapped port.</value>
public int PublicPort { get; set; } = DefaultHttpPort;

/// <summary>
/// Gets or sets a value indicating whether gets or sets IPV6 capability.
/// </summary>
public bool EnableIPV6 { get; set; }

/// <summary>
/// Gets or sets a value indicating whether gets or sets IPV4 capability.
/// </summary>
public bool EnableIPV4 { get; set; } = true;

/// <summary>
/// Gets or sets a value indicating whether address names that match <see cref="VirtualInterfaceNames"/> should be Ignore for the purposes of binding.
/// </summary>
public bool IgnoreVirtualInterfaces { get; set; } = true;

/// <summary>
/// Gets or sets a value indicating the interfaces that should be ignored. The list can be comma separated. <seealso cref="IgnoreVirtualInterfaces"/>.
/// </summary>
public string VirtualInterfaceNames { get; set; } = "vEthernet*";

/// <summary>
/// Gets or sets a value indicating whether all IPv6 interfaces should be treated as on the internal network.
/// Depending on the address range implemented ULA ranges might not be used.
/// </summary>
public bool TrustAllIP6Interfaces { get; set; }

/// <summary>
/// Gets or sets the PublishedServerUriBySubnet
/// Gets or sets PublishedServerUri to advertise for specific subnets.
/// </summary>
public string[] PublishedServerUriBySubnet { get; set; } = Array.Empty<string>();

/// <summary>
/// Gets or sets the filter for remote IP connectivity. Used in conjuntion with <seealso cref="IsRemoteIPFilterBlacklist"/>.
/// </summary>
public string[] RemoteIPFilter { get; set; } = Array.Empty<string>();

/// <summary>
/// Gets or sets a value indicating whether <seealso cref="RemoteIPFilter"/> contains a blacklist or a whitelist. Default is a whitelist.
/// </summary>
public bool IsRemoteIPFilterBlacklist { get; set; }

/// <summary>
/// Gets or sets a value indicating whether to enable automatic port forwarding.
/// </summary>
public bool EnableUPnP { get; set; }

/// <summary>
/// Gets or sets a value indicating whether access outside of the LAN is permitted.
/// </summary>
public bool EnableRemoteAccess { get; set; } = true;

/// <summary>
/// Gets or sets the subnets that are deemed to make up the LAN.
/// </summary>
public string[] LocalNetworkSubnets { get; set; } = Array.Empty<string>();

/// <summary>
/// Gets or sets the interface addresses which Jellyfin will bind to. If empty, all interfaces will be used.
/// </summary>
public string[] LocalNetworkAddresses { get; set; } = Array.Empty<string>();

/// <summary>
/// Gets or sets the known proxies. If the proxy is a network, it's added to the KnownNetworks.
/// </summary>
public string[] KnownProxies { get; set; } = Array.Empty<string>();
}
}
@@ -0,0 +1,9 @@
namespace Jellyfin.Server.Migrations.Legacy
{
/// <summary>
/// Represents the server configuration.
/// </summary>
public class ServerConfiguration : NetworkConfiguration
{
}
}
@@ -1,15 +1,9 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using Emby.Server.Implementations.Serialization;
using Jellyfin.Networking.Configuration;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller;
using MediaBrowser.Model.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

@@ -98,97 +92,29 @@ public static void Run(CoreAppHost host, ILoggerFactory loggerFactory)
/// <param name="logger">The <see cref="ILogger"/>.</param>
public static void RunNetworkSettingMigration(IServerApplicationPaths appPaths, ILogger logger)
{
const string NetworkRoutine = "909525D1-AC26-4DCF-9100-6E94742F3016";
string routineComplete = " <ValueTupleOfGuidString>\r\n <Item1>" + NetworkRoutine + "</Item1>\r\n <Item2>NetworkSettingMigration</Item2>\r\n </ValueTupleOfGuidString>";

// Cannot use ConfigurationManager as it overwrites the changes we need to see, so we need to emulate the
// function of the MigrationsFactory.
var migrateFile = Path.Combine(appPaths.ConfigurationDirectoryPath, "migrations.xml");
bool needToRun = true;
List<string>? completedMigrations = null;

if (File.Exists(migrateFile))
var destFile = Path.Combine(appPaths.ConfigurationDirectoryPath, "network.xml");
if (!File.Exists(destFile))
{
completedMigrations = File.ReadLines(migrateFile, Encoding.UTF8).ToList();
needToRun = string.IsNullOrEmpty(completedMigrations.FirstOrDefault(p => p.IndexOf(NetworkRoutine, StringComparison.Ordinal) != -1));
}

if (needToRun)
{
var destFile = Path.Combine(appPaths.ConfigurationDirectoryPath, "network.xml");
NetworkConfiguration settings = new ();
var settingsType = typeof(NetworkConfiguration);
var props = settingsType.GetProperties().Where(x => x.CanWrite).ToList();

// manually load source xml file.
var serializer = new XmlSerializer(typeof(ServerConfiguration));
serializer.UnknownElement += (object? sender, XmlElementEventArgs e) =>
{
var p = props.Find(x => string.Equals(x.Name, e.Element.Name, StringComparison.Ordinal));
if (p != null)
{
if (p.PropertyType == typeof(bool))
{
_ = bool.TryParse(e.Element.InnerText, out var boolVal);
p.SetValue(settings, boolVal);
}
else if (p.PropertyType == typeof(int))
{
_ = int.TryParse(e.Element.InnerText, out var intVal);
p.SetValue(settings, intVal);
}
else if (p.PropertyType == typeof(string[]))
{
var items = new List<string>();
foreach (XmlNode el in e.Element.ChildNodes)
{
items.Add(el.InnerText);
}

p.SetValue(settings, items.ToArray());
}
else
{
try
{
p.SetValue(settings, e.Element.InnerText ?? string.Empty);
}
catch
{
logger.LogDebug(
"Unable to migrate value {Name}. Unknown datatype {DataType}. Value {Value}.",
e.Element.Name,
p.PropertyType,
e.Element.InnerText);
}
}
}
};

try
{
using (var xmlReader = new XmlTextReader(appPaths.SystemConfigurationFilePath))
{
var deserialized = (ServerConfiguration?)serializer.Deserialize(xmlReader);
}

var xmlSerializer = new MyXmlSerializer();
xmlSerializer.SerializeToFile(settings, destFile);
var source = xmlSerializer.DeserializeFromFile(typeof(Legacy.ServerConfiguration), appPaths.SystemConfigurationFilePath);

// Insert our completed state at the end of the migrations, but before the Applied element.
if (completedMigrations == null)
{
// Create the file.
File.WriteAllText(
migrateFile,
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<MigrationOptions xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\r\n <Applied>\r\n" + routineComplete + "\r\n </Applied>\r\n</MigrationOptions>\r\n");
}
else
Legacy.NetworkConfiguration target = new ();

var tprops = typeof(Legacy.NetworkConfiguration).GetProperties();
tprops.Where(x => x.CanWrite == true).ToList().ForEach(prop =>
{
// Append us to the end of the elements in the file. (the last 2 lines are the root and top element.)
completedMigrations.Insert(completedMigrations.Count - 2, routineComplete);
File.WriteAllLines(migrateFile, completedMigrations.ToArray());
}
var sp = source.GetType().GetProperty(prop.Name);
if (sp != null)
{
var value = sp.GetValue(source, null);
target.GetType().GetProperty(prop.Name)?.SetValue(target, value, null);
This conversation was marked as resolved by BaronGreenback

This comment has been minimized.

@BaronGreenback

BaronGreenback Mar 23, 2021
Author Contributor

Suggested change
target.GetType().GetProperty(prop.Name)?.SetValue(target, value, null);
try
{
target.GetType().GetProperty(prop.Name)?.SetValue(target, value, null);
}
catch
{
logger.LogDebug("Unable to migration property {Name}", prop.Name);
}
}
});

xmlSerializer.SerializeToFile(target, destFile);
}
catch (Exception ex)
{
ProTip! Use n and p to navigate between commits in a pull request.