Esempio n. 1
0
        /// <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;

            while ((reader.PeekByte() != -1) && (reader.PeekByte() != ':'))        // read in how many characters
            {
                length += (char)reader.ReadByte();                                 // the string is
            }
            if (reader.ReadByte() != ':')                                          // 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));
            }

            this.textBytes = new byte[letterCount];
            if (reader.Read(textBytes, 0, letterCount) != letterCount)
            {
                throw new BEncodingException("Couldn't decode string");
            }
        }
Esempio n. 2
0
        /// <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;
            var            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)Decode(reader);           // keys have to be BEncoded strings

                if (reader.PeekByte() == 'd')
                {
                    value = new BEncodedDictionary();
                    ((BEncodedDictionary)value).DecodeInternal(reader, key.Text.ToLower().Equals("info"));
                }
                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);
        }
Esempio n. 3
0
        private void DecodeInternal(RawReader reader, bool strictDecoding)
        {
            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(String.Format(
                                                         "Illegal BEncodedDictionary. The attributes are not ordered correctly. Old key: {0}, New key: {1}",
                                                         oldkey, key));
                    }
                }

                oldkey = key;
                value  = BEncodedValue.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");
            }
        }
Esempio n. 4
0
        static BEncodedNumber DecodeNumber(RawReader reader)
        {
            int  sign   = 1;
            long result = 0;
            int  val    = reader.ReadByte();

            if (val == '-')
            {
                sign = -1;
                val  = reader.ReadByte();
            }

            do
            {
                if (val < '0' || val > '9')
                {
                    throw new BEncodingException("Invalid number found.");
                }
                result = result * 10 + (val - '0');
            } while ((val = reader.ReadByte()) != 'e' && val != -1);

            if (val == -1)        //remove the trailing 'e'
            {
                throw new BEncodingException("Invalid data found. Aborting.");
            }

            result *= sign;
            return(result);
        }
Esempio n. 5
0
        internal static BEncodedDictionary DecodeTorrent(RawReader reader)
        {
            var torrent = new BEncodedDictionary();

            if (reader.ReadByte() != 'd')
            {
                throw new BEncodingException("Invalid data found. Aborting");  // Remove the leading 'd'
            }
            int read;

            while ((read = reader.ReadByte()) != -1 && read != 'e')
            {
                BEncodedValue value;
                var           key = (BEncodedString)Decode(reader, read); // keys have to be BEncoded strings

                if ((read = reader.ReadByte()) == 'd')
                {
                    value = DecodeDictionary(reader, InfoKey.Equals(key));
                }
                else
                {
                    value = Decode(reader, read);                      // the value is a BEncoded value
                }
                torrent.Add(key, value);
            }

            if (read != 'e')                                    // remove the trailing 'e'
            {
                throw new BEncodingException("Invalid data found. Aborting");
            }

            return(torrent);
        }
        /// <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(BEncodedValue.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");
            }
        }
Esempio n. 7
0
        internal static (BEncodedDictionary torrent, InfoHash infohash) DecodeTorrent(RawReader reader)
        {
            var torrent = new BEncodedDictionary();

            if (reader.ReadByte() != 'd')
            {
                throw new BEncodingException("Invalid data found. Aborting");  // Remove the leading 'd'
            }
            int      read;
            InfoHash infoHash = null;

            // We can save a few resizes and array copies if we pre-allocate
            // a buffer and then get the memory stream to write to it. We
            // can trivially pass the final set of bytes to the hash function then.
            byte[]       capturedDataBytes  = null;
            MemoryStream capturedDataStream = null;

            while ((read = reader.ReadByte()) != -1 && read != 'e')
            {
                BEncodedValue value;
                var           key = (BEncodedString)Decode(reader, read); // keys have to be BEncoded strings

                if ((read = reader.ReadByte()) == 'd')
                {
                    if (InfoKey.Equals(key))
                    {
                        capturedDataBytes  = new byte[reader.Length - reader.Position];
                        capturedDataStream = new MemoryStream(capturedDataBytes, true);
                        capturedDataStream.WriteByte((byte)'d');
                        reader.BeginCaptureData(capturedDataStream);
                    }

                    value = DecodeDictionary(reader, reader.StrictDecoding);

                    if (InfoKey.Equals(key))
                    {
                        reader.EndCaptureData();
                        using var hasher = SHA1.Create();
                        infoHash         = new InfoHash(hasher.ComputeHash(capturedDataBytes, 0, (int)capturedDataStream.Position));
                    }
                }
                else
                {
                    value = Decode(reader, read);                      // the value is a BEncoded value
                }
                torrent.Add(key, value);
            }

            if (read != 'e')                                    // remove the trailing 'e'
            {
                throw new BEncodingException("Invalid data found. Aborting");
            }

            return(torrent, infoHash);
        }
Esempio n. 8
0
        /// <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)
        {
            var sign = 1;

            if (reader == null)
            {
                throw new ArgumentNullException("reader");
            }

            try
            {
                if (reader.ReadByte() != 'i')                 // remove the leading 'i'
                {
                    throw new BEncodingException("Invalid data found. Aborting.");
                }

                if (reader.PeekChar() == '-')
                {
                    sign = -1;
                    reader.ReadChar();
                }

                int letter;
                while (((letter = reader.PeekChar()) != -1) && letter != 'e')
                {
                    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.");
                }

                number *= sign;
            }
            catch (BEncodingException ex)
            {
                throw new BEncodingException("Couldn't decode number", ex);
            }
            catch
            {
                throw new BEncodingException("Couldn't decode number");
            }
        }
Esempio n. 9
0
        static BEncodedString DecodeString(RawReader reader, int length)
        {
            int read;

            while ((read = reader.ReadByte()) != -1 && read != ':')
            {
                if (read < '0' || read > '9')
                {
                    throw new BEncodingException($"Invalid BEncodedString. Length was '{length}' instead of a number");
                }
                length = length * 10 + (read - '0');
            }

            if (read != ':')
            {
                throw new BEncodingException("Invalid data found. Aborting");
            }

            var bytes = new byte[length];

            if (reader.Read(bytes, 0, length) != length)
            {
                throw new BEncodingException("Couldn't decode string");
            }
            return(new BEncodedString(bytes));
        }
Esempio n. 10
0
        static BEncodedDictionary DecodeDictionary(RawReader reader, bool strictDecoding)
        {
            int            read;
            BEncodedString oldkey     = null;
            var            dictionary = new BEncodedDictionary();

            while ((read = reader.ReadByte()) != -1 && read != 'e')
            {
                BEncodedString key = DecodeString(reader, read - '0');          // 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;
                BEncodedValue value = Decode(reader);                      // the value is a BEncoded value
                dictionary.Add(key, value);
            }

            if (read != 'e')                                    // remove the trailing 'e'
            {
                throw new BEncodingException("Invalid data found. Aborting");
            }
            return(dictionary);
        }
        /// <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)BEncodedValue.Decode(reader);         // keys have to be BEncoded strings

                    if (reader.PeekChar() == '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')                                    // remove the trailing 'e'
                {
                    throw new BEncodingException("Invalid data found. Aborting");
                }

                return(torrent);
            }
            catch (Exception ex)
            {
                throw new BEncodingException("Couldn't decode dictionary", ex);
            }
        }
Esempio n. 12
0
        /// <summary>
        /// Decodes a BEncodedList from the given StreamReader
        /// </summary>
        /// <param name="reader"></param>
        internal override void DecodeInternal(RawReader reader)
        {
            if (reader.ReadByte() != 'l')                            // Remove the leading 'l'
            {
                throw new BEncodingException("Invalid data found. Aborting");
            }

            while ((reader.PeekByte() != -1) && (reader.PeekByte() != 'e'))
            {
                list.Add(BEncodedValue.Decode(reader));
            }

            if (reader.ReadByte() != 'e')                            // Remove the trailing 'e'
            {
                throw new BEncodingException("Invalid data found. Aborting");
            }
        }
Esempio n. 13
0
        static BEncodedList DecodeList(RawReader reader)
        {
            var list = new BEncodedList();
            int read;

            while ((read = reader.ReadByte()) != -1 && read != 'e')
            {
                list.Add(Decode(reader, read));
            }

            if (read != 'e')                            // Remove the trailing 'e'
            {
                throw new BEncodingException("Invalid data found. Aborting");
            }

            return(list);
        }
Esempio n. 14
0
 internal static BEncodedValue Decode(RawReader reader)
 => Decode(reader, reader.ReadByte());