Merge pull request #9759 from seaeagle1/patch-malformedxml

Rescue malformed Xml response in DLNA PlayTo
pull/9778/head
Claus Vium 1 year ago committed by GitHub
commit 315b13076b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -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,17 +59,32 @@ 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;
}
}
}
public async Task<XDocument?> GetDataAsync(string url, CancellationToken cancellationToken)
{
@ -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();
}
}

Loading…
Cancel
Save