byte [] CalcPiecesHash(List <TorrentFile> files, IPieceWriter writer, CancellationToken token) { int bufferRead = 0; long fileRead = 0; long overallRead = 0; MD5 md5Hasher = null; var shaHasher = HashAlgoFactory.Create <SHA1> (); var torrentHashes = new List <byte> (); var overallTotal = files.Sum(t => t.Length); var buffer = new byte [PieceLength]; if (StoreMD5) { md5Hasher = HashAlgoFactory.Create <MD5> (); } try { foreach (TorrentFile file in files) { fileRead = 0; md5Hasher?.Initialize(); while (fileRead < file.Length) { int toRead = (int)Math.Min(buffer.Length - bufferRead, file.Length - fileRead); int read = writer.Read(file, fileRead, buffer, bufferRead, toRead); token.ThrowIfCancellationRequested(); md5Hasher?.TransformBlock(buffer, bufferRead, read, buffer, bufferRead); shaHasher.TransformBlock(buffer, bufferRead, read, buffer, bufferRead); bufferRead += read; fileRead += read; overallRead += read; if (bufferRead == buffer.Length) { bufferRead = 0; shaHasher.TransformFinalBlock(buffer, 0, 0); torrentHashes.AddRange(shaHasher.Hash); shaHasher.Initialize(); } Hashed?.InvokeAsync(this, new TorrentCreatorEventArgs(file.Path, fileRead, file.Length, overallRead, overallTotal)); } md5Hasher?.TransformFinalBlock(buffer, 0, 0); md5Hasher?.Initialize(); file.MD5 = md5Hasher?.Hash; } if (bufferRead > 0) { shaHasher.TransformFinalBlock(buffer, 0, 0); torrentHashes.AddRange(shaHasher.Hash); } } finally { shaHasher.Dispose(); md5Hasher?.Dispose(); } return(torrentHashes.ToArray()); }
protected void LoadInternal(BEncodedDictionary torrentInformation) { Check.TorrentInformation(torrentInformation); originalDictionary = torrentInformation; torrentPath = ""; try { foreach (KeyValuePair <BEncodedString, BEncodedValue> keypair in torrentInformation) { switch (keypair.Key.Text) { case ("announce"): // Ignore this if we have an announce-list if (torrentInformation.ContainsKey("announce-list")) { break; } announceUrls.Add(new RawTrackerTier()); announceUrls[0].Add(keypair.Value.ToString()); break; case ("creation date"): try { try { creationDate = creationDate.AddSeconds(long.Parse(keypair.Value.ToString())); } catch (Exception e) { if (e is ArgumentOutOfRangeException) { creationDate = creationDate.AddMilliseconds(long.Parse(keypair.Value.ToString())); } else { throw; } } } catch (Exception e) { if (e is ArgumentOutOfRangeException) { throw new BEncodingException("Argument out of range exception when adding seconds to creation date.", e); } else if (e is FormatException) { throw new BEncodingException(String.Format("Could not parse {0} into a number", keypair.Value), e); } else { throw; } } break; case ("nodes"): nodes = (BEncodedList)keypair.Value; break; case ("comment.utf-8"): if (keypair.Value.ToString().Length != 0) { comment = keypair.Value.ToString(); // Always take the UTF-8 version } break; // even if there's an existing value case ("comment"): if (String.IsNullOrEmpty(comment)) { comment = keypair.Value.ToString(); } break; case ("publisher-url.utf-8"): // Always take the UTF-8 version publisherUrl = keypair.Value.ToString(); // even if there's an existing value break; case ("publisher-url"): if (String.IsNullOrEmpty(publisherUrl)) { publisherUrl = keypair.Value.ToString(); } break; case ("azureus_properties"): azureusProperties = keypair.Value; break; case ("created by"): createdBy = keypair.Value.ToString(); break; case ("encoding"): encoding = keypair.Value.ToString(); break; case ("info"): using (SHA1 s = HashAlgoFactory.Create <SHA1>()) infoHash = new InfoHash(s.ComputeHash(keypair.Value.Encode())); ProcessInfo(((BEncodedDictionary)keypair.Value)); break; case ("name"): // Handled elsewhere break; case ("announce-list"): if (keypair.Value is BEncodedString) { break; } BEncodedList announces = (BEncodedList)keypair.Value; for (int j = 0; j < announces.Count; j++) { if (announces[j] is BEncodedList) { BEncodedList bencodedTier = (BEncodedList)announces[j]; List <string> tier = new List <string>(bencodedTier.Count); for (int k = 0; k < bencodedTier.Count; k++) { tier.Add(bencodedTier[k].ToString()); } Toolbox.Randomize <string>(tier); RawTrackerTier collection = new RawTrackerTier(); for (int k = 0; k < tier.Count; k++) { collection.Add(tier[k]); } if (collection.Count != 0) { announceUrls.Add(collection); } } else { throw new BEncodingException(String.Format("Non-BEncodedList found in announce-list (found {0})", announces[j].GetType())); } } break; case ("httpseeds"): // This form of web-seeding is not supported. break; case ("url-list"): if (keypair.Value is BEncodedString) { getRightHttpSeeds.Add(((BEncodedString)keypair.Value).Text); } else if (keypair.Value is BEncodedList) { foreach (BEncodedString str in (BEncodedList)keypair.Value) { GetRightHttpSeeds.Add(str.Text); } } break; default: break; } } } catch (Exception e) { if (e is BEncodingException) { throw; } else { throw new BEncodingException("", e); } } }
void LoadInternal(BEncodedDictionary torrentInformation) { Check.TorrentInformation(torrentInformation); AnnounceUrls = new List <IList <string> > ().AsReadOnly(); foreach (KeyValuePair <BEncodedString, BEncodedValue> keypair in torrentInformation) { switch (keypair.Key.Text) { case ("announce"): // Ignore this if we have an announce-list if (torrentInformation.ContainsKey("announce-list")) { break; } AnnounceUrls = new List <IList <string> > { new List <string> { keypair.Value.ToString() }.AsReadOnly() }.AsReadOnly(); break; case ("creation date"): try { try { CreationDate = UnixEpoch.AddSeconds(long.Parse(keypair.Value.ToString())); } catch (Exception e) { if (e is ArgumentOutOfRangeException) { CreationDate = UnixEpoch.AddMilliseconds(long.Parse(keypair.Value.ToString())); } else { throw; } } } catch (Exception e) { if (e is ArgumentOutOfRangeException) { throw new BEncodingException("Argument out of range exception when adding seconds to creation date.", e); } else if (e is FormatException) { throw new BEncodingException($"Could not parse {keypair.Value} into a number", e); } else { throw; } } break; case ("nodes"): if (keypair.Value is BEncodedList list) { Nodes = list; } break; case ("comment.utf-8"): if (keypair.Value.ToString().Length != 0) { Comment = keypair.Value.ToString(); // Always take the UTF-8 version } break; // even if there's an existing value case ("comment"): if (string.IsNullOrEmpty(Comment)) { Comment = keypair.Value.ToString(); } break; case ("publisher-url.utf-8"): // Always take the UTF-8 version PublisherUrl = keypair.Value.ToString(); // even if there's an existing value break; case ("publisher-url"): if (string.IsNullOrEmpty(PublisherUrl)) { PublisherUrl = keypair.Value.ToString(); } break; case ("created by"): CreatedBy = keypair.Value.ToString(); break; case ("encoding"): Encoding = keypair.Value.ToString(); break; case ("info"): using (SHA1 s = HashAlgoFactory.SHA1()) InfoHash = new InfoHash(s.ComputeHash(keypair.Value.Encode())); ProcessInfo(((BEncodedDictionary)keypair.Value)); break; case ("name"): // Handled elsewhere break; case ("announce-list"): if (keypair.Value is BEncodedString) { break; } var result = new List <IList <string> > (); var announces = (BEncodedList)keypair.Value; for (int j = 0; j < announces.Count; j++) { if (announces[j] is BEncodedList bencodedTier) { var tier = new List <string> (bencodedTier.Count); for (int k = 0; k < bencodedTier.Count; k++) { tier.Add(bencodedTier[k].ToString()); } Toolbox.Randomize(tier); var resultTier = new List <string> (); for (int k = 0; k < tier.Count; k++) { resultTier.Add(tier[k]); } if (resultTier.Count != 0) { result.Add(tier.AsReadOnly()); } } else { throw new BEncodingException( $"Non-BEncodedList found in announce-list (found {announces[j].GetType ()})"); } } if (result.Count > 0) { AnnounceUrls = result.AsReadOnly(); } break; case ("httpseeds"): // This form of web-seeding is not supported. break; case ("url-list"): if (keypair.Value is BEncodedString httpSeedString) { HttpSeeds.Add(httpSeedString.Text); } else if (keypair.Value is BEncodedList httpSeedList) { foreach (BEncodedString str in httpSeedList) { HttpSeeds.Add(str.Text); } } break; default: break; } } }