1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //------------------------------------------------------------
4 
5 namespace System.ServiceModel.Channels
6 {
7     using System;
8     using System.Collections.Generic;
9     using System.Xml;
10     using System.Net;
11     using System.IO;
12     using System.Text;
13     using System.Globalization;
14     using System.Runtime.Serialization;
15     using System.ServiceModel.Diagnostics;
16     using System.Diagnostics;
17 
18     abstract class ContextProtocol
19     {
20         ContextExchangeMechanism contextExchangeMechanism;
21 
ContextProtocol(ContextExchangeMechanism contextExchangeMechanism)22         protected ContextProtocol(ContextExchangeMechanism contextExchangeMechanism)
23         {
24             if (!ContextExchangeMechanismHelper.IsDefined(contextExchangeMechanism))
25             {
26                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("contextExchangeMechanism"));
27             }
28             this.contextExchangeMechanism = contextExchangeMechanism;
29         }
30 
31         protected ContextExchangeMechanism ContextExchangeMechanism
32         {
33             get { return this.contextExchangeMechanism; }
34         }
35 
OnIncomingMessage(Message message)36         public abstract void OnIncomingMessage(Message message);
37 
OnOutgoingMessage(Message message, RequestContext requestContext)38         public abstract void OnOutgoingMessage(Message message, RequestContext requestContext);
39 
OnSendSoapContextHeader(Message message, ContextMessageProperty context)40         protected void OnSendSoapContextHeader(Message message, ContextMessageProperty context)
41         {
42             if (message == null)
43             {
44                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("message");
45             }
46             if (context == null)
47             {
48                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("context");
49             }
50 
51             if (context.Context.Count > 0)
52             {
53                 message.Headers.Add(new ContextMessageHeader(context.Context));
54             }
55 
56             if (DiagnosticUtility.ShouldTraceVerbose)
57             {
58                 TraceUtility.TraceEvent(TraceEventType.Verbose, TraceCode.ContextProtocolContextAddedToMessage,
59                     SR.GetString(SR.TraceCodeContextProtocolContextAddedToMessage), this);
60             }
61         }
62 
63         internal static class HttpCookieToolbox
64         {
65             public const string ContextHttpCookieName = "WscContext";
66             public const string RemoveContextHttpCookieHeader = ContextHttpCookieName + ";Max-Age=0";
67 
EncodeContextAsHttpSetCookieHeader(ContextMessageProperty context, Uri uri)68             public static string EncodeContextAsHttpSetCookieHeader(ContextMessageProperty context, Uri uri)
69             {
70                 if (uri == null)
71                 {
72                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("uri");
73                 }
74                 if (context == null)
75                 {
76                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("context");
77                 }
78 
79                 MemoryStream stream = new MemoryStream();
80                 XmlWriterSettings writerSettings = new XmlWriterSettings();
81                 writerSettings.OmitXmlDeclaration = true;
82                 XmlWriter writer = XmlWriter.Create(stream, writerSettings);
83                 ContextMessageHeader contextHeader = new ContextMessageHeader(context.Context);
84                 contextHeader.WriteHeader(writer, MessageVersion.Default);
85                 writer.Flush();
86 
87                 string result = string.Format(
88                     CultureInfo.InvariantCulture,
89                     "{0}=\"{1}\";Path={2}",
90                     HttpCookieToolbox.ContextHttpCookieName,
91                     Convert.ToBase64String(stream.GetBuffer(), 0, (int)stream.Length),
92                     uri.AbsolutePath);
93 
94                 return result;
95             }
96 
TryCreateFromHttpCookieHeader(string httpCookieHeader, out ContextMessageProperty context)97             public static bool TryCreateFromHttpCookieHeader(string httpCookieHeader, out ContextMessageProperty context)
98             {
99                 if (httpCookieHeader == null)
100                 {
101                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("httpCookieHeader");
102                 }
103 
104                 context = null;
105 
106                 foreach (string token in httpCookieHeader.Split(';'))
107                 {
108                     string trimmedToken = token.Trim();
109                     if (trimmedToken.StartsWith(HttpCookieToolbox.ContextHttpCookieName, StringComparison.Ordinal))
110                     {
111                         int equalsSignIndex = trimmedToken.IndexOf('=');
112                         if (equalsSignIndex < 0)
113                         {
114                             context = new ContextMessageProperty();
115                             break;
116                         }
117                         if (equalsSignIndex < (trimmedToken.Length - 1))
118                         {
119                             string value = trimmedToken.Substring(equalsSignIndex + 1).Trim();
120 
121                             if (value.Length > 1 && (value[0] == '"') && (value[value.Length - 1] == '"'))
122                             {
123                                 value = value.Substring(1, value.Length - 2);
124                             }
125                             try
126                             {
127                                 context = ContextMessageHeader.ParseContextHeader(
128                                     XmlReader.Create(new MemoryStream(Convert.FromBase64String(value))));
129                                 break;
130                             }
131                             catch (SerializationException e)
132                             {
133                                 DiagnosticUtility.TraceHandledException(e, TraceEventType.Warning);
134                             }
135                             catch (ProtocolException pe)
136                             {
137                                 DiagnosticUtility.TraceHandledException(pe, TraceEventType.Warning);
138                             }
139                         }
140                     }
141                 }
142 
143                 return context != null;
144             }
145         }
146     }
147 }
148