Fixed: Indexers returning relative urls for grabs.

This commit is contained in:
Taloth Saldono 2015-08-15 12:32:37 +02:00
parent 38c57ce73a
commit 211863d55d
10 changed files with 87 additions and 50 deletions

View File

@ -1,31 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE torrent PUBLIC "-//bitTorrent//DTD torrent 0.1//EN" "http://xmlns.ezrss.it/0.1/dtd/">
<rss version="2.0">
<channel>
<title>ezRSS - Latest torrent releases</title>
<ttl>15</ttl>
<link>http://ezrss.it/feed/</link>
<image>
<title>ezRSS - Latest torrent releases</title>
<url>http://ezrss.it/images/ezrssit.png</url>
<link>http://ezrss.it/feed/</link>
</image>
<description>The latest 30 torrent releases.</description>
<item>
<title><![CDATA[Andy McNabs Tour Of Duty Series 1 - Courage Under Fire 1x6 [DVDRIP - MVGROUP]]]></title>
<link>invalid.url</link>
<category domain="http://eztv.it/shows/187/mv-group-documentaries/"><![CDATA[TV Show / MV Group Documentaries]]></category>
<pubDate>Mon, 15 Sep 2014 13:04:21 -0500</pubDate>
<description><![CDATA[Show Name: Andy McNabs Tour Of Duty Series 1; Episode Title: Courage Under Fire; Season: 1; Episode: 6]]></description>
<enclosure url="invalid.url" length="698999946" type="application/x-bittorrent" />
<comments>http://eztv.it/forum/discuss/58438/</comments>
<guid>http://eztv.it/ep/58438/andy-mcnabs-tour-of-duty-series-1-6of6-courage-under-fire-dvdrip-x264-mvgroup/</guid>
<torrent xmlns="http://xmlns.ezrss.it/0.1/">
<fileName><![CDATA[Andy.McNabs.Tour.Of.Duty.Series.1.6of6.Courage.Under.Fire.DVDRip.x264-MVGroup.[MVGroup.org].torrent]]></fileName>
<contentLength>698999946</contentLength>
<infoHash>AAA2038BED9EBCA2C312D1C9C3E8E024D0EB414E</infoHash>
<magnetURI><![CDATA[magnet:?xt=urn:btih:VKRAHC7NT26KFQYS2HE4H2HAETIOWQKO&dn=Andy.McNabs.Tour.Of.Duty.Series.1.6of6.Courage.Under.Fire.DVDRip.x264-MVGroup]]></magnetURI>
</torrent>
</item>
</channel>
</rss>

View File

@ -25,7 +25,7 @@
&lt;br /&gt; &lt;br /&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;&lt;span id=&quot;lazyload&quot;&gt;&lt;span id=&quot;350237944_80b24e6a90a69f7bb9b39a6b3f99e4bb&quot;&gt;&amp;nbsp;&lt;/span&gt; &lt;a href=&quot;https://immortalseed.me/images/modpics/195.jpg&quot; id=&quot;ts_show_preview&quot; alt=&quot;&quot;&gt;&lt;img src=&quot;https://immortalseed.me/images/modpics/195.jpg&quot; border=&quot;0&quot; alt=&quot;&quot; onload=&quot;TSResizeImage(this, '350237944_80b24e6a90a69f7bb9b39a6b3f99e4bb');&quot; /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/div&gt; &lt;div style=&quot;text-align: center;&quot;&gt;&lt;span id=&quot;lazyload&quot;&gt;&lt;span id=&quot;350237944_80b24e6a90a69f7bb9b39a6b3f99e4bb&quot;&gt;&amp;nbsp;&lt;/span&gt; &lt;a href=&quot;https://immortalseed.me/images/modpics/195.jpg&quot; id=&quot;ts_show_preview&quot; alt=&quot;&quot;&gt;&lt;img src=&quot;https://immortalseed.me/images/modpics/195.jpg&quot; border=&quot;0&quot; alt=&quot;&quot; onload=&quot;TSResizeImage(this, '350237944_80b24e6a90a69f7bb9b39a6b3f99e4bb');&quot; /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;
</description> </description>
<link>invalid.url</link> <link></link>
<author>Anonymous</author> <author>Anonymous</author>
<category>TV - High Definition</category> <category>TV - High Definition</category>
<pubDate>2015-02-06 13:32:26</pubDate> <pubDate>2015-02-06 13:32:26</pubDate>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<item>
<title>Real.Time.With.Bill.Maher.2015.08.07.720p.HDTV.x264-BATV </title>
<guid isPermaLink="true">details/123</guid>
<link>getnzb/123.nzb&amp;i=782&amp;r=123</link>
<comments>details/123#comments</comments>
<pubDate>Sat, 08 Aug 2015 14:27:16 +0100</pubDate>
<category>TV &gt; HD</category>
<description>Real.Time.With.Bill.Maher.2015.08.07.720p.HDTV.x264-BATV </description>
<enclosure url="getnzb/123.nzb&amp;i=123&amp;r=123" length="1230000000" type="application/x-nzb"/>
</item>
</channel>
</rss>

View File

@ -1,5 +1,8 @@
using FluentAssertions; using System.Linq;
using System.Text;
using FluentAssertions;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Common.Http;
using NzbDrone.Core.Indexers; using NzbDrone.Core.Indexers;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
@ -34,5 +37,25 @@ namespace NzbDrone.Core.Test.IndexerTests
result.Should().Be(0); 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");
}
} }
} }

View File

@ -194,7 +194,6 @@ namespace NzbDrone.Core.Test.IndexerTests.TorrentRssIndexerTests
settings.Should().NotBeNull(); settings.Should().NotBeNull();
} }
[TestCase("TorrentRss/invalid/Eztv_InvalidDownloadUrl.xml")]
[TestCase("TorrentRss/invalid/ImmortalSeed_InvalidDownloadUrl.xml")] [TestCase("TorrentRss/invalid/ImmortalSeed_InvalidDownloadUrl.xml")]
public void should_reject_recent_feed_with_invalid_downloadurl(string rssXmlFile) public void should_reject_recent_feed_with_invalid_downloadurl(string rssXmlFile)
{ {

View File

@ -403,6 +403,9 @@
<Content Include="Files\emptyfile.txt"> <Content Include="Files\emptyfile.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content> </Content>
<Content Include="Files\Indexers\relative_urls.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Files\Indexers\TorrentRss\Doki.xml"> <Content Include="Files\Indexers\TorrentRss\Doki.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content> </Content>
@ -410,10 +413,6 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content> </Content>
<Content Include="Files\Indexers\TorrentRss\invalid\Eztv_InvalidDownloadUrl.xml">
<SubType>Designer</SubType>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Files\Indexers\Fanzub\fanzub.xml"> <Content Include="Files\Indexers\Fanzub\fanzub.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content> </Content>

View File

@ -47,12 +47,12 @@ namespace NzbDrone.Core.Indexers.Newznab
protected override String GetInfoUrl(XElement item) 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) protected override String GetCommentUrl(XElement item)
{ {
return item.TryGetValue("comments"); return ParseUrl(item.TryGetValue("comments"));
} }
protected override Int64 GetSize(XElement item) protected override Int64 GetSize(XElement item)
@ -87,7 +87,7 @@ namespace NzbDrone.Core.Indexers.Newznab
if (!Uri.IsWellFormedUriString(url, UriKind.Absolute)) if (!Uri.IsWellFormedUriString(url, UriKind.Absolute))
{ {
url = item.Element("enclosure").Attribute("url").Value; url = ParseUrl((string)item.Element("enclosure").Attribute("url"));
} }
return url; return url;

View File

@ -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. // Parse "Size: 1.3 GB" or "1.3 GB" parts in the description element and use that as Size.
public Boolean ParseSizeInDescription { get; set; } public Boolean ParseSizeInDescription { get; set; }
private IndexerResponse _indexerResponse;
public RssParser() public RssParser()
{ {
_logger = NzbDroneLogger.GetLogger(this); _logger = NzbDroneLogger.GetLogger(this);
@ -35,6 +37,8 @@ namespace NzbDrone.Core.Indexers
public virtual IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse) public virtual IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
{ {
_indexerResponse = indexerResponse;
var releases = new List<ReleaseInfo>(); var releases = new List<ReleaseInfo>();
if (!PreProcess(indexerResponse)) if (!PreProcess(indexerResponse))
@ -168,25 +172,25 @@ namespace NzbDrone.Core.Indexers
{ {
if (UseEnclosureUrl) 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) protected virtual string GetInfoUrl(XElement item)
{ {
if (UseGuidInfoUrl) if (UseGuidInfoUrl)
{ {
return (String)item.Element("guid"); return ParseUrl((string)item.Element("guid"));
} }
return String.Empty; return null;
} }
protected virtual string GetCommentUrl(XElement item) protected virtual string GetCommentUrl(XElement item)
{ {
return (String)item.Element("comments"); return ParseUrl((string)item.Element("comments"));
} }
protected virtual long GetSize(XElement item) protected virtual long GetSize(XElement item)
@ -234,6 +238,31 @@ namespace NzbDrone.Core.Indexers
return channel.Elements("item"); 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(@"(?<value>(?:\d+,)*\d+(?:\.\d{1,2})?)\W?(?<unit>[KMG]i?B)(?![\w/])", private static readonly Regex ParseSizeRegex = new Regex(@"(?<value>(?:\d+,)*\d+(?:\.\d{1,2})?)\W?(?<unit>[KMG]i?B)(?![\w/])",
RegexOptions.IgnoreCase | RegexOptions.Compiled); RegexOptions.IgnoreCase | RegexOptions.Compiled);

View File

@ -66,7 +66,7 @@ namespace NzbDrone.Core.Indexers
protected virtual String GetMagnetUrl(XElement item) protected virtual String GetMagnetUrl(XElement item)
{ {
var downloadUrl = GetDownloadUrl(item); var downloadUrl = GetDownloadUrl(item);
if (downloadUrl.StartsWith("magnet:")) if (downloadUrl.IsNotNullOrWhiteSpace() && downloadUrl.StartsWith("magnet:"))
{ {
return downloadUrl; return downloadUrl;
} }

View File

@ -59,12 +59,12 @@ namespace NzbDrone.Core.Indexers.Torznab
protected override String GetInfoUrl(XElement item) 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) protected override String GetCommentUrl(XElement item)
{ {
return item.TryGetValue("comments"); return ParseUrl(item.TryGetValue("comments"));
} }
protected override Int64 GetSize(XElement item) protected override Int64 GetSize(XElement item)
@ -93,7 +93,7 @@ namespace NzbDrone.Core.Indexers.Torznab
if (!Uri.IsWellFormedUriString(url, UriKind.Absolute)) if (!Uri.IsWellFormedUriString(url, UriKind.Absolute))
{ {
url = item.Element("enclosure").Attribute("url").Value; url = ParseUrl((string)item.Element("enclosure").Attribute("url"));
} }
return url; return url;