From 39be99504f00123a078d55f1352b0a892a89cfc3 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 19 Jul 2020 21:20:18 +0200 Subject: [PATCH 1/2] Improve DescriptionXmlBuilder * Replace XML escape code with SecurityElement.Escape * Optimize StringBuilder.Append calls --- Emby.Dlna/Server/DescriptionXmlBuilder.cs | 176 +++++++++------------- 1 file changed, 72 insertions(+), 104 deletions(-) diff --git a/Emby.Dlna/Server/DescriptionXmlBuilder.cs b/Emby.Dlna/Server/DescriptionXmlBuilder.cs index 7143c31094..4a19061d71 100644 --- a/Emby.Dlna/Server/DescriptionXmlBuilder.cs +++ b/Emby.Dlna/Server/DescriptionXmlBuilder.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Globalization; using System.Linq; +using System.Security; using System.Text; using Emby.Dlna.Common; using MediaBrowser.Model.Dlna; @@ -67,7 +68,7 @@ namespace Emby.Dlna.Server builder.AppendFormat(" {0}=\"{1}\"", att.Name, att.Value); } - builder.Append(">"); + builder.Append('>'); builder.Append(""); builder.Append("1"); @@ -76,7 +77,9 @@ namespace Emby.Dlna.Server if (!EnableAbsoluteUrls) { - builder.Append("" + Escape(_serverAddress) + ""); + builder.Append("") + .Append(SecurityElement.Escape(_serverAddress)) + .Append(""); } AppendDeviceInfo(builder); @@ -93,91 +96,14 @@ namespace Emby.Dlna.Server AppendIconList(builder); - builder.Append("" + Escape(_serverAddress) + "/web/index.html"); + builder.Append("") + .Append(SecurityElement.Escape(_serverAddress)) + .Append("/web/index.html"); AppendServiceList(builder); builder.Append(""); } - private static readonly char[] s_escapeChars = new char[] - { - '<', - '>', - '"', - '\'', - '&' - }; - - private static readonly string[] s_escapeStringPairs = new[] - { - "<", - "<", - ">", - ">", - "\"", - """, - "'", - "'", - "&", - "&" - }; - - private static string GetEscapeSequence(char c) - { - int num = s_escapeStringPairs.Length; - for (int i = 0; i < num; i += 2) - { - string text = s_escapeStringPairs[i]; - string result = s_escapeStringPairs[i + 1]; - if (text[0] == c) - { - return result; - } - } - - return c.ToString(CultureInfo.InvariantCulture); - } - - /// Replaces invalid XML characters in a string with their valid XML equivalent. - /// The input string with invalid characters replaced. - /// The string within which to escape invalid characters. - public static string Escape(string str) - { - if (str == null) - { - return null; - } - - StringBuilder stringBuilder = null; - int length = str.Length; - int num = 0; - while (true) - { - int num2 = str.IndexOfAny(s_escapeChars, num); - if (num2 == -1) - { - break; - } - - if (stringBuilder == null) - { - stringBuilder = new StringBuilder(); - } - - stringBuilder.Append(str, num, num2 - num); - stringBuilder.Append(GetEscapeSequence(str[num2])); - num = num2 + 1; - } - - if (stringBuilder == null) - { - return str; - } - - stringBuilder.Append(str, num, length - num); - return stringBuilder.ToString(); - } - private void AppendDeviceProperties(StringBuilder builder) { builder.Append(""); @@ -187,32 +113,54 @@ namespace Emby.Dlna.Server builder.Append("urn:schemas-upnp-org:device:MediaServer:1"); - builder.Append("" + Escape(GetFriendlyName()) + ""); - builder.Append("" + Escape(_profile.Manufacturer ?? string.Empty) + ""); - builder.Append("" + Escape(_profile.ManufacturerUrl ?? string.Empty) + ""); + builder.Append("") + .Append(SecurityElement.Escape(GetFriendlyName())) + .Append(""); + builder.Append("") + .Append(SecurityElement.Escape(_profile.Manufacturer ?? string.Empty)) + .Append(""); + builder.Append("") + .Append(SecurityElement.Escape(_profile.ManufacturerUrl ?? string.Empty)) + .Append(""); - builder.Append("" + Escape(_profile.ModelDescription ?? string.Empty) + ""); - builder.Append("" + Escape(_profile.ModelName ?? string.Empty) + ""); + builder.Append("") + .Append(SecurityElement.Escape(_profile.ModelDescription ?? string.Empty)) + .Append(""); + builder.Append("") + .Append(SecurityElement.Escape(_profile.ModelName ?? string.Empty)) + .Append(""); - builder.Append("" + Escape(_profile.ModelNumber ?? string.Empty) + ""); - builder.Append("" + Escape(_profile.ModelUrl ?? string.Empty) + ""); + builder.Append("") + .Append(SecurityElement.Escape(_profile.ModelNumber ?? string.Empty)) + .Append(""); + builder.Append("") + .Append(SecurityElement.Escape(_profile.ModelUrl ?? string.Empty)) + .Append(""); if (string.IsNullOrEmpty(_profile.SerialNumber)) { - builder.Append("" + Escape(_serverId) + ""); + builder.Append("") + .Append(SecurityElement.Escape(_serverId)) + .Append(""); } else { - builder.Append("" + Escape(_profile.SerialNumber) + ""); + builder.Append("") + .Append(SecurityElement.Escape(_profile.SerialNumber)) + .Append(""); } builder.Append(""); - builder.Append("uuid:" + Escape(_serverUdn) + ""); + builder.Append("uuid:") + .Append(SecurityElement.Escape(_serverUdn)) + .Append(""); if (!string.IsNullOrEmpty(_profile.SonyAggregationFlags)) { - builder.Append("" + Escape(_profile.SonyAggregationFlags) + ""); + builder.Append("") + .Append(SecurityElement.Escape(_profile.SonyAggregationFlags)) + .Append(""); } } @@ -250,11 +198,21 @@ namespace Emby.Dlna.Server { builder.Append(""); - builder.Append("" + Escape(icon.MimeType ?? string.Empty) + ""); - builder.Append("" + Escape(icon.Width.ToString(_usCulture)) + ""); - builder.Append("" + Escape(icon.Height.ToString(_usCulture)) + ""); - builder.Append("" + Escape(icon.Depth ?? string.Empty) + ""); - builder.Append("" + BuildUrl(icon.Url) + ""); + builder.Append("") + .Append(SecurityElement.Escape(icon.MimeType ?? string.Empty)) + .Append(""); + builder.Append("") + .Append(SecurityElement.Escape(icon.Width.ToString(_usCulture))) + .Append(""); + builder.Append("") + .Append(SecurityElement.Escape(icon.Height.ToString(_usCulture))) + .Append(""); + builder.Append("") + .Append(SecurityElement.Escape(icon.Depth ?? string.Empty)) + .Append(""); + builder.Append("") + .Append(BuildUrl(icon.Url)) + .Append(""); builder.Append(""); } @@ -270,11 +228,21 @@ namespace Emby.Dlna.Server { builder.Append(""); - builder.Append("" + Escape(service.ServiceType ?? string.Empty) + ""); - builder.Append("" + Escape(service.ServiceId ?? string.Empty) + ""); - builder.Append("" + BuildUrl(service.ScpdUrl) + ""); - builder.Append("" + BuildUrl(service.ControlUrl) + ""); - builder.Append("" + BuildUrl(service.EventSubUrl) + ""); + builder.Append("") + .Append(SecurityElement.Escape(service.ServiceType ?? string.Empty)) + .Append(""); + builder.Append("") + .Append(SecurityElement.Escape(service.ServiceId ?? string.Empty)) + .Append(""); + builder.Append("") + .Append(BuildUrl(service.ScpdUrl)) + .Append(""); + builder.Append("") + .Append(BuildUrl(service.ControlUrl)) + .Append(""); + builder.Append("") + .Append(BuildUrl(service.EventSubUrl)) + .Append(""); builder.Append(""); } @@ -298,7 +266,7 @@ namespace Emby.Dlna.Server url = _serverAddress.TrimEnd('/') + url; } - return Escape(url); + return SecurityElement.Escape(url); } private IEnumerable GetIcons() From 65453c0a84044e313b27cb639d80b5a85565eee2 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 19 Jul 2020 21:31:14 +0200 Subject: [PATCH 2/2] Fix build and more Append calls --- Emby.Dlna/PlayTo/Device.cs | 4 +-- Emby.Dlna/Server/DescriptionXmlBuilder.cs | 2 +- Emby.Dlna/Service/ServiceXmlBuilder.cs | 34 +++++++++++++++++------ 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/Emby.Dlna/PlayTo/Device.cs b/Emby.Dlna/PlayTo/Device.cs index c5080b90f3..72834c69d1 100644 --- a/Emby.Dlna/PlayTo/Device.cs +++ b/Emby.Dlna/PlayTo/Device.cs @@ -4,12 +4,12 @@ using System; using System.Collections.Generic; using System.Globalization; using System.Linq; +using System.Security; using System.Threading; using System.Threading.Tasks; using System.Xml; using System.Xml.Linq; using Emby.Dlna.Common; -using Emby.Dlna.Server; using Emby.Dlna.Ssdp; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; @@ -334,7 +334,7 @@ namespace Emby.Dlna.PlayTo return string.Empty; } - return DescriptionXmlBuilder.Escape(value); + return SecurityElement.Escape(value); } private Task SetPlay(TransportCommands avCommands, CancellationToken cancellationToken) diff --git a/Emby.Dlna/Server/DescriptionXmlBuilder.cs b/Emby.Dlna/Server/DescriptionXmlBuilder.cs index 4a19061d71..bca9e81cd0 100644 --- a/Emby.Dlna/Server/DescriptionXmlBuilder.cs +++ b/Emby.Dlna/Server/DescriptionXmlBuilder.cs @@ -65,7 +65,7 @@ namespace Emby.Dlna.Server foreach (var att in attributes) { - builder.AppendFormat(" {0}=\"{1}\"", att.Name, att.Value); + builder.AppendFormat(CultureInfo.InvariantCulture, " {0}=\"{1}\"", att.Name, att.Value); } builder.Append('>'); diff --git a/Emby.Dlna/Service/ServiceXmlBuilder.cs b/Emby.Dlna/Service/ServiceXmlBuilder.cs index af557aa144..6c7d6f8462 100644 --- a/Emby.Dlna/Service/ServiceXmlBuilder.cs +++ b/Emby.Dlna/Service/ServiceXmlBuilder.cs @@ -1,9 +1,9 @@ #pragma warning disable CS1591 using System.Collections.Generic; +using System.Security; using System.Text; using Emby.Dlna.Common; -using Emby.Dlna.Server; namespace Emby.Dlna.Service { @@ -37,7 +37,9 @@ namespace Emby.Dlna.Service { builder.Append(""); - builder.Append("" + DescriptionXmlBuilder.Escape(item.Name ?? string.Empty) + ""); + builder.Append("") + .Append(SecurityElement.Escape(item.Name ?? string.Empty)) + .Append(""); builder.Append(""); @@ -45,9 +47,15 @@ namespace Emby.Dlna.Service { builder.Append(""); - builder.Append("" + DescriptionXmlBuilder.Escape(argument.Name ?? string.Empty) + ""); - builder.Append("" + DescriptionXmlBuilder.Escape(argument.Direction ?? string.Empty) + ""); - builder.Append("" + DescriptionXmlBuilder.Escape(argument.RelatedStateVariable ?? string.Empty) + ""); + builder.Append("") + .Append(SecurityElement.Escape(argument.Name ?? string.Empty)) + .Append(""); + builder.Append("") + .Append(SecurityElement.Escape(argument.Direction ?? string.Empty)) + .Append(""); + builder.Append("") + .Append(SecurityElement.Escape(argument.RelatedStateVariable ?? string.Empty)) + .Append(""); builder.Append(""); } @@ -68,17 +76,25 @@ namespace Emby.Dlna.Service { var sendEvents = item.SendsEvents ? "yes" : "no"; - builder.Append(""); + builder.Append(""); - builder.Append("" + DescriptionXmlBuilder.Escape(item.Name ?? string.Empty) + ""); - builder.Append("" + DescriptionXmlBuilder.Escape(item.DataType ?? string.Empty) + ""); + builder.Append("") + .Append(SecurityElement.Escape(item.Name ?? string.Empty)) + .Append(""); + builder.Append("") + .Append(SecurityElement.Escape(item.DataType ?? string.Empty)) + .Append(""); if (item.AllowedValues.Length > 0) { builder.Append(""); foreach (var allowedValue in item.AllowedValues) { - builder.Append("" + DescriptionXmlBuilder.Escape(allowedValue) + ""); + builder.Append("") + .Append(SecurityElement.Escape(allowedValue)) + .Append(""); } builder.Append("");