Skip to content

Commit 3aff262

Browse files
committed
Add support for parsing announce-list as list of strings
Fixes #39
1 parent f02be51 commit 3aff262

2 files changed

Lines changed: 51 additions & 11 deletions

File tree

BencodeNET.Tests/Torrents/TorrentParserTests.cs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Collections.Generic;
33
using System.Text;
44
using BencodeNET.IO;
@@ -317,6 +317,31 @@ public void AnnounceList_Multiple_IsParsed(IList<string> announceList1, IList<st
317317
torrent.Trackers[1].Should().BeEquivalentTo(announceList2);
318318
}
319319

320+
[Theory]
321+
[AutoMockedData]
322+
public void AnnounceList_Multiple_StringsInsteadOfLists_IsParsed(string announce1, string announce2, string announce3)
323+
{
324+
// Arrange
325+
ParsedData = ValidSingleFileTorrentData;
326+
ParsedData[TorrentFields.AnnounceList] = new BList
327+
{
328+
new BString(announce1),
329+
new BString(announce2),
330+
new BString(announce3),
331+
};
332+
333+
// Act
334+
var parser = new TorrentParser(BencodeParser);
335+
var torrent = parser.Parse((BencodeReader)null);
336+
337+
// Assert
338+
torrent.Trackers.Should().HaveCount(1);
339+
torrent.Trackers[0].Should().HaveCount(3);
340+
torrent.Trackers[0][0].Should().Be(announce1);
341+
torrent.Trackers[0][1].Should().Be(announce2);
342+
torrent.Trackers[0][2].Should().Be(announce3);
343+
}
344+
320345
[Theory]
321346
[AutoMockedData]
322347
public void AnnounceAndAnnounceList_IsParsed(string announceUrl, IList<string> announceList1, IList<string> announceList2)

BencodeNET/Torrents/TorrentParser.cs

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,8 @@ private void FixEncodingInDictionary(BDictionary data, Encoding encoding)
347347
/// <returns>A list of list of trackers (announce URLs).</returns>
348348
protected virtual IList<IList<string>> ParseTrackers(BDictionary data, Encoding encoding)
349349
{
350+
// Specification: http://bittorrent.org/beps/bep_0012.html
351+
350352
var trackerList = new List<IList<string>>();
351353
var primary = new List<string>();
352354
trackerList.Add(primary);
@@ -358,18 +360,31 @@ protected virtual IList<IList<string>> ParseTrackers(BDictionary data, Encoding
358360
primary.Add(announce);
359361
}
360362

361-
// Get the 'announce-list' list´s
362-
var announceLists = data.Get<BList>(TorrentFields.AnnounceList)?.AsType<BList>() as IList<BList>;
363-
if (announceLists?.Any() == true)
363+
// Get the 'announce-list' list's
364+
var announceLists = data.Get<BList>(TorrentFields.AnnounceList);
365+
if (announceLists == null)
366+
return trackerList;
367+
368+
// According to the specification it should be a list of lists
369+
if (announceLists.All(x => x is BList))
364370
{
365-
// Add the first list to the primary list and remove duplicates
366-
primary.AddRange(announceLists.First().AsStrings(encoding));
367-
trackerList[0] = primary.Distinct().ToList();
371+
var lists = announceLists.AsType<BList>() as IList<BList>;
372+
if (lists.Any())
373+
{
374+
// Add the first list to the primary list and remove duplicates
375+
primary.AddRange(lists.First().AsStrings(encoding));
376+
trackerList[0] = primary.Distinct().ToList();
368377

369-
// Add the other lists to the lists of lists of announce urls
370-
trackerList.AddRange(
371-
announceLists.Skip(1)
372-
.Select(x => x.AsStrings(encoding).ToList()));
378+
// Add the other lists to the lists of lists of announce urls
379+
trackerList.AddRange(lists.Skip(1).Select(x => x.AsStrings(encoding).ToList()));
380+
}
381+
}
382+
// It's not following the specification, it's strings instead of lists
383+
else if (ParseMode == TorrentParserMode.Tolerant && announceLists.All(x => x is BString))
384+
{
385+
// Add them all to the first list
386+
primary.AddRange(announceLists.AsStrings(encoding));
387+
trackerList[0] = primary.Distinct().ToList();
373388
}
374389

375390
return trackerList;

0 commit comments

Comments
 (0)