Skip to content

Commit

Permalink
Add UTF-8 file name/path properties
Browse files Browse the repository at this point in the history
#47
+semver: minor
  • Loading branch information
Krusen committed Feb 28, 2020
1 parent 7e803dd commit ad7c504
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 7 deletions.
35 changes: 32 additions & 3 deletions BencodeNET.Tests/Torrents/TorrentParserTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,14 @@ public class TorrentParserTests
public TorrentParserTests()
{
BencodeParser = Substitute.For<IBencodeParser>();
BencodeParser.Parse<BDictionary>((BencodeReader) null).ReturnsForAnyArgs(x => ParsedData);
BencodeParser.Parse<BDictionary>(null).ReturnsForAnyArgs(x => ParsedData);

ValidSingleFileTorrentData = new BDictionary
{
[TorrentFields.Info] = new BDictionary
{
[TorrentInfoFields.Name] = (BString) "",
[TorrentInfoFields.NameUtf8] = (BString) "",
[TorrentInfoFields.Pieces] = (BString) "",
[TorrentInfoFields.PieceLength] = (BNumber) 0,
[TorrentInfoFields.Length] = (BNumber) 0
Expand All @@ -42,6 +43,7 @@ public TorrentParserTests()
[TorrentFields.Info] = new BDictionary
{
[TorrentInfoFields.Name] = (BString) "",
[TorrentInfoFields.NameUtf8] = (BString) "",
[TorrentInfoFields.Pieces] = (BString) "",
[TorrentInfoFields.PieceLength] = (BNumber) 0,
[TorrentInfoFields.Files] = new BList()
Expand Down Expand Up @@ -394,13 +396,14 @@ public void AnnounceAndAnnounceList_DoesNotContainDuplicatesInPrimaryList(string

[Theory]
[AutoMockedData]
public void SingleFileInfo_IsParsed(long length, string fileName, string md5Sum)
public void SingleFileInfo_IsParsed(long length, string fileName, string fileNameUtf8, string md5Sum)
{
// Arrange
ParsedData = ValidSingleFileTorrentData;
var info = ParsedData.Get<BDictionary>(TorrentFields.Info);
info[TorrentInfoFields.Length] = (BNumber) length;
info[TorrentInfoFields.Name] = (BString) fileName;
info[TorrentInfoFields.NameUtf8] = (BString) fileNameUtf8;
info[TorrentInfoFields.Md5Sum] = (BString) md5Sum;

// Act
Expand All @@ -414,12 +417,34 @@ public void SingleFileInfo_IsParsed(long length, string fileName, string md5Sum)
torrent.File.Should().NotBeNull();
torrent.File.FileSize.Should().Be(length);
torrent.File.FileName.Should().Be(fileName);
torrent.File.FileNameUtf8.Should().Be(fileNameUtf8);
torrent.File.Md5Sum.Should().Be(md5Sum);
}

[Fact]
public void SingleFileInfo_NameUtf8_IsParsedAsUtf8EncodingIndependentlyOfActualEncoding()
{
var encoding = "ISO-8859-1";
var fileName = "øæå"; // Use characters with different byte values for UTF8 and ISO-8859-1

ParsedData = ValidSingleFileTorrentData;
ParsedData[TorrentFields.Encoding] = (BString) encoding;
var info = ParsedData.Get<BDictionary>(TorrentFields.Info);
info[TorrentInfoFields.Name] = new BString(fileName, Encoding.GetEncoding(encoding));
info[TorrentInfoFields.NameUtf8] = new BString(fileName, Encoding.UTF8);

// Act
var parser = new TorrentParser(BencodeParser);
var torrent = parser.Parse((BencodeReader)null);

// Assert
torrent.File.FileName.Should().Be(fileName);
torrent.File.FileNameUtf8.Should().Be(fileName);
}

[Theory]
[AutoMockedData]
public void MultiFileInfo_IsParsed(string directoryName, long length1, IList<string> paths1, string md5Sum1, long length2, IList<string> paths2, string md5Sum2)
public void MultiFileInfo_IsParsed(string directoryName, long length1, IList<string> paths1, IList<string> paths1Utf8, string md5Sum1, long length2, IList<string> paths2, IList<string> paths2Utf8, string md5Sum2)
{
// Arrange
ParsedData = ValidMultiFileTorrentData;
Expand All @@ -431,12 +456,14 @@ public void MultiFileInfo_IsParsed(string directoryName, long length1, IList<str
{
[TorrentFilesFields.Length] = (BNumber) length1,
[TorrentFilesFields.Path] = new BList(paths1),
[TorrentFilesFields.PathUtf8] = new BList(paths1Utf8),
[TorrentFilesFields.Md5Sum] = (BString) md5Sum1
},
new BDictionary
{
[TorrentFilesFields.Length] = (BNumber) length2,
[TorrentFilesFields.Path] = new BList(paths2),
[TorrentFilesFields.PathUtf8] = new BList(paths2Utf8),
[TorrentFilesFields.Md5Sum] = (BString) md5Sum2
}
};
Expand All @@ -453,9 +480,11 @@ public void MultiFileInfo_IsParsed(string directoryName, long length1, IList<str
torrent.Files.Should().HaveCount(2);
torrent.Files[0].FileSize.Should().Be(length1);
torrent.Files[0].Path.Should().BeEquivalentTo(paths1);
torrent.Files[0].PathUtf8.Should().BeEquivalentTo(paths1Utf8);
torrent.Files[0].Md5Sum.Should().Be(md5Sum1);
torrent.Files[1].FileSize.Should().Be(length2);
torrent.Files[1].Path.Should().BeEquivalentTo(paths2);
torrent.Files[1].PathUtf8.Should().BeEquivalentTo(paths2Utf8);
torrent.Files[1].Md5Sum.Should().Be(md5Sum2);
}

Expand Down
21 changes: 20 additions & 1 deletion BencodeNET/Torrents/MultiFileInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ public class MultiFileInfo
/// <summary>
/// The file name. It just returns the last part of <see cref="Path"/>.
/// </summary>
public string FileName => Path.LastOrDefault();
public string FileName => Path?.LastOrDefault();

/// <summary>
/// The UTF-8 encoded file name. It just returns the last part of <see cref="PathUtf8"/>.
/// </summary>
public string FileNameUtf8 => PathUtf8?.LastOrDefault();

/// <summary>
/// The file size in bytes.
Expand All @@ -36,6 +41,11 @@ public class MultiFileInfo
/// </summary>
public IList<string> Path { get; set; } = new List<string>();

/// <summary>
/// A list of UTF-8 encoded file path elements.
/// </summary>
public IList<string> PathUtf8 { get; set; } = new List<string>();

/// <summary>
/// The full path of the file including file name.
/// </summary>
Expand All @@ -44,5 +54,14 @@ public string FullPath
get => string.Join(System.IO.Path.DirectorySeparatorChar.ToString(), Path);
set => Path = value.Split(new[] { System.IO.Path.DirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries);
}

/// <summary>
/// The full UTF-8 encoded path of the file including file name.
/// </summary>
public string FullPathUtf8
{
get => string.Join(System.IO.Path.DirectorySeparatorChar.ToString(), PathUtf8);
set => PathUtf8 = value.Split(new[] { System.IO.Path.DirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries);
}
}
}
9 changes: 8 additions & 1 deletion BencodeNET/Torrents/SingleFileInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
/// </remarks>
public class SingleFileInfo
{
// Name
/// <summary>
/// The file name. This is purely advisory.
/// </summary>
Expand All @@ -17,6 +16,14 @@ public class SingleFileInfo
/// </remarks>
public string FileName { get; set; }

/// <summary>
/// The UTF-8 encoded file name. This is purely advisory.
/// </summary>
/// <remarks>
/// Corresponds to the 'name.utf-8' field.
/// </remarks>
public string FileNameUtf8 { get; set; }

/// <summary>
/// The file size in bytes.
/// </summary>
Expand Down
4 changes: 4 additions & 0 deletions BencodeNET/Torrents/TorrentFields.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public static class TorrentFields
public static class TorrentInfoFields
{
public const string Name = "name";
public const string NameUtf8 = "name.utf-8";
public const string Private = "private";
public const string PieceLength = "piece length";
public const string Pieces = "pieces";
Expand All @@ -44,6 +45,7 @@ public static class TorrentInfoFields
public static readonly BString[] Keys =
{
Name,
NameUtf8,
Private,
PieceLength,
Pieces,
Expand All @@ -60,12 +62,14 @@ public static class TorrentFilesFields
{
public const string Length = "length";
public const string Path = "path";
public const string PathUtf8 = "path.utf-8";
public const string Md5Sum = "md5sum";

public static readonly BString[] Keys =
{
Length,
Path,
PathUtf8,
Md5Sum
};
}
Expand Down
6 changes: 4 additions & 2 deletions BencodeNET/Torrents/TorrentParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ protected void EnsureValidTorrentData(BDictionary data)
}
}

private static void EnsureFields(IEnumerable<string> requiredFields, BDictionary data, string message = null)
private static void EnsureFields(IList<string> requiredFields, BDictionary data, string message = null)
{
message = message ?? "Torrent is missing required field.";

Expand All @@ -190,7 +190,7 @@ private static void EnsureFields(IEnumerable<string> requiredFields, BDictionary
}
}

private static void EnsureFields(IEnumerable<string> requiredFields, IEnumerable<BDictionary> list, string message = null)
private static void EnsureFields(IList<string> requiredFields, IEnumerable<BDictionary> list, string message = null)
{
message = message ?? "Torrent is missing required field.";

Expand All @@ -217,6 +217,7 @@ protected virtual SingleFileInfo ParseSingleFileInfo(BDictionary info, Encoding
return new SingleFileInfo
{
FileName = info.Get<BString>(TorrentInfoFields.Name)?.ToString(encoding),
FileNameUtf8 = info.Get<BString>(TorrentInfoFields.NameUtf8)?.ToString(Encoding.UTF8),
FileSize = info.Get<BNumber>(TorrentInfoFields.Length),
Md5Sum = info.Get<BString>(TorrentInfoFields.Md5Sum)?.ToString(encoding)
};
Expand All @@ -243,6 +244,7 @@ protected virtual MultiFileInfoList ParseMultiFileInfo(BDictionary info, Encodin
{
FileSize = x.Get<BNumber>(TorrentFilesFields.Length),
Path = x.Get<BList>(TorrentFilesFields.Path)?.AsStrings(encoding).ToList(),
PathUtf8 = x.Get<BList>(TorrentFilesFields.PathUtf8)?.AsStrings(Encoding.UTF8).ToList(),
Md5Sum = x.Get<BString>(TorrentFilesFields.Md5Sum)?.ToString(encoding)
});

Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
### Added
- Added `FileNameUtf8` and `PathUtf8` and `FullPathUtf8` properties to `SingleFileInfo`/`MultiFileInfo`
- These properties reads from `name.utf-8` and `path.utf-8` fields.

## [3.0.1] - 2019-10-17
### Fixed
Expand Down

0 comments on commit ad7c504

Please sign in to comment.