/// <summary> /// Decodes a BEncodedString from the supplied StreamReader /// </summary> /// <param name="reader">The StreamReader containing the BEncodedString</param> internal override void DecodeInternal(RawReader reader) { reader.CannotBeNull(); int letterCount; string length = string.Empty; // read in how many characters the string is long while (reader.PeekByte() != -1 && reader.PeekByte() != ':') { length += (char)reader.ReadByte(); } if (reader.ReadByte() != ':') { throw new BEncodingException("Invalid data found. Aborting"); } if (!int.TryParse(length, out letterCount)) { throw new BEncodingException("Invalid BEncodedString. Could not read the string length."); } this.textBytes = new byte[letterCount]; if (reader.Read(this.textBytes, 0, letterCount) != letterCount) { throw new BEncodingException("Invalid BEncodedString. The string does not match the specified length."); } }
/// <summary> /// Decode BEncoded data in the given RawReader /// </summary> /// <param name="reader">The RawReader containing the BEncoded data</param> /// <returns>BEncodedValue containing the data that was in the stream</returns> public static BEncodedValue Decode(RawReader reader) { reader.CannotBeNull(); BEncodedValue data; int peekByte = reader.PeekByte(); if (peekByte == 'i') { // integer data = new BEncodedNumber(); data.DecodeInternal(reader); return(data); } else if (peekByte == 'd') { // dictionary data = new BEncodedDictionary(); data.DecodeInternal(reader); return(data); } else if (peekByte == 'l') { // list data = new BEncodedList(); data.DecodeInternal(reader); return(data); } else if (peekByte == '0' || peekByte == '1' || peekByte == '2' || peekByte == '3' || peekByte == '4' || peekByte == '5' || peekByte == '6' || peekByte == '7' || peekByte == '8' || peekByte == '9') { // string data = new BEncodedString(); data.DecodeInternal(reader); return(data); } else { throw new BEncodingException("Could not find what value to decode."); } }
/// <summary> /// Special decoding method for torrent files - allows dictionary attributes to be out of order for the /// overall torrent file, but imposes strict rules on the info dictionary. /// </summary> /// <param name="reader">The reader.</param> /// <value> /// The BEncoded dictionary. /// </value> public static BEncodedDictionary DecodeTorrent(RawReader reader) { reader.CannotBeNull(); BEncodedString key = null; BEncodedValue value = null; BEncodedDictionary torrent = new BEncodedDictionary(); if (reader.ReadByte() != 'd') { throw new BEncodingException("Invalid data found. Aborting"); // Remove the leading 'd' } while (reader.PeekByte() != -1 && reader.PeekByte() != 'e') { key = (BEncodedString)BEncodedValue.Decode(reader); // keys have to be BEncoded strings if (reader.PeekByte() == 'd') { value = new BEncodedDictionary(); if (key.Text.ToLower().Equals("info")) { ((BEncodedDictionary)value).DecodeInternal(reader, true); } else { ((BEncodedDictionary)value).DecodeInternal(reader, false); } } else { value = BEncodedValue.Decode(reader); // the value is a BEncoded value } torrent.dictionary.Add(key, value); } if (reader.ReadByte() != 'e') { throw new BEncodingException("Invalid data found. Aborting"); } return(torrent); }
/// <summary> /// Decodes a BEncodedList from the given StreamReader /// </summary> /// <param name="reader">The reader.</param> internal override void DecodeInternal(RawReader reader) { reader.CannotBeNull(); if (reader.ReadByte() != 'l') { throw new BEncodingException("Invalid data found. Aborting"); } while (reader.PeekByte() != -1 && reader.PeekByte() != 'e') { this.list.Add(BEncodedValue.Decode(reader)); } if (reader.ReadByte() != 'e') { throw new BEncodingException("Invalid data found. Aborting"); } }
/// <summary> /// Decodes a BEncoded number from the supplied RawReader /// </summary> /// <param name="reader">RawReader containing a BEncoded Number</param> internal override void DecodeInternal(RawReader reader) { reader.CannotBeNull(); int sign = 1; int letter; if (reader.ReadByte() != 'i') { throw new BEncodingException("Invalid data found. Aborting."); } if (reader.PeekByte() == '-') { sign = -1; reader.ReadByte(); } while ((letter = reader.PeekByte()) != -1 && letter != 'e') { if (letter < '0' || letter > '9') { throw new BEncodingException("Invalid number found."); } this.number = (this.number * 10) + (letter - '0'); reader.ReadByte(); } if (reader.ReadByte() != 'e') { throw new BEncodingException("Invalid data found. Aborting."); } this.number *= sign; }
/// <summary> /// Decodes the internal. /// </summary> /// <param name="reader">The reader.</param> /// <param name="strictDecoding">if set to <c>true</c> [strict decoding].</param> /// <exception cref="TorrentClient.BEncoding.BEncodingException"> /// Invalid data found. Aborting /// or /// or /// Invalid data found. Aborting /// </exception> private void DecodeInternal(RawReader reader, bool strictDecoding) { reader.CannotBeNull(); BEncodedString key = null; BEncodedValue value = null; BEncodedString oldkey = null; if (reader.ReadByte() != 'd') { throw new BEncodingException("Invalid data found. Aborting"); // Remove the leading 'd' } while (reader.PeekByte() != -1 && reader.PeekByte() != 'e') { key = (BEncodedString)BEncodedValue.Decode(reader); // keys have to be BEncoded strings if (oldkey != null && oldkey.CompareTo(key) > 0) { if (strictDecoding) { throw new BEncodingException($"Illegal BEncodedDictionary. The attributes are not ordered correctly. Old key: {oldkey}, New key: {key}"); } } oldkey = key; value = BEncodedValue.Decode(reader); // the value is a BEncoded value this.dictionary.Add(key, value); } if (reader.ReadByte() != 'e') { throw new BEncodingException("Invalid data found. Aborting"); } }
/// <summary> /// Decodes the specified reader. /// </summary> /// <typeparam name="T">The BEncoded value type.</typeparam> /// <param name="reader">The reader.</param> /// <returns> /// The BEncoded value. /// </returns> public static T Decode <T>(RawReader reader) where T : BEncodedValue { reader.CannotBeNull(); return((T)BEncodedValue.Decode(reader)); }
/// <summary> /// Decodes the internal. /// </summary> /// <param name="reader">The reader.</param> internal override void DecodeInternal(RawReader reader) { reader.CannotBeNull(); this.DecodeInternal(reader, reader.StrictDecoding); }