1 //------------------------------------------------------------------------------
2 // <copyright file="SessionStateUtil.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 //------------------------------------------------------------------------------
11 namespace System.Web.SessionState {
12 using System.Collections;
13 using System.Collections.Generic;
15 using System.IO.Compression;
16 using System.Runtime.Serialization;
17 using System.Security.Permissions;
19 using System.Web.Util;
22 public static class SessionStateUtility {
23 internal const String SESSION_KEY = "AspSession";
25 // Used by AltSerialization's BinaryFormatter for session serialization customization
26 public static ISurrogateSelector SerializationSurrogateSelector {
27 [SecurityPermission(SecurityAction.LinkDemand, SerializationFormatter = true)]
29 [SecurityPermission(SecurityAction.LinkDemand, SerializationFormatter = true)]
33 // Called by custom session state module if they want to raise Session_End.
34 static public void RaiseSessionEnd(IHttpSessionState session, Object eventSource, EventArgs eventArgs) {
35 HttpApplicationFactory.EndSession(new HttpSessionState(session), eventSource, eventArgs);
38 // Called by custom session state module
39 static public void AddHttpSessionStateToContext(HttpContext context, IHttpSessionState container) {
40 HttpSessionState sessionState = new HttpSessionState(container);
43 context.Items.Add(SESSION_KEY, sessionState);
45 catch (ArgumentException) {
46 throw new HttpException(SR.GetString(SR.Cant_have_multiple_session_module));
50 static internal void AddHttpSessionStateModuleToContext(HttpContext context, SessionStateModule module, bool delayed) {
51 context.AddHttpSessionStateModule(module, delayed);
54 static internal void RemoveHttpSessionStateFromContext(HttpContext context, bool delayed) {
56 context.Items.Remove(SESSION_KEY);
59 context.RemoveHttpSessionStateModule();
62 // Called by custom session state module
63 static public void RemoveHttpSessionStateFromContext(HttpContext context) {
64 RemoveHttpSessionStateFromContext(context, false);
67 // Called by custom session state module
68 static public IHttpSessionState GetHttpSessionStateFromContext(HttpContext context) {
69 return context.Session.Container;
72 static public HttpStaticObjectsCollection GetSessionStaticObjects(HttpContext context) {
73 return context.Application.SessionStaticObjects.Clone();
77 /// Gets a value that indicates whether session state is required by the context.
79 /// <param name="context">The HttpContext.</param>
80 /// <returns>A value that indicates whether session state is required by the context.</returns>
81 static public bool IsSessionStateRequired(HttpContext context) {
82 return context.RequiresSessionState;
86 /// Gets a value that indicates whether session state is read-only in the context.
88 /// <param name="context">The HttpContext.</param>
89 /// <returns>A value that indicates whether session state is read-only in the context.</returns>
90 static public bool IsSessionStateReadOnly(HttpContext context) {
91 return context.ReadOnlySessionState;
94 internal static SessionStateStoreData CreateLegitStoreData(HttpContext context,
95 ISessionStateItemCollection sessionItems,
96 HttpStaticObjectsCollection staticObjects,
98 if (sessionItems == null) {
99 sessionItems = new SessionStateItemCollection();
102 if (staticObjects == null && context != null) {
103 staticObjects = SessionStateUtility.GetSessionStaticObjects(context);
106 return new SessionStateStoreData(sessionItems, staticObjects, timeout);
110 // This method will take an item and serialize it
111 [SecurityPermission(SecurityAction.Assert, SerializationFormatter = true)]
112 internal static void Serialize(SessionStateStoreData item, Stream stream) {
113 bool hasItems = true;
114 bool hasStaticObjects = true;
116 BinaryWriter writer = new BinaryWriter(stream);
117 writer.Write(item.Timeout);
119 if (item.Items == null || item.Items.Count == 0) {
122 writer.Write(hasItems);
124 if (item.StaticObjects == null || item.StaticObjects.NeverAccessed) {
125 hasStaticObjects = false;
127 writer.Write(hasStaticObjects);
130 ((SessionStateItemCollection)item.Items).Serialize(writer);
133 if (hasStaticObjects) {
134 item.StaticObjects.Serialize(writer);
137 // Prevent truncation of the stream
138 writer.Write(unchecked((byte)0xff));
141 // This will deserialize and return an item.
142 // This version uses the default classes for SessionStateItemCollection, HttpStaticObjectsCollection
143 // and SessionStateStoreData
144 [SecurityPermission(SecurityAction.Assert, SerializationFormatter = true)]
145 internal static SessionStateStoreData Deserialize(HttpContext context, Stream stream) {
148 SessionStateItemCollection sessionItems;
150 bool hasStaticObjects;
151 HttpStaticObjectsCollection staticObjects;
154 Debug.Assert(context != null);
157 BinaryReader reader = new BinaryReader(stream);
158 timeout = reader.ReadInt32();
159 hasItems = reader.ReadBoolean();
160 hasStaticObjects = reader.ReadBoolean();
163 sessionItems = SessionStateItemCollection.Deserialize(reader);
166 sessionItems = new SessionStateItemCollection();
169 if (hasStaticObjects) {
170 staticObjects = HttpStaticObjectsCollection.Deserialize(reader);
173 staticObjects = SessionStateUtility.GetSessionStaticObjects(context);
176 eof = reader.ReadByte();
178 throw new HttpException(SR.GetString(SR.Invalid_session_state));
181 catch (EndOfStreamException) {
182 throw new HttpException(SR.GetString(SR.Invalid_session_state));
185 return new SessionStateStoreData(sessionItems, staticObjects, timeout);
188 static internal void SerializeStoreData(SessionStateStoreData item, int initialStreamSize, out byte[] buf, out int length, bool compressionEnabled) {
189 using(MemoryStream s = new MemoryStream(initialStreamSize)) {
190 SessionStateUtility.Serialize(item, s);
191 if(compressionEnabled) {
192 byte[] serializedBuffer = s.GetBuffer();
193 int serializedLength = (int)s.Length;
194 // truncate the MemoryStream so we can write the compressed data in it
196 // compress the serialized bytes
197 using(DeflateStream zipStream = new DeflateStream(s, CompressionMode.Compress, true)) {
198 zipStream.Write(serializedBuffer, 0, serializedLength);
200 // if the session state tables have ANSI_PADDING disabled, last )s are trimmed.
201 // This shouldn't happen, but to be sure, we are padding with an extra byte
202 s.WriteByte((byte)0xff);
205 length = (int) s.Length;
209 static internal SessionStateStoreData DeserializeStoreData(HttpContext context, Stream stream, bool compressionEnabled) {
210 if(compressionEnabled) {
211 // apply the compression decorator on top of the stream
212 // the data should not be bigger than 4GB - compression doesn't work for more than that
213 using(DeflateStream zipStream = new DeflateStream(stream, CompressionMode.Decompress, true)) {
214 return SessionStateUtility.Deserialize(context, zipStream);
217 return SessionStateUtility.Deserialize(context, stream);