2
0
Эх сурвалжийг харах

Merge pull request #9759 from seaeagle1/patch-malformedxml

Rescue malformed Xml response in DLNA PlayTo
Claus Vium 2 жил өмнө
parent
commit
315b13076b

+ 33 - 6
Emby.Dlna/PlayTo/DlnaHttpClient.cs

@@ -2,9 +2,11 @@
 
 using System;
 using System.Globalization;
+using System.IO;
 using System.Net.Http;
 using System.Net.Mime;
 using System.Text;
+using System.Text.RegularExpressions;
 using System.Threading;
 using System.Threading.Tasks;
 using System.Xml;
@@ -15,7 +17,10 @@ using Microsoft.Extensions.Logging;
 
 namespace Emby.Dlna.PlayTo
 {
-    public class DlnaHttpClient
+    /// <summary>
+    /// Http client for Dlna PlayTo function.
+    /// </summary>
+    public partial class DlnaHttpClient
     {
         private readonly ILogger _logger;
         private readonly IHttpClientFactory _httpClientFactory;
@@ -54,15 +59,30 @@ namespace Emby.Dlna.PlayTo
                     LoadOptions.None,
                     cancellationToken).ConfigureAwait(false);
             }
-            catch (XmlException ex)
+            catch (XmlException)
             {
-                _logger.LogError(ex, "Failed to parse response");
-                if (_logger.IsEnabled(LogLevel.Debug))
+                // try correcting the Xml response with common errors
+                var xmlString = await response.Content.ReadAsStringAsync(cancellationToken).ConfigureAwait(false);
+
+                // find and replace unescaped ampersands (&)
+                xmlString = EscapeAmpersandRegex().Replace(xmlString, "&amp;");
+
+                try
                 {
-                    _logger.LogDebug("Malformed response: {Content}\n", await response.Content.ReadAsStringAsync(cancellationToken).ConfigureAwait(false));
+                    // retry reading Xml
+                    var xmlReader = new StringReader(xmlString);
+                    return await XDocument.LoadAsync(
+                        xmlReader,
+                        LoadOptions.None,
+                        cancellationToken).ConfigureAwait(false);
                 }
+                catch (XmlException ex)
+                {
+                    _logger.LogError(ex, "Failed to parse response");
+                    _logger.LogDebug("Malformed response: {Content}\n", xmlString);
 
-                return null;
+                    return null;
+                }
             }
         }
 
@@ -104,5 +124,12 @@ namespace Emby.Dlna.PlayTo
             // Have to await here instead of returning the Task directly, otherwise request would be disposed too soon
             return await SendRequestAsync(request, cancellationToken).ConfigureAwait(false);
         }
+
+        /// <summary>
+        /// Compile-time generated regular expression for escaping ampersands.
+        /// </summary>
+        /// <returns>Compiled regular expression.</returns>
+        [GeneratedRegex("(&(?![a-z]*;))")]
+        private static partial Regex EscapeAmpersandRegex();
     }
 }