public SaveConfigToken GetLastSaveConfigToken() { Type ourType = this.GetType(); string savedTokenName = "SaveConfigToken." + ourType.Namespace + "." + ourType.Name + ".BinaryFormatter"; string savedToken = Settings.CurrentUser.GetString(savedTokenName, null); SaveConfigToken saveConfigToken = null; if (savedToken != null) { try { byte[] bytes = Convert.FromBase64String(savedToken); MemoryStream ms = new MemoryStream(bytes); BinaryFormatter formatter = new BinaryFormatter(); DeferredFormatter deferred = new DeferredFormatter(); StreamingContext streamingContext = new StreamingContext(formatter.Context.State, deferred); formatter.Context = streamingContext; SerializationFallbackBinder sfb = new SerializationFallbackBinder(); sfb.AddAssembly(this.GetType().Assembly); sfb.AddAssembly(typeof(FileType).Assembly); formatter.Binder = sfb; object obj = formatter.Deserialize(ms); deferred.FinishDeserialization(ms); ms.Close(); ms = null; //SaveConfigToken sct = new SaveConfigToken(); //saveConfigToken = (SaveConfigToken)obj; saveConfigToken = GetSaveConfigTokenFromSerializablePortion(obj); } catch (Exception) { // Ignore erros and revert to default saveConfigToken = null; } } if (saveConfigToken == null) { saveConfigToken = CreateDefaultSaveConfigToken(); } return(saveConfigToken); }
/// <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 PaintDotNet.Core.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); }