/// <summary> /// Decodes a BEncodedList from the given StreamReader /// </summary> /// <param name="reader"></param> internal override void DecodeInternal(RawReader reader) { try { if (reader.ReadByte() != 'l') // Remove the leading 'l' { throw new BEncodingException("Invalid data found. Aborting"); } while (reader.PeekChar() != -1 && (char)reader.PeekChar() != 'e') { list.Add(Decode(reader)); } if (reader.ReadByte() != 'e') // Remove the trailing 'e' { throw new BEncodingException("Invalid data found. Aborting"); } } catch (BEncodingException ex) { throw new BEncodingException("Couldn't decode list", ex); } catch { throw new BEncodingException("Couldn't decode list"); } }
/// <summary> /// Decodes a BEncodedString from the supplied StreamReader /// </summary> /// <param name="reader">The StreamReader containing the BEncodedString</param> internal override void DecodeInternal(RawReader reader) { if (reader == null) { throw new ArgumentNullException("reader"); } int letterCount; string length = string.Empty; try { while ((reader.PeekChar() != -1) && (reader.PeekChar() != ':')) // read in how many characters { length += (char)reader.ReadChar(); // the string is } if (reader.ReadChar() != ':') // remove the ':' { throw new BEncodingException("Invalid data found. Aborting"); } if (!int.TryParse(length, out letterCount)) { throw new BEncodingException(string.Format("Invalid BEncodedString. Length was '{0}' instead of a number", length)); } textBytes = new byte[letterCount]; if (reader.Read(textBytes, 0, letterCount) != letterCount) { throw new BEncodingException("Couldn't decode string"); } } catch (Exception ex) { if (ex is BEncodingException) { throw; } else { throw new BEncodingException("Couldn't decode string", ex); } } }
private void DecodeInternal(RawReader reader, bool strictDecoding) { BEncodedString key = null; BEncodedValue value = null; BEncodedString oldkey = null; try { if (reader.ReadByte() != 'd') { throw new BEncodingException("Invalid data found. Aborting"); // Remove the leading 'd' } while (reader.PeekChar() != -1 && (char)reader.PeekChar() != 'e') { key = (BEncodedString)Decode(reader); // keys have to be BEncoded strings if (oldkey != null && oldkey.CompareTo(key) > 0) { if (strictDecoding) { throw new BEncodingException(string.Format( "Illegal BEncodedDictionary. The attributes are not ordered correctly. Old key: {0}, New key: {1}", oldkey, key)); } } oldkey = key; value = Decode(reader); // the value is a BEncoded value _dictionary.Add(key, value); } if (reader.ReadByte() != 'e') // remove the trailing 'e' { throw new BEncodingException("Invalid data found. Aborting"); } } catch (Exception ex) { throw new BEncodingException("Couldn't decode dictionary", ex); } }
/// <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> /// <returns></returns> public static BEncodedDictionary DecodeTorrent(RawReader reader) { BEncodedString key = null; BEncodedValue value = null; BEncodedDictionary torrent = new BEncodedDictionary(); try { if (reader.ReadByte() != 'd') { throw new BEncodingException("Invalid data found. Aborting"); // Remove the leading 'd' } while (reader.PeekChar() != -1 && (char)reader.PeekChar() != 'e') { key = (BEncodedString)Decode(reader); // keys have to be BEncoded strings if (reader.PeekChar() == 'd') { value = new BEncodedDictionary(); bool strictDecoding = key.Text.ToLower().Equals("info"); ((BEncodedDictionary)value).DecodeInternal(reader, strictDecoding); } else { value = Decode(reader); // the value is a BEncoded value } torrent._dictionary.Add(key, value); } if (reader.ReadByte() != 'e') // remove the trailing 'e' { throw new BEncodingException("Invalid data found. Aborting"); } return(torrent); } catch (Exception ex) { throw new BEncodingException("Couldn't decode dictionary", ex); } }
/// <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) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } BEncodedValue data; switch ((char)reader.PeekChar()) { case 'i': // Integer data = new BEncodedNumber(); break; case 'd': // Dictionary data = new BEncodedDictionary(); break; case 'l': // List data = new BEncodedList(); break; case '1': // String case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '0': data = new BEncodedString(); break; default: throw new BEncodingException("Could not find what value to decode"); } data.DecodeInternal(reader); return(data); }
/// <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) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } try { if (reader.ReadByte() != 'i') // remove the leading 'i' { throw new BEncodingException("Invalid data found. Aborting."); } int letter; while ((letter = reader.PeekChar()) != -1 && letter != 'e') { // TODO: Maybe should completely use a nuget package for BEncode. //if (letter < '0' || letter > '9') //throw new BEncodingException("Invalid number found."); Number = Number * 10 + (letter - '0'); reader.ReadChar(); } if (reader.ReadByte() != 'e') //remove the trailing 'e' { throw new BEncodingException("Invalid data found. Aborting."); } } catch (BEncodingException ex) { throw new BEncodingException("Couldn't decode number", ex); } catch { throw new BEncodingException("Couldn't decode number"); } }