From f96f99750637e9bb39f90008bed7031205906b94 Mon Sep 17 00:00:00 2001 From: Taloth Saldono Date: Fri, 5 Feb 2016 20:08:54 +0100 Subject: [PATCH] Fixed: Handling xml responses containing invalid html entities. fixes #1123 --- .../KickassTorrents_accents.xml | 93 +++++++++++++++++++ .../KickassTorrentsFixture.cs | 15 +++ .../NzbDrone.Core.Test.csproj | 3 + src/NzbDrone.Core/Indexers/RssParser.cs | 23 ++++- 4 files changed, 132 insertions(+), 2 deletions(-) create mode 100644 src/NzbDrone.Core.Test/Files/Indexers/KickassTorrents/KickassTorrents_accents.xml diff --git a/src/NzbDrone.Core.Test/Files/Indexers/KickassTorrents/KickassTorrents_accents.xml b/src/NzbDrone.Core.Test/Files/Indexers/KickassTorrents/KickassTorrents_accents.xml new file mode 100644 index 000000000..7deced5f1 --- /dev/null +++ b/src/NzbDrone.Core.Test/Files/Indexers/KickassTorrents/KickassTorrents_accents.xml @@ -0,0 +1,93 @@ + + + + tv torrents RSS feed - KickassTorrents + http://kickass.to/ + tv torrents RSS feed + + Doctor Strangér.E03.140512.HDTV.H264.720p-iPOP.avi [CTRG] + TV + http://kickass.to/user/2NE1/ + http://kickass.to/doctor-stranger-e03-140512-hdtv-h264-720p-ipop-avi-ctrg-t9100648.html + http://kickass.to/doctor-stranger-e03-140512-hdtv-h264-720p-ipop-avi-ctrg-t9100648.html + Mon, 12 May 2014 16:16:49 +0000 + 1205364736 + 208C4F7866612CC88BFEBC7C496FA72C2368D1C0 + + 206 + 311 + 1 + doctor.stranger.e03.140512.hdtv.h264.720p.ipop.avi.ctrg.torrent + + + + Triangle.E03.140512.HDTV.XViD-iPOP.avi [CTRG] + TV + http://kickass.to/user/2NE1/ + http://kickass.to/triangle-e03-140512-hdtv-xvid-ipop-avi-ctrg-t9100647.html + http://kickass.to/triangle-e03-140512-hdtv-xvid-ipop-avi-ctrg-t9100647.html + Mon, 12 May 2014 16:16:31 +0000 + 677543936 + BF22A53C9889A7D325F2A3D904E566B7DF4074EB + + 242 + 374 + 1 + triangle.e03.140512.hdtv.xvid.ipop.avi.ctrg.torrent + + + + Triangle.E03.140512.HDTV.H264.720p-iPOP.avi [CTRG] + TV + http://kickass.to/user/2NE1/ + http://kickass.to/triangle-e03-140512-hdtv-h264-720p-ipop-avi-ctrg-t9100646.html + http://kickass.to/triangle-e03-140512-hdtv-h264-720p-ipop-avi-ctrg-t9100646.html + Mon, 12 May 2014 16:16:10 +0000 + 1196869632 + 8427BFB8884B8228364EBB9B3EA7D8B77E03A7BC + + 177 + 268 + 1 + triangle.e03.140512.hdtv.h264.720p.ipop.avi.ctrg.torrent + + + + Triangle.E03.140512.HDTV.X264.720p-BarosG_.avi [CTRG] + TV + http://kickass.to/user/2NE1/ + http://kickass.to/triangle-e03-140512-hdtv-x264-720p-barosg-avi-ctrg-t9100644.html + http://kickass.to/triangle-e03-140512-hdtv-x264-720p-barosg-avi-ctrg-t9100644.html + Mon, 12 May 2014 16:15:52 +0000 + 1418906266 + 5556B773893DB55287ECEC581E850B853163DB11 + + 522 + 785 + 1 + triangle.e03.140512.hdtv.x264.720p.barosg.avi.ctrg.torrent + + + + Battlestar Galactica 1978 Dvd3 e09 e10 e11 e12 [NL] [FR] [ENG] Sub + + + + TV + http://kickass.to/user/hendriknl/ + http://kickass.to/battlestar-galactica-1978-dvd3-e09-e10-e11-e12-nl-fr-eng-sub-t9100642.html + http://kickass.to/battlestar-galactica-1978-dvd3-e09-e10-e11-e12-nl-fr-eng-sub-t9100642.html + Mon, 12 May 2014 16:15:46 +0000 + 4680841216 + 3D293CAFEDAC595F6E55F9C284DD76862FE254F6 + + 2 + 5 + 0 + battlestar.galactica.1978.dvd3.e09.e10.e11.e12.nl.fr.eng.sub.torrent + + + + \ No newline at end of file diff --git a/src/NzbDrone.Core.Test/IndexerTests/KickassTorrentsTests/KickassTorrentsFixture.cs b/src/NzbDrone.Core.Test/IndexerTests/KickassTorrentsTests/KickassTorrentsFixture.cs index d6c06a6cd..8da5e572f 100644 --- a/src/NzbDrone.Core.Test/IndexerTests/KickassTorrentsTests/KickassTorrentsFixture.cs +++ b/src/NzbDrone.Core.Test/IndexerTests/KickassTorrentsTests/KickassTorrentsFixture.cs @@ -154,5 +154,20 @@ public void should_not_set_seeders_to_null_if_older_than_12_hours() torrentInfo.Peers.Should().Be(0); torrentInfo.Seeders.Should().Be(0); } + + + [Test] + public void should_handle_xml_with_html_accents() + { + var recentFeed = ReadAllText(@"Files/Indexers/KickassTorrents/KickassTorrents_accents.xml"); + + Mocker.GetMock() + .Setup(o => o.Execute(It.Is(v => v.Method == HttpMethod.GET))) + .Returns(r => new HttpResponse(r, new HttpHeader(), recentFeed)); + + var releases = Subject.FetchRecent(); + + releases.Should().HaveCount(5); + } } } diff --git a/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj index 327dd3996..4210c8171 100644 --- a/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj +++ b/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj @@ -403,6 +403,9 @@ Always + + Always + Always diff --git a/src/NzbDrone.Core/Indexers/RssParser.cs b/src/NzbDrone.Core/Indexers/RssParser.cs index 27f1496ee..c78c67094 100644 --- a/src/NzbDrone.Core/Indexers/RssParser.cs +++ b/src/NzbDrone.Core/Indexers/RssParser.cs @@ -3,6 +3,7 @@ using System.Globalization; using System.IO; using System.Linq; +using System.Net; using System.Text.RegularExpressions; using System.Xml; using System.Xml.Linq; @@ -16,6 +17,8 @@ namespace NzbDrone.Core.Indexers { public class RssParser : IParseIndexerResponse { + private static readonly Regex ReplaceEntities = new Regex("&[a-z]+;", RegexOptions.Compiled | RegexOptions.IgnoreCase); + protected readonly Logger _logger; // Use the 'guid' element content as InfoUrl. @@ -71,7 +74,10 @@ protected virtual XDocument LoadXmlDocument(IndexerResponse indexerResponse) { try { - using (var xmlTextReader = XmlReader.Create(new StringReader(indexerResponse.Content), new XmlReaderSettings { DtdProcessing = DtdProcessing.Ignore, IgnoreComments = true })) + var content = indexerResponse.Content; + content = ReplaceEntities.Replace(content, ReplaceEntity); + + using (var xmlTextReader = XmlReader.Create(new StringReader(content), new XmlReaderSettings { DtdProcessing = DtdProcessing.Ignore, IgnoreComments = true })) { return XDocument.Load(xmlTextReader); } @@ -88,6 +94,19 @@ protected virtual XDocument LoadXmlDocument(IndexerResponse indexerResponse) } } + protected virtual string ReplaceEntity(Match match) + { + try + { + var character = WebUtility.HtmlDecode(match.Value); + return string.Concat("&#", (int)character[0], ";"); + } + catch + { + return match.Value; + } + } + protected virtual ReleaseInfo CreateNewReleaseInfo() { return new ReleaseInfo(); @@ -95,7 +114,7 @@ protected virtual ReleaseInfo CreateNewReleaseInfo() protected virtual bool PreProcess(IndexerResponse indexerResponse) { - if (indexerResponse.HttpResponse.StatusCode != System.Net.HttpStatusCode.OK) + if (indexerResponse.HttpResponse.StatusCode != HttpStatusCode.OK) { throw new IndexerException(indexerResponse, "Indexer API call resulted in an unexpected StatusCode [{0}]", indexerResponse.HttpResponse.StatusCode); }