示例#1
0
		public void SerializationUnsafeRoundtrip ()
		{
			Stream s = GetSerializedStream ();
			BinaryFormatter bf = new BinaryFormatter ();
			SerializationTest clone = (SerializationTest) bf.UnsafeDeserialize (s, null);
			Assert.AreEqual (Int32.MinValue, clone.Integer, "Integer");
			Assert.IsFalse (clone.Boolean, "Boolean");
		}
示例#2
0
        /// <summary>
        /// Deserializes a Document from a stream.
        /// </summary>
        /// <param name="stream">The stream to deserialize from. This stream must be seekable.</param>
        /// <returns>The Document that was stored in stream.</returns>
        /// <remarks>
        /// This is the only supported way to deserialize a Document instance from disk.
        /// </remarks>
        public static Document FromStream(Stream stream)
        {
            long oldPosition = stream.Position;
            bool pdn21Format = true;

            // Version 2.1+ file format:
            //   Starts with bytes as defined by MagicBytes
            //   Next three bytes are 24-bit unsigned int 'N' (first byte is low-word, second byte is middle-word, third byte is high word)
            //   The next N bytes are a string, this is the document header (it is XML, UTF-8 encoded)
            //       Important: 'N' indicates a byte count, not a character count. 'N' bytes may result in less than 'N' characters,
            //                  depending on how the characters decode as per UTF8
            //   If the next 2 bytes are 0x00, 0x01: This signifies that non-compressed .NET serialized data follows.
            //   If the next 2 bytes are 0x1f, 0x8b: This signifies the start of the gzip compressed .NET serialized data
            //
            // Version 2.0 and previous file format:
            //   Starts with 0x1f, 0x8b: this signifies the start of the gzip compressed .NET serialized data.

            // Read in the 'magic' bytes
            for (int i = 0; i < MagicBytes.Length; ++i)
            {
                int theByte = stream.ReadByte();

                if (theByte == -1)
                {
                    throw new EndOfStreamException();
                }

                if (theByte != MagicBytes[i])
                {
                    pdn21Format = false;
                    break;
                }
            }

            // Read in the header if we found the 'magic' bytes identifying a PDN 2.1 file
            XmlDocument headerXml = null;
            if (pdn21Format)
            {
                // This is a Paint.NET v2.1+ file.
                int low = stream.ReadByte();

                if (low == -1)
                {
                    throw new EndOfStreamException();
                }

                int mid = stream.ReadByte();

                if (mid == -1)
                {
                    throw new EndOfStreamException();
                }

                int high = stream.ReadByte();

                if (high == -1)
                {
                    throw new EndOfStreamException();
                }

                int byteCount = low + (mid << 8) + (high << 16);
                byte[] bytes = new byte[byteCount];
                int bytesRead = Utility.ReadFromStream(stream, bytes, 0, byteCount);

                if (bytesRead != byteCount)
                {
                    throw new EndOfStreamException("expected " + byteCount + " bytes, but only got " + bytesRead);
                }

                string xml = Encoding.UTF8.GetString(bytes);
                headerXml = new XmlDocument();
                headerXml.LoadXml(xml);
            }
            else
            {
                stream.Position = oldPosition; // rewind and try as v2.0-or-earlier file
            }

            // Start reading the data section of the file. Determine if it's gzip or regular
            long oldPosition2 = stream.Position;
            int first = stream.ReadByte();

            if (first == -1)
            {
                throw new EndOfStreamException();
            }

            int second = stream.ReadByte();

            if (second == -1)
            {
                throw new EndOfStreamException();
            }

            Document document;
            object docObject;
            BinaryFormatter formatter = new BinaryFormatter();
            SerializationFallbackBinder sfb = new SerializationFallbackBinder();

            sfb.AddAssembly(Assembly.GetExecutingAssembly());     // first try PaintDotNet.Data.dll
            sfb.AddAssembly(typeof(Utility).Assembly);            // second, try PdnLib.dll
            sfb.AddAssembly(typeof(SystemLayer.Memory).Assembly); // third, try PaintDotNet.SystemLayer.dll
            formatter.Binder = sfb;

            if (first == 0 && second == 1)
            {
                DeferredFormatter deferred = new DeferredFormatter();
                formatter.Context = new StreamingContext(formatter.Context.State, deferred);
                docObject = formatter.UnsafeDeserialize(stream, null);
                deferred.FinishDeserialization(stream);
            }
            else if (first == 0x1f && second == 0x8b)
            {
                stream.Position = oldPosition2; // rewind to the start of 0x1f, 0x8b
                GZipStream gZipStream = new GZipStream(stream, CompressionMode.Decompress, true);
                docObject = formatter.UnsafeDeserialize(gZipStream, null);
            }
            else
            {
                throw new FormatException("file is not a valid Paint.NET document");
            }

            document = (Document)docObject;
            document.Dirty = true;
            document.headerXml = headerXml;
            document.Invalidate();
            return document;
        }
		public void UnsafeDeserialization_PermitOnly_SerializationFormatter ()
		{
			BinaryFormatter bf = new BinaryFormatter ();
			SerializationTest clone = (SerializationTest) bf.UnsafeDeserialize (stream, null);
			Assert.AreEqual (Int32.MinValue, clone.Integer, "Integer");
			Assert.IsFalse (clone.Boolean, "Boolean");
		}