/// <summary>
        /// Deflate the token
        /// </summary>
        /// <param name="destination">Stream to deflate token to</param>
        public override void Deflate(Stream destination)
        {
            // Calculate total length by adding strings
            uint totalPacketLength = (uint)(FixedPacketLength
                                            + (uint)(string.IsNullOrEmpty(HostName) ? 0 : HostName.Length * 2)                     // HostName
                                            + (uint)(string.IsNullOrEmpty(UserID) ? 0 : UserID.Length * 2)                         // UserID
                                            + (uint)(string.IsNullOrEmpty(Password) ? 0 : Password.Length * 2)                     // Password
                                            + (uint)(string.IsNullOrEmpty(ApplicationName) ? 0 : ApplicationName.Length * 2)       // ApplicationName
                                            + (uint)(string.IsNullOrEmpty(ServerName) ? 0 : ServerName.Length * 2)                 // ServerName
                                            + (uint)(string.IsNullOrEmpty(LibraryName) ? 0 : LibraryName.Length * 2)               // LibraryName
                                            + (uint)(string.IsNullOrEmpty(Language) ? 0 : Language.Length * 2)                     // Language
                                            + (uint)(string.IsNullOrEmpty(Database) ? 0 : Database.Length * 2)                     // Database
                                            + (uint)(string.IsNullOrEmpty(AttachDatabaseFile) ? 0 : AttachDatabaseFile.Length * 2) // AttachDatabaseFile
                                            + (uint)(string.IsNullOrEmpty(ChangePassword) ? 0 : ChangePassword.Length * 2)         // ChangePassword
                                            + (uint)(SSPI == null ? 0 : SSPI.Length)                                               // SSPI
                                            + 0);                                                                                  // Feature extension

            MemoryStream featureExtension = null;

            // Check if we have a feature extension
            if (FeatureExt != null)
            {
                // Allocate feature extension block
                featureExtension = new MemoryStream();

                // Serialize feature extension
                FeatureExt.Deflate(featureExtension);

                // Update total lentgh
                totalPacketLength += (uint)(sizeof(uint) /* Offset of feature extension data */ + featureExtension.Length /* feature extension itself*/);
            }

            // Write packet length
            TDSUtilities.WriteUInt(destination, totalPacketLength);

            // Compile TDS version
            uint tdsVersion = Convert.ToUInt32(string.Format("{0:X}", Math.Max(TDSVersion.Major, 0)) + string.Format("{0:X}", Math.Max(TDSVersion.Minor, 0)) + string.Format("{0:X2}", Math.Max(TDSVersion.Build, 0)) + string.Format("{0:X4}", Math.Max(TDSVersion.Revision, 0)), 16);

            // Write TDS version
            TDSUtilities.WriteUInt(destination, tdsVersion);

            // Write packet length
            TDSUtilities.WriteUInt(destination, PacketSize);

            // Write client program version
            TDSUtilities.WriteUInt(destination, ClientProgramVersion);

            // Write client program identifier
            TDSUtilities.WriteUInt(destination, ClientPID);

            // Write connection identifier
            TDSUtilities.WriteUInt(destination, ConnectionID);

            // Write the first optional flags
            destination.WriteByte(OptionalFlags1.ToByte());

            // Write the second optional flags
            destination.WriteByte(OptionalFlags2.ToByte());

            // Instantiate type flags
            destination.WriteByte(TypeFlags.ToByte());

            // Write the third optional flags
            destination.WriteByte(OptionalFlags3.ToByte());

            // Write client time zone
            TDSUtilities.WriteInt(destination, ClientTimeZone);

            // Write client locale identifier
            TDSUtilities.WriteUInt(destination, ClientLCID);

            // Prepare a collection of property values that will be set later
            IList <TDSLogin7TokenOffsetProperty> variableProperties = new List <TDSLogin7TokenOffsetProperty>();

            // Write client host name
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("HostName"), FixedPacketLength, (ushort)(string.IsNullOrEmpty(HostName) ? 0 : HostName.Length)));
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Position);
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Length);

            // Write user name and password
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("UserID"), (ushort)(variableProperties.Last().Position + variableProperties.Last().Length * 2), (ushort)(string.IsNullOrEmpty(UserID) ? 0 : UserID.Length)));
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Position);
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Length);

            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("Password"), (ushort)(variableProperties.Last().Position + variableProperties.Last().Length * 2), (ushort)(string.IsNullOrEmpty(Password) ? 0 : Password.Length)));
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Position);
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Length);

            // Write application name
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("ApplicationName"), (ushort)(variableProperties.Last().Position + variableProperties.Last().Length * 2), (ushort)(string.IsNullOrEmpty(ApplicationName) ? 0 : ApplicationName.Length)));
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Position);
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Length);

            // Write server name
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("ServerName"), (ushort)(variableProperties.Last().Position + variableProperties.Last().Length * 2), (ushort)(string.IsNullOrEmpty(ServerName) ? 0 : ServerName.Length)));
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Position);
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Length);

            // Check if we have a feature extension block
            if (FeatureExt != null)
            {
                // Write the offset of the feature extension offset (pointer to pointer)
                variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("FeatureExt"), (ushort)(variableProperties.Last().Position + variableProperties.Last().Length * 2), sizeof(uint) / 2, true)); // Should be 4 bytes, devided by 2 because the next guy multiplies by 2
                TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Position);
                TDSUtilities.WriteUShort(destination, (ushort)(variableProperties.Last().Length * 2));                                                                                                                      // Compensate for division by 2 above
            }
            else
            {
                // Skip unused
                TDSUtilities.WriteUShort(destination, 0);
                TDSUtilities.WriteUShort(destination, 0);
            }

            // Write client library name
            // We do not need to account for skipped unused bytes here because they're already accounted in fixedPacketLength
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("LibraryName"), (ushort)(variableProperties.Last().Position + variableProperties.Last().Length * 2), (ushort)(string.IsNullOrEmpty(LibraryName) ? 0 : LibraryName.Length)));
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Position);
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Length);

            // Write language
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("Language"), (ushort)(variableProperties.Last().Position + variableProperties.Last().Length * 2), (ushort)(string.IsNullOrEmpty(Language) ? 0 : Language.Length)));
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Position);
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Length);

            // Write database
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("Database"), (ushort)(variableProperties.Last().Position + variableProperties.Last().Length * 2), (ushort)(string.IsNullOrEmpty(Database) ? 0 : Database.Length)));
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Position);
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Length);

            // Check if client is defined
            if (ClientID == null)
            {
                // Allocate empty identifier
                ClientID = new byte[6];
            }

            // Write unique client identifier
            destination.Write(ClientID, 0, 6);

            // Write SSPI
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("SSPI"), (ushort)(variableProperties.Last().Position + variableProperties.Last().Length * 2), (ushort)(SSPI == null ? 0 : SSPI.Length)));
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Position);
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Length);

            // Write database file to be attached. NOTE, "variableProperties.Last().Length" without " * 2" because the preceeding buffer isn't string
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("AttachDatabaseFile"), (ushort)(variableProperties.Last().Position + variableProperties.Last().Length), (ushort)(string.IsNullOrEmpty(AttachDatabaseFile) ? 0 : AttachDatabaseFile.Length)));
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Position);
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Length);

            // Write password change
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("ChangePassword"), (ushort)(variableProperties.Last().Position + variableProperties.Last().Length * 2), (ushort)(string.IsNullOrEmpty(ChangePassword) ? 0 : ChangePassword.Length)));
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Position);
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Length);

            // Skip long SSPI
            TDSUtilities.WriteUInt(destination, 0);

            // We will be changing collection as we go and serialize everything. As such we can't use foreach and iterator.
            int iCurrentProperty = 0;

            // Iterate through the collection
            while (iCurrentProperty < variableProperties.Count)
            {
                // Get current property by index
                TDSLogin7TokenOffsetProperty property = variableProperties[iCurrentProperty];

                // Check if length is positive
                if (property.Length == 0)
                {
                    // Move to the next property
                    iCurrentProperty++;
                    continue;
                }

                // Check special properties
                if (property.Property.Name == "Password" || property.Property.Name == "ChangePassword")
                {
                    // Write encrypted string value
                    TDSUtilities.WritePasswordString(destination, (string)property.Property.GetValue(this, null));
                }
                else if (property.Property.Name == "FeatureExt")
                {
                    // Check if we are to serialize the offset or the actual data
                    if (property.IsOffsetOffset)
                    {
                        // Property will be written at the offset immediately following all variable length data
                        property.Position = variableProperties.Last().Position + variableProperties.Last().Length;

                        // Write the position at which we'll be serializing the feature extension block
                        TDSUtilities.WriteUInt(destination, property.Position);

                        // Order strings in ascending order by offset
                        variableProperties = variableProperties.OrderBy(p => p.Position).ToList();

                        // Compensate increment to the next position in order to stay on the same
                        iCurrentProperty--;

                        // No longer offset, actual data is going to follow
                        property.IsOffsetOffset = false;
                    }
                    else
                    {
                        // Transfer deflated feature extension into the login stream
                        featureExtension.WriteTo(destination);
                    }
                }
                else if (property.Property.Name == "SSPI")
                {
                    // Write SSPI
                    destination.Write(SSPI, 0, SSPI.Length);
                }
                else
                {
                    // Write the string value
                    TDSUtilities.WriteString(destination, (string)property.Property.GetValue(this, null));
                }

                // Move to the next property
                iCurrentProperty++;
            }
        }