|
4 | 4 | using System.IO; |
5 | 5 | using System.Linq; |
6 | 6 | using System.Text; |
| 7 | +using System.Text.RegularExpressions; |
7 | 8 | using BencodeNET.Exceptions; |
8 | 9 | using BencodeNET.IO; |
9 | 10 |
|
@@ -128,9 +129,39 @@ public virtual string DisplayName |
128 | 129 | // TODO: Split into list of 20-byte hashes and rename to something appropriate? |
129 | 130 | /// <summary> |
130 | 131 | /// A concatenation of all 20-byte SHA1 hash values (one for each piece). |
| 132 | + /// Use <see cref="PiecesAsHexString"/> to get/set this value as a hex string instead. |
131 | 133 | /// </summary> |
132 | 134 | public virtual byte[] Pieces { get; set; } |
133 | 135 |
|
| 136 | + /// <summary> |
| 137 | + /// Gets or sets <see cref="Pieces"/> from/to a hex string (without dashes), e.g. 1C115D26444AEF2A5E936133DCF8789A552BBE9F[...]. |
| 138 | + /// The length of the string must be a multiple of 40. |
| 139 | + /// </summary> |
| 140 | + public virtual string PiecesAsHexString |
| 141 | + { |
| 142 | + get |
| 143 | + { |
| 144 | + return BitConverter.ToString(Pieces).Replace("-", ""); |
| 145 | + } |
| 146 | + set |
| 147 | + { |
| 148 | + if (value?.Length % 40 != 0) |
| 149 | + throw new ArgumentException("Value length must be a multiple of 40 (20 bytes as hex)."); |
| 150 | + |
| 151 | + if (Regex.IsMatch(value, "[^0-9A-F]")) |
| 152 | + throw new ArgumentException("Value must only contain hex characters (0-9 and A-F) and only uppercase."); |
| 153 | + |
| 154 | + var bytes = new byte[value.Length/2]; |
| 155 | + for (var i = 0; i < bytes.Length; i++) |
| 156 | + { |
| 157 | + var str = $"{value[i*2]}{value[i*2+1]}"; |
| 158 | + bytes[i] = Convert.ToByte(str, 16); |
| 159 | + } |
| 160 | + |
| 161 | + Pieces = bytes; |
| 162 | + } |
| 163 | + } |
| 164 | + |
134 | 165 | /// <summary> |
135 | 166 | /// [optional] If set to true clients must only publish it's presence to the defined trackers. |
136 | 167 | /// Mainly used for private trackers which don't allow PEX, DHT etc. |
@@ -209,7 +240,7 @@ protected virtual BDictionary CreateInfoDictionary(Encoding encoding) |
209 | 240 | if (PieceSize > 0) |
210 | 241 | info[TorrentInfoFields.PieceLength] = (BNumber) PieceSize; |
211 | 242 |
|
212 | | - if (Pieces != null) |
| 243 | + if (Pieces?.Length > 0) |
213 | 244 | info[TorrentInfoFields.Pieces] = new BString(Pieces, encoding); |
214 | 245 |
|
215 | 246 | if (IsPrivate) |
|
0 commit comments