[bcl] Update Reference Source to .NET Framework 4.6.2
[mono.git] / mcs / class / referencesource / System.Web / State / SessionStateUtil.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="SessionStateUtil.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //------------------------------------------------------------------------------
6
7 /*
8  * SessionStateUtil
9  *
10  */
11 namespace System.Web.SessionState {
12     using System.Collections;
13     using System.Collections.Generic;
14     using System.IO;
15     using System.IO.Compression;
16     using System.Runtime.Serialization;
17     using System.Security.Permissions;
18     using System.Web;
19     using System.Web.Util;
20     using System.Xml;
21
22     public static class SessionStateUtility {
23         internal const String SESSION_KEY = "AspSession";
24
25         // Used by AltSerialization's BinaryFormatter for session serialization customization
26         public static ISurrogateSelector SerializationSurrogateSelector {
27             [SecurityPermission(SecurityAction.LinkDemand, SerializationFormatter = true)]
28             get;
29             [SecurityPermission(SecurityAction.LinkDemand, SerializationFormatter = true)]
30             set;
31         }
32
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);
36         }
37
38         // Called by custom session state module
39         static public void AddHttpSessionStateToContext(HttpContext context, IHttpSessionState container) {
40             HttpSessionState sessionState = new HttpSessionState(container);
41
42             try {
43                 context.Items.Add(SESSION_KEY, sessionState);
44             }
45             catch (ArgumentException) {
46                 throw new HttpException(SR.GetString(SR.Cant_have_multiple_session_module));
47             }
48         }
49
50         static internal void AddHttpSessionStateModuleToContext(HttpContext context, SessionStateModule module, bool delayed) {
51             context.AddHttpSessionStateModule(module, delayed);
52         }
53
54         static internal void RemoveHttpSessionStateFromContext(HttpContext context, bool delayed) {
55             if (!delayed) {
56                 context.Items.Remove(SESSION_KEY);
57             }
58
59             context.RemoveHttpSessionStateModule();
60          }
61
62         // Called by custom session state module
63         static public void RemoveHttpSessionStateFromContext(HttpContext context) {
64             RemoveHttpSessionStateFromContext(context, false);
65         }
66
67         // Called by custom session state module
68         static public IHttpSessionState GetHttpSessionStateFromContext(HttpContext context) {
69                 return context.Session.Container;
70         }
71
72         static public HttpStaticObjectsCollection GetSessionStaticObjects(HttpContext context) {
73             return context.Application.SessionStaticObjects.Clone();
74         }
75
76         /// <summary>
77         /// Gets a value that indicates whether session state is required by the context.
78         /// </summary>
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;
83         }
84
85         /// <summary>
86         /// Gets a value that indicates whether session state is read-only in the context.
87         /// </summary>
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;
92         }
93
94         internal static SessionStateStoreData CreateLegitStoreData(HttpContext context,
95                                                     ISessionStateItemCollection sessionItems,
96                                                     HttpStaticObjectsCollection staticObjects,
97                                                     int timeout) {
98             if (sessionItems == null) {
99                 sessionItems = new SessionStateItemCollection();
100             }
101
102             if (staticObjects == null && context != null) {
103                 staticObjects = SessionStateUtility.GetSessionStaticObjects(context);
104             }
105
106             return new SessionStateStoreData(sessionItems, staticObjects, timeout);
107         }
108
109
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;
115
116             BinaryWriter writer = new BinaryWriter(stream);
117             writer.Write(item.Timeout);
118
119             if (item.Items == null || item.Items.Count == 0) {
120                 hasItems = false;
121             }
122             writer.Write(hasItems);
123
124             if (item.StaticObjects == null || item.StaticObjects.NeverAccessed) {
125                 hasStaticObjects = false;
126             }
127             writer.Write(hasStaticObjects);
128
129             if (hasItems) {
130                 ((SessionStateItemCollection)item.Items).Serialize(writer);
131             }
132
133             if (hasStaticObjects) {
134                 item.StaticObjects.Serialize(writer);
135             }
136
137             // Prevent truncation of the stream
138             writer.Write(unchecked((byte)0xff));
139         }
140
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) {
146
147             int                 timeout;
148             SessionStateItemCollection   sessionItems;
149             bool                hasItems;
150             bool                hasStaticObjects;
151             HttpStaticObjectsCollection staticObjects;
152             Byte                eof;
153
154             Debug.Assert(context != null);
155
156             try {
157                 BinaryReader reader = new BinaryReader(stream);
158                 timeout = reader.ReadInt32();
159                 hasItems = reader.ReadBoolean();
160                 hasStaticObjects = reader.ReadBoolean();
161
162                 if (hasItems) {
163                     sessionItems = SessionStateItemCollection.Deserialize(reader);
164                 }
165                 else {
166                     sessionItems = new SessionStateItemCollection();
167                 }
168
169                 if (hasStaticObjects) {
170                     staticObjects = HttpStaticObjectsCollection.Deserialize(reader);
171                 }
172                 else {
173                     staticObjects = SessionStateUtility.GetSessionStaticObjects(context);
174                 }
175
176                 eof = reader.ReadByte();
177                 if (eof != 0xff) {
178                     throw new HttpException(SR.GetString(SR.Invalid_session_state));
179                 }
180             }
181             catch (EndOfStreamException) {
182                 throw new HttpException(SR.GetString(SR.Invalid_session_state));
183             }
184
185             return new SessionStateStoreData(sessionItems, staticObjects, timeout);
186         }
187
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
195                     s.SetLength(0);
196                     // compress the serialized bytes
197                     using(DeflateStream zipStream = new DeflateStream(s, CompressionMode.Compress, true)) {
198                         zipStream.Write(serializedBuffer, 0, serializedLength);
199                     }
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);
203                 }
204                 buf = s.GetBuffer();
205                 length = (int) s.Length;
206             }
207         }
208
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);
215                 }
216             }
217             return SessionStateUtility.Deserialize(context, stream);
218         }
219     }
220
221 }