diff --git a/src/NzbDrone.Core.Test/Files/Indexers/TorrentRss/invalid/Eztv_InvalidDownloadUrl.xml b/src/NzbDrone.Core.Test/Files/Indexers/TorrentRss/invalid/Eztv_InvalidDownloadUrl.xml
deleted file mode 100644
index 27317341c..000000000
--- a/src/NzbDrone.Core.Test/Files/Indexers/TorrentRss/invalid/Eztv_InvalidDownloadUrl.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
-
- ezRSS - Latest torrent releases
- 15
- http://ezrss.it/feed/
-
- ezRSS - Latest torrent releases
- http://ezrss.it/images/ezrssit.png
- http://ezrss.it/feed/
-
- The latest 30 torrent releases.
- -
-
- invalid.url
-
- Mon, 15 Sep 2014 13:04:21 -0500
-
-
- http://eztv.it/forum/discuss/58438/
- http://eztv.it/ep/58438/andy-mcnabs-tour-of-duty-series-1-6of6-courage-under-fire-dvdrip-x264-mvgroup/
-
-
- 698999946
- AAA2038BED9EBCA2C312D1C9C3E8E024D0EB414E
-
-
-
-
-
\ No newline at end of file
diff --git a/src/NzbDrone.Core.Test/Files/Indexers/TorrentRss/invalid/ImmortalSeed_InvalidDownloadUrl.xml b/src/NzbDrone.Core.Test/Files/Indexers/TorrentRss/invalid/ImmortalSeed_InvalidDownloadUrl.xml
index 12b49c5c5..d156d09ed 100644
--- a/src/NzbDrone.Core.Test/Files/Indexers/TorrentRss/invalid/ImmortalSeed_InvalidDownloadUrl.xml
+++ b/src/NzbDrone.Core.Test/Files/Indexers/TorrentRss/invalid/ImmortalSeed_InvalidDownloadUrl.xml
@@ -25,7 +25,7 @@
<br />
<div style="text-align: center;"><span id="lazyload"><span id="350237944_80b24e6a90a69f7bb9b39a6b3f99e4bb"> </span> <a href="https://immortalseed.me/images/modpics/195.jpg" id="ts_show_preview" alt=""><img src="https://immortalseed.me/images/modpics/195.jpg" border="0" alt="" onload="TSResizeImage(this, '350237944_80b24e6a90a69f7bb9b39a6b3f99e4bb');" /></a></span></div>
- invalid.url
+
Anonymous
TV - High Definition
2015-02-06 13:32:26
diff --git a/src/NzbDrone.Core.Test/Files/Indexers/relative_urls.xml b/src/NzbDrone.Core.Test/Files/Indexers/relative_urls.xml
new file mode 100644
index 000000000..eb08b2b02
--- /dev/null
+++ b/src/NzbDrone.Core.Test/Files/Indexers/relative_urls.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+ -
+ Real.Time.With.Bill.Maher.2015.08.07.720p.HDTV.x264-BATV
+ details/123
+ getnzb/123.nzb&i=782&r=123
+ details/123#comments
+ Sat, 08 Aug 2015 14:27:16 +0100
+ TV > HD
+ Real.Time.With.Bill.Maher.2015.08.07.720p.HDTV.x264-BATV
+
+
+
+
+
\ No newline at end of file
diff --git a/src/NzbDrone.Core.Test/IndexerTests/BasicRssParserFixture.cs b/src/NzbDrone.Core.Test/IndexerTests/BasicRssParserFixture.cs
index e17fb602f..99cfb82a6 100644
--- a/src/NzbDrone.Core.Test/IndexerTests/BasicRssParserFixture.cs
+++ b/src/NzbDrone.Core.Test/IndexerTests/BasicRssParserFixture.cs
@@ -1,5 +1,8 @@
-using FluentAssertions;
+using System.Linq;
+using System.Text;
+using FluentAssertions;
using NUnit.Framework;
+using NzbDrone.Common.Http;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.Test.Framework;
@@ -34,5 +37,25 @@ namespace NzbDrone.Core.Test.IndexerTests
result.Should().Be(0);
}
+ private IndexerResponse CreateResponse(string url, string content)
+ {
+ var httpRequest = new HttpRequest(url);
+ var httpResponse = new HttpResponse(httpRequest, new HttpHeader(), Encoding.UTF8.GetBytes(content));
+
+ return new IndexerResponse(new IndexerRequest(httpRequest), httpResponse);
+ }
+
+ [Test]
+ public void should_handle_relative_url()
+ {
+ var xml = ReadAllText("Files", "Indexers", "relative_urls.xml");
+
+ var result = Subject.ParseResponse(CreateResponse("http://my.indexer.com/api?q=My+Favourite+Show", xml));
+
+ result.Should().HaveCount(1);
+
+ result.First().CommentUrl.Should().Be("http://my.indexer.com/details/123#comments");
+ result.First().DownloadUrl.Should().Be("http://my.indexer.com/getnzb/123.nzb&i=782&r=123");
+ }
}
}
\ No newline at end of file
diff --git a/src/NzbDrone.Core.Test/IndexerTests/TorrentRssIndexerTests/TorrentRssSettingsDetectorFixture.cs b/src/NzbDrone.Core.Test/IndexerTests/TorrentRssIndexerTests/TorrentRssSettingsDetectorFixture.cs
index df4753f2c..8399d436d 100644
--- a/src/NzbDrone.Core.Test/IndexerTests/TorrentRssIndexerTests/TorrentRssSettingsDetectorFixture.cs
+++ b/src/NzbDrone.Core.Test/IndexerTests/TorrentRssIndexerTests/TorrentRssSettingsDetectorFixture.cs
@@ -194,7 +194,6 @@ namespace NzbDrone.Core.Test.IndexerTests.TorrentRssIndexerTests
settings.Should().NotBeNull();
}
- [TestCase("TorrentRss/invalid/Eztv_InvalidDownloadUrl.xml")]
[TestCase("TorrentRss/invalid/ImmortalSeed_InvalidDownloadUrl.xml")]
public void should_reject_recent_feed_with_invalid_downloadurl(string rssXmlFile)
{
diff --git a/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj
index 4da4f578f..16d62a3be 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
@@ -410,10 +413,6 @@
Designer
Always
-
- Designer
- Always
-
Always
diff --git a/src/NzbDrone.Core/Indexers/Newznab/NewznabRssParser.cs b/src/NzbDrone.Core/Indexers/Newznab/NewznabRssParser.cs
index cc3829cd7..0a895530d 100644
--- a/src/NzbDrone.Core/Indexers/Newznab/NewznabRssParser.cs
+++ b/src/NzbDrone.Core/Indexers/Newznab/NewznabRssParser.cs
@@ -47,12 +47,12 @@ namespace NzbDrone.Core.Indexers.Newznab
protected override String GetInfoUrl(XElement item)
{
- return item.TryGetValue("comments").TrimEnd("#comments");
+ return ParseUrl(item.TryGetValue("comments").TrimEnd("#comments"));
}
protected override String GetCommentUrl(XElement item)
{
- return item.TryGetValue("comments");
+ return ParseUrl(item.TryGetValue("comments"));
}
protected override Int64 GetSize(XElement item)
@@ -87,7 +87,7 @@ namespace NzbDrone.Core.Indexers.Newznab
if (!Uri.IsWellFormedUriString(url, UriKind.Absolute))
{
- url = item.Element("enclosure").Attribute("url").Value;
+ url = ParseUrl((string)item.Element("enclosure").Attribute("url"));
}
return url;
diff --git a/src/NzbDrone.Core/Indexers/RssParser.cs b/src/NzbDrone.Core/Indexers/RssParser.cs
index 985e4968d..2b60153d1 100644
--- a/src/NzbDrone.Core/Indexers/RssParser.cs
+++ b/src/NzbDrone.Core/Indexers/RssParser.cs
@@ -28,6 +28,8 @@ namespace NzbDrone.Core.Indexers
// Parse "Size: 1.3 GB" or "1.3 GB" parts in the description element and use that as Size.
public Boolean ParseSizeInDescription { get; set; }
+ private IndexerResponse _indexerResponse;
+
public RssParser()
{
_logger = NzbDroneLogger.GetLogger(this);
@@ -35,6 +37,8 @@ namespace NzbDrone.Core.Indexers
public virtual IList ParseResponse(IndexerResponse indexerResponse)
{
+ _indexerResponse = indexerResponse;
+
var releases = new List();
if (!PreProcess(indexerResponse))
@@ -168,25 +172,25 @@ namespace NzbDrone.Core.Indexers
{
if (UseEnclosureUrl)
{
- return item.Element("enclosure").Attribute("url").Value;
+ return ParseUrl((string)item.Element("enclosure").Attribute("url"));
}
- return item.Element("link").Value;
+ return ParseUrl((string)item.Element("link"));
}
protected virtual string GetInfoUrl(XElement item)
{
if (UseGuidInfoUrl)
{
- return (String)item.Element("guid");
+ return ParseUrl((string)item.Element("guid"));
}
- return String.Empty;
+ return null;
}
protected virtual string GetCommentUrl(XElement item)
{
- return (String)item.Element("comments");
+ return ParseUrl((string)item.Element("comments"));
}
protected virtual long GetSize(XElement item)
@@ -234,6 +238,31 @@ namespace NzbDrone.Core.Indexers
return channel.Elements("item");
}
+ protected virtual string ParseUrl(string value)
+ {
+ if (value.IsNullOrWhiteSpace())
+ {
+ return null;
+ }
+
+ try
+ {
+ var uri = new Uri(value, UriKind.RelativeOrAbsolute);
+
+ if (!uri.IsAbsoluteUri)
+ {
+ uri = new Uri(_indexerResponse.HttpRequest.Url, uri);
+ }
+
+ return uri.AbsoluteUri;
+ }
+ catch (Exception ex)
+ {
+ _logger.DebugException(string.Format("Failed to parse Uri {0}, ignoring.", value), ex);
+ return null;
+ }
+ }
+
private static readonly Regex ParseSizeRegex = new Regex(@"(?(?:\d+,)*\d+(?:\.\d{1,2})?)\W?(?[KMG]i?B)(?![\w/])",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
diff --git a/src/NzbDrone.Core/Indexers/TorrentRssParser.cs b/src/NzbDrone.Core/Indexers/TorrentRssParser.cs
index de5ba8a71..c3b13aba9 100644
--- a/src/NzbDrone.Core/Indexers/TorrentRssParser.cs
+++ b/src/NzbDrone.Core/Indexers/TorrentRssParser.cs
@@ -66,7 +66,7 @@ namespace NzbDrone.Core.Indexers
protected virtual String GetMagnetUrl(XElement item)
{
var downloadUrl = GetDownloadUrl(item);
- if (downloadUrl.StartsWith("magnet:"))
+ if (downloadUrl.IsNotNullOrWhiteSpace() && downloadUrl.StartsWith("magnet:"))
{
return downloadUrl;
}
diff --git a/src/NzbDrone.Core/Indexers/Torznab/TorznabRssParser.cs b/src/NzbDrone.Core/Indexers/Torznab/TorznabRssParser.cs
index 60a861c6c..bce7cd028 100644
--- a/src/NzbDrone.Core/Indexers/Torznab/TorznabRssParser.cs
+++ b/src/NzbDrone.Core/Indexers/Torznab/TorznabRssParser.cs
@@ -59,12 +59,12 @@ namespace NzbDrone.Core.Indexers.Torznab
protected override String GetInfoUrl(XElement item)
{
- return item.TryGetValue("comments").TrimEnd("#comments");
+ return ParseUrl(item.TryGetValue("comments").TrimEnd("#comments"));
}
protected override String GetCommentUrl(XElement item)
{
- return item.TryGetValue("comments");
+ return ParseUrl(item.TryGetValue("comments"));
}
protected override Int64 GetSize(XElement item)
@@ -93,7 +93,7 @@ namespace NzbDrone.Core.Indexers.Torznab
if (!Uri.IsWellFormedUriString(url, UriKind.Absolute))
{
- url = item.Element("enclosure").Attribute("url").Value;
+ url = ParseUrl((string)item.Element("enclosure").Attribute("url"));
}
return url;