//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace System.IdentityModel
{
using System.Diagnostics;
using System.IdentityModel.Diagnostics;
using System.IdentityModel.Tokens;
using System.IO;
using System.IO.Compression;
///
/// Provides cookie compression using .
///
public sealed class DeflateCookieTransform : CookieTransform
{
int _maxDecompressedSize = 1024 * 1024; // Default maximum of 1MB
///
/// Creates a new instance of .
///
public DeflateCookieTransform()
{
}
///
/// Gets or sets the maximum size (in bytes) of a decompressed cookie.
///
public int MaxDecompressedSize
{
get { return _maxDecompressedSize; }
set { _maxDecompressedSize = value; }
}
///
/// Inflates data.
///
/// Data previously returned from
/// Decoded data.
/// The argument 'value' is null.
/// The argument 'value' contains zero bytes.
/// The decompressed length is larger than MaxDecompressedSize.
public override byte[] Decode( byte[] encoded )
{
if ( null == encoded )
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull( "encoded" );
}
if ( 0 == encoded.Length )
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument( "encoded", SR.GetString( SR.ID6045 ) );
}
MemoryStream compressedStream = new MemoryStream( encoded );
using ( DeflateStream deflateStream = new DeflateStream( compressedStream, CompressionMode.Decompress, false ) )
{
using ( MemoryStream decompressedStream = new MemoryStream() )
{
byte[] buffer = new byte[1024];
int bytesRead;
do
{
bytesRead = deflateStream.Read( buffer, 0, buffer.Length );
decompressedStream.Write( buffer, 0, bytesRead );
// check length against configured maximum to prevevent decompression bomb attacks
if ( decompressedStream.Length > MaxDecompressedSize )
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new SecurityTokenException( SR.GetString( SR.ID1068, MaxDecompressedSize ) ) );
}
} while ( bytesRead > 0 );
return decompressedStream.ToArray();
}
}
}
///
/// Deflates data.
///
/// Data to be compressed.
/// Compressed data.
/// The argument 'value' is null.
/// The argument 'value' contains zero bytes.
public override byte[] Encode( byte[] value )
{
if ( null == value )
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull( "value" );
}
if ( 0 == value.Length )
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument( "value", SR.GetString( SR.ID6044 ) );
}
using ( MemoryStream compressedStream = new MemoryStream() )
{
using ( DeflateStream deflateStream = new DeflateStream( compressedStream, CompressionMode.Compress, true ) )
{
deflateStream.Write( value, 0, value.Length );
}
byte[] encoded = compressedStream.ToArray();
if ( DiagnosticUtility.ShouldTrace( TraceEventType.Information ) )
{
TraceUtility.TraceEvent(
TraceEventType.Information,
TraceCode.Diagnostics,
SR.GetString(SR.TraceDeflateCookieEncode),
new DeflateCookieTraceRecord( value.Length, encoded.Length ),
null,
null );
}
return encoded;
}
}
}
}