Imported Upstream version 3.6.0

Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
This commit is contained in:
Jo Shields
2014-08-13 10:39:27 +01:00
commit a575963da9
50588 changed files with 8155799 additions and 0 deletions

View File

@@ -0,0 +1,219 @@
//
// System.Net.AuthenticationManager.cs
//
// Author:
// Miguel de Icaza (miguel@ximian.com)
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
//
// (C) 2002,2003 Ximian, Inc. (http://www.ximian.com)
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System.Collections;
using System.Collections.Specialized;
using System.Configuration;
using System.Net.Configuration;
namespace System.Net
{
public class AuthenticationManager {
static ArrayList modules;
static object locker = new object ();
private AuthenticationManager ()
{
}
static void EnsureModules ()
{
lock (locker) {
if (modules != null)
return;
modules = new ArrayList ();
#if NET_2_1
modules.Add (new NtlmClient ());
modules.Add (new DigestClient ());
modules.Add (new BasicClient ());
#elif CONFIGURATION_DEP
object cfg = ConfigurationManager.GetSection ("system.net/authenticationModules");
AuthenticationModulesSection s = cfg as AuthenticationModulesSection;
if (s != null) {
foreach (AuthenticationModuleElement element in s.AuthenticationModules) {
IAuthenticationModule module = null;
try {
Type type = Type.GetType (element.Type, true);
module = (IAuthenticationModule) Activator.CreateInstance (type);
} catch {}
modules.Add (module);
}
}
#else
ConfigurationSettings.GetConfig ("system.net/authenticationModules");
#endif
}
}
static ICredentialPolicy credential_policy = null;
public static ICredentialPolicy CredentialPolicy
{
get {
return(credential_policy);
}
set {
credential_policy = value;
}
}
static Exception GetMustImplement ()
{
return new NotImplementedException ();
}
[MonoTODO]
public static StringDictionary CustomTargetNameDictionary
{
get {
throw GetMustImplement ();
}
}
public static IEnumerator RegisteredModules {
get {
EnsureModules ();
return modules.GetEnumerator ();
}
}
internal static void Clear ()
{
EnsureModules ();
lock (modules)
modules.Clear ();
}
public static Authorization Authenticate (string challenge, WebRequest request, ICredentials credentials)
{
if (request == null)
throw new ArgumentNullException ("request");
if (credentials == null)
throw new ArgumentNullException ("credentials");
if (challenge == null)
throw new ArgumentNullException ("challenge");
return DoAuthenticate (challenge, request, credentials);
}
static Authorization DoAuthenticate (string challenge, WebRequest request, ICredentials credentials)
{
EnsureModules ();
lock (modules) {
foreach (IAuthenticationModule mod in modules) {
Authorization auth = mod.Authenticate (challenge, request, credentials);
if (auth == null)
continue;
auth.Module = mod;
return auth;
}
}
return null;
}
public static Authorization PreAuthenticate (WebRequest request, ICredentials credentials)
{
if (request == null)
throw new ArgumentNullException ("request");
if (credentials == null)
return null;
EnsureModules ();
lock (modules) {
foreach (IAuthenticationModule mod in modules) {
Authorization auth = mod.PreAuthenticate (request, credentials);
if (auth == null)
continue;
auth.Module = mod;
return auth;
}
}
return null;
}
public static void Register (IAuthenticationModule authenticationModule)
{
if (authenticationModule == null)
throw new ArgumentNullException ("authenticationModule");
DoUnregister (authenticationModule.AuthenticationType, false);
lock (modules)
modules.Add (authenticationModule);
}
public static void Unregister (IAuthenticationModule authenticationModule)
{
if (authenticationModule == null)
throw new ArgumentNullException ("authenticationModule");
DoUnregister (authenticationModule.AuthenticationType, true);
}
public static void Unregister (string authenticationScheme)
{
if (authenticationScheme == null)
throw new ArgumentNullException ("authenticationScheme");
DoUnregister (authenticationScheme, true);
}
static void DoUnregister (string authenticationScheme, bool throwEx)
{
EnsureModules ();
lock (modules) {
IAuthenticationModule module = null;
foreach (IAuthenticationModule mod in modules) {
string modtype = mod.AuthenticationType;
if (String.Compare (modtype, authenticationScheme, true) == 0) {
module = mod;
break;
}
}
if (module == null) {
if (throwEx)
throw new InvalidOperationException ("Scheme not registered.");
} else {
modules.Remove (module);
}
}
}
}
}

View File

@@ -0,0 +1,35 @@
//
// System.Net.AuthenticationSchemeSelector.cs
//
// Author:
// Gonzalo Paniagua Javier <gonzalo@novell.com>
//
// Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#if SECURITY_DEP
namespace System.Net {
public delegate AuthenticationSchemes AuthenticationSchemeSelector (HttpListenerRequest httpRequest);
}
#endif

View File

@@ -0,0 +1,46 @@
//
// System.Net.AuthenticationSchemes.cs
//
// Author:
// Atsushi Enomoto <atsushi@ximian.com>
//
// (C) 2005 Novell, Inc. (http://www.novell.com)
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System.Collections;
using System.Configuration;
namespace System.Net
{
[Flags]
public enum AuthenticationSchemes {
None,
Digest = 1,
Negotiate = 2,
Ntlm = 4,
IntegratedWindowsAuthentication = 6,
Basic = 8,
Anonymous = 0x8000,
}
}

View File

@@ -0,0 +1,95 @@
//
// System.Net.Authorization.cs
//
// Author:
// Miguel de Icaza (miguel@ximian.com)
// Lawrence Pit (loz@cable.a2000.nl)
//
// (C) Ximian, Inc. http://www.ximian.com
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
namespace System.Net {
public class Authorization {
string token;
bool complete;
string connectionGroupId;
string [] protectionRealm;
IAuthenticationModule module;
public Authorization (string token) : this (token, true)
{
}
public Authorization (string token, bool finished)
: this (token, finished, null)
{
}
public Authorization (string token, bool finished, string connectionGroupId)
{
this.token = token;
this.complete = finished;
this.connectionGroupId = connectionGroupId;
}
public string Message {
get { return token; }
}
public bool Complete {
get { return complete; }
}
public string ConnectionGroupId {
get { return connectionGroupId; }
}
public string[] ProtectionRealm {
get { return protectionRealm; }
set { protectionRealm = value; }
}
internal IAuthenticationModule Module {
get { return module; }
set { module = value; }
}
static Exception GetMustImplement ()
{
return new NotImplementedException ();
}
[MonoTODO]
public bool MutuallyAuthenticated
{
get {
throw GetMustImplement ();
}
set {
throw GetMustImplement ();
}
}
}
}

View File

@@ -0,0 +1,100 @@
//
// System.Net.BasicClient
//
// Authors:
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
//
// (C) 2003 Ximian, Inc (http://www.ximian.com)
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System.Text;
namespace System.Net
{
class BasicClient : IAuthenticationModule
{
public Authorization Authenticate (string challenge, WebRequest webRequest, ICredentials credentials)
{
if (credentials == null || challenge == null)
return null;
string header = challenge.Trim ();
if (header.ToLower ().IndexOf ("basic", StringComparison.Ordinal) == -1)
return null;
return InternalAuthenticate (webRequest, credentials);
}
static byte [] GetBytes (string str)
{
int i = str.Length;
byte [] result = new byte [i];
for (--i; i >= 0; i--)
result [i] = (byte) str [i];
return result;
}
static Authorization InternalAuthenticate (WebRequest webRequest, ICredentials credentials)
{
HttpWebRequest request = webRequest as HttpWebRequest;
if (request == null || credentials == null)
return null;
NetworkCredential cred = credentials.GetCredential (request.AuthUri, "basic");
if (cred == null)
return null;
string userName = cred.UserName;
if (userName == null || userName == "")
return null;
string password = cred.Password;
string domain = cred.Domain;
byte [] bytes;
// If domain is set, MS sends "domain\user:password".
if (domain == null || domain == "" || domain.Trim () == "")
bytes = GetBytes (userName + ":" + password);
else
bytes = GetBytes (domain + "\\" + userName + ":" + password);
string auth = "Basic " + Convert.ToBase64String (bytes);
return new Authorization (auth);
}
public Authorization PreAuthenticate (WebRequest webRequest, ICredentials credentials)
{
return InternalAuthenticate ( webRequest, credentials);
}
public string AuthenticationType {
get { return "Basic"; }
}
public bool CanPreAuthenticate {
get { return true; }
}
}
}

View File

@@ -0,0 +1,32 @@
//
// System.Net.BindIPEndPoint
//
// Author:
// Gonzalo Paniagua Javier <gonzalo@novell.com>
//
// Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
namespace System.Net {
public delegate IPEndPoint BindIPEndPoint (ServicePoint servicePoint, IPEndPoint remoteEndPoint, int retryCount);
}

View File

@@ -0,0 +1 @@
28f2b747b7c503c5a4a8180b0d927f500e9cff8d

View File

@@ -0,0 +1,367 @@
//
// System.Net.ChunkStream
//
// Authors:
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
//
// (C) 2003 Ximian, Inc (http://www.ximian.com)
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System.Collections;
using System.Globalization;
using System.IO;
using System.Text;
namespace System.Net
{
class ChunkStream
{
enum State {
None,
Body,
BodyFinished,
Trailer
}
class Chunk {
public byte [] Bytes;
public int Offset;
public Chunk (byte [] chunk)
{
this.Bytes = chunk;
}
public int Read (byte [] buffer, int offset, int size)
{
int nread = (size > Bytes.Length - Offset) ? Bytes.Length - Offset : size;
Buffer.BlockCopy (Bytes, Offset, buffer, offset, nread);
Offset += nread;
return nread;
}
}
internal WebHeaderCollection headers;
int chunkSize;
int chunkRead;
int totalWritten;
State state;
//byte [] waitBuffer;
StringBuilder saved;
bool sawCR;
bool gotit;
int trailerState;
ArrayList chunks;
public ChunkStream (byte [] buffer, int offset, int size, WebHeaderCollection headers)
: this (headers)
{
Write (buffer, offset, size);
}
public ChunkStream (WebHeaderCollection headers)
{
this.headers = headers;
saved = new StringBuilder ();
chunks = new ArrayList ();
chunkSize = -1;
totalWritten = 0;
}
public void ResetBuffer ()
{
chunkSize = -1;
chunkRead = 0;
totalWritten = 0;
chunks.Clear ();
}
public void WriteAndReadBack (byte [] buffer, int offset, int size, ref int read)
{
if (offset + read > 0)
Write (buffer, offset, offset+read);
read = Read (buffer, offset, size);
}
public int Read (byte [] buffer, int offset, int size)
{
return ReadFromChunks (buffer, offset, size);
}
int ReadFromChunks (byte [] buffer, int offset, int size)
{
int count = chunks.Count;
int nread = 0;
for (int i = 0; i < count; i++) {
Chunk chunk = (Chunk) chunks [i];
if (chunk == null)
continue;
if (chunk.Offset == chunk.Bytes.Length) {
chunks [i] = null;
continue;
}
nread += chunk.Read (buffer, offset + nread, size - nread);
if (nread == size)
break;
}
return nread;
}
public void Write (byte [] buffer, int offset, int size)
{
if (offset < size)
InternalWrite (buffer, ref offset, size);
}
void InternalWrite (byte [] buffer, ref int offset, int size)
{
if (state == State.None) {
state = GetChunkSize (buffer, ref offset, size);
if (state == State.None)
return;
saved.Length = 0;
sawCR = false;
gotit = false;
}
if (state == State.Body && offset < size) {
state = ReadBody (buffer, ref offset, size);
if (state == State.Body)
return;
}
if (state == State.BodyFinished && offset < size) {
state = ReadCRLF (buffer, ref offset, size);
if (state == State.BodyFinished)
return;
sawCR = false;
}
if (state == State.Trailer && offset < size) {
state = ReadTrailer (buffer, ref offset, size);
if (state == State.Trailer)
return;
saved.Length = 0;
sawCR = false;
gotit = false;
}
if (offset < size)
InternalWrite (buffer, ref offset, size);
}
public bool WantMore {
get { return (chunkRead != chunkSize || chunkSize != 0 || state != State.None); }
}
public bool DataAvailable {
get {
int count = chunks.Count;
for (int i = 0; i < count; i++) {
Chunk ch = (Chunk) chunks [i];
if (ch == null || ch.Bytes == null)
continue;
if (ch.Bytes.Length > 0 && ch.Offset < ch.Bytes.Length)
return (state != State.Body);
}
return false;
}
}
public int TotalDataSize {
get { return totalWritten; }
}
public int ChunkLeft {
get { return chunkSize - chunkRead; }
}
State ReadBody (byte [] buffer, ref int offset, int size)
{
if (chunkSize == 0)
return State.BodyFinished;
int diff = size - offset;
if (diff + chunkRead > chunkSize)
diff = chunkSize - chunkRead;
byte [] chunk = new byte [diff];
Buffer.BlockCopy (buffer, offset, chunk, 0, diff);
chunks.Add (new Chunk (chunk));
offset += diff;
chunkRead += diff;
totalWritten += diff;
return (chunkRead == chunkSize) ? State.BodyFinished : State.Body;
}
State GetChunkSize (byte [] buffer, ref int offset, int size)
{
chunkRead = 0;
chunkSize = 0;
char c = '\0';
while (offset < size) {
c = (char) buffer [offset++];
if (c == '\r') {
if (sawCR)
ThrowProtocolViolation ("2 CR found");
sawCR = true;
continue;
}
if (sawCR && c == '\n')
break;
if (c == ' ')
gotit = true;
if (!gotit)
saved.Append (c);
if (saved.Length > 20)
ThrowProtocolViolation ("chunk size too long.");
}
if (!sawCR || c != '\n') {
if (offset < size)
ThrowProtocolViolation ("Missing \\n");
try {
if (saved.Length > 0) {
chunkSize = Int32.Parse (RemoveChunkExtension (saved.ToString ()), NumberStyles.HexNumber);
}
} catch (Exception) {
ThrowProtocolViolation ("Cannot parse chunk size.");
}
return State.None;
}
chunkRead = 0;
try {
chunkSize = Int32.Parse (RemoveChunkExtension (saved.ToString ()), NumberStyles.HexNumber);
} catch (Exception) {
ThrowProtocolViolation ("Cannot parse chunk size.");
}
if (chunkSize == 0) {
trailerState = 2;
return State.Trailer;
}
return State.Body;
}
static string RemoveChunkExtension (string input)
{
int idx = input.IndexOf (';');
if (idx == -1)
return input;
return input.Substring (0, idx);
}
State ReadCRLF (byte [] buffer, ref int offset, int size)
{
if (!sawCR) {
if ((char) buffer [offset++] != '\r')
ThrowProtocolViolation ("Expecting \\r");
sawCR = true;
if (offset == size)
return State.BodyFinished;
}
if (sawCR && (char) buffer [offset++] != '\n')
ThrowProtocolViolation ("Expecting \\n");
return State.None;
}
State ReadTrailer (byte [] buffer, ref int offset, int size)
{
char c = '\0';
// short path
if (trailerState == 2 && (char) buffer [offset] == '\r' && saved.Length == 0) {
offset++;
if (offset < size && (char) buffer [offset] == '\n') {
offset++;
return State.None;
}
offset--;
}
int st = trailerState;
string stString = "\r\n\r";
while (offset < size && st < 4) {
c = (char) buffer [offset++];
if ((st == 0 || st == 2) && c == '\r') {
st++;
continue;
}
if ((st == 1 || st == 3) && c == '\n') {
st++;
continue;
}
if (st > 0) {
saved.Append (stString.Substring (0, saved.Length == 0? st-2: st));
st = 0;
if (saved.Length > 4196)
ThrowProtocolViolation ("Error reading trailer (too long).");
}
}
if (st < 4) {
trailerState = st;
if (offset < size)
ThrowProtocolViolation ("Error reading trailer.");
return State.Trailer;
}
StringReader reader = new StringReader (saved.ToString ());
string line;
while ((line = reader.ReadLine ()) != null && line != "")
headers.Add (line);
return State.None;
}
static void ThrowProtocolViolation (string message)
{
WebException we = new WebException (message, null, WebExceptionStatus.ServerProtocolViolation, null);
throw we;
}
}
}

View File

@@ -0,0 +1,176 @@
//
// System.Net.ChunkedInputStream
//
// Authors:
// Gonzalo Paniagua Javier (gonzalo@novell.com)
//
// Copyright (c) 2005 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#if SECURITY_DEP
using System.IO;
using System.Net.Sockets;
using System.Runtime.InteropServices;
namespace System.Net {
class ChunkedInputStream : RequestStream {
bool disposed;
ChunkStream decoder;
HttpListenerContext context;
bool no_more_data;
class ReadBufferState {
public byte [] Buffer;
public int Offset;
public int Count;
public int InitialCount;
public HttpStreamAsyncResult Ares;
public ReadBufferState (byte [] buffer, int offset, int count,
HttpStreamAsyncResult ares)
{
Buffer = buffer;
Offset = offset;
Count = count;
InitialCount = count;
Ares = ares;
}
}
public ChunkedInputStream (HttpListenerContext context, Stream stream,
byte [] buffer, int offset, int length)
: base (stream, buffer, offset, length)
{
this.context = context;
WebHeaderCollection coll = (WebHeaderCollection) context.Request.Headers;
decoder = new ChunkStream (coll);
}
public ChunkStream Decoder {
get { return decoder; }
set { decoder = value; }
}
public override int Read ([In,Out] byte [] buffer, int offset, int count)
{
IAsyncResult ares = BeginRead (buffer, offset, count, null, null);
return EndRead (ares);
}
public override IAsyncResult BeginRead (byte [] buffer, int offset, int count,
AsyncCallback cback, object state)
{
if (disposed)
throw new ObjectDisposedException (GetType ().ToString ());
if (buffer == null)
throw new ArgumentNullException ("buffer");
int len = buffer.Length;
if (offset < 0 || offset > len)
throw new ArgumentOutOfRangeException ("offset exceeds the size of buffer");
if (count < 0 || offset > len - count)
throw new ArgumentOutOfRangeException ("offset+size exceeds the size of buffer");
HttpStreamAsyncResult ares = new HttpStreamAsyncResult ();
ares.Callback = cback;
ares.State = state;
if (no_more_data) {
ares.Complete ();
return ares;
}
int nread = decoder.Read (buffer, offset, count);
offset += nread;
count -= nread;
if (count == 0) {
// got all we wanted, no need to bother the decoder yet
ares.Count = nread;
ares.Complete ();
return ares;
}
if (!decoder.WantMore) {
no_more_data = nread == 0;
ares.Count = nread;
ares.Complete ();
return ares;
}
ares.Buffer = new byte [8192];
ares.Offset = 0;
ares.Count = 8192;
ReadBufferState rb = new ReadBufferState (buffer, offset, count, ares);
rb.InitialCount += nread;
base.BeginRead (ares.Buffer, ares.Offset, ares.Count, OnRead, rb);
return ares;
}
void OnRead (IAsyncResult base_ares)
{
ReadBufferState rb = (ReadBufferState) base_ares.AsyncState;
HttpStreamAsyncResult ares = rb.Ares;
try {
int nread = base.EndRead (base_ares);
decoder.Write (ares.Buffer, ares.Offset, nread);
nread = decoder.Read (rb.Buffer, rb.Offset, rb.Count);
rb.Offset += nread;
rb.Count -= nread;
if (rb.Count == 0 || !decoder.WantMore || nread == 0) {
no_more_data = !decoder.WantMore && nread == 0;
ares.Count = rb.InitialCount - rb.Count;
ares.Complete ();
return;
}
ares.Offset = 0;
ares.Count = Math.Min (8192, decoder.ChunkLeft + 6);
base.BeginRead (ares.Buffer, ares.Offset, ares.Count, OnRead, rb);
} catch (Exception e) {
context.Connection.SendError (e.Message, 400);
ares.Complete (e);
}
}
public override int EndRead (IAsyncResult ares)
{
if (disposed)
throw new ObjectDisposedException (GetType ().ToString ());
HttpStreamAsyncResult my_ares = ares as HttpStreamAsyncResult;
if (ares == null)
throw new ArgumentException ("Invalid IAsyncResult", "ares");
if (!ares.IsCompleted)
ares.AsyncWaitHandle.WaitOne ();
if (my_ares.Error != null)
throw new HttpListenerException (400, "I/O operation aborted: " + my_ares.Error.Message);
return my_ares.Count;
}
public override void Close ()
{
if (!disposed) {
disposed = true;
base.Close ();
}
}
}
}
#endif

View File

@@ -0,0 +1,58 @@
// ConnectionModes.cs
//
// This code was automatically generated from
// ECMA CLI XML Library Specification.
// Generator: libgen.xsl [1.0; (C) Sergey Chaban (serge@wildwestsoftware.com)]
// Created: Wed, 5 Sep 2001 06:35:39 UTC
// Source file: all.xml
// URL: http://devresource.hp.com/devresource/Docs/TechPapers/CSharp/all.xml
//
// (C) 2001 Ximian, Inc. http://www.ximian.com
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
namespace System.Net {
/// <summary>
/// </summary>
enum ConnectionModes {
/// <summary>
/// </summary>
Single = 0,
/// <summary>
/// </summary>
Persistent = 1,
/// <summary>
/// </summary>
Pipeline = 2,
/// <summary>
/// </summary>
Mux = 3,
} // ConnectionModes
} // System.Net

View File

@@ -0,0 +1,362 @@
//
// System.Net.Cookie.cs
//
// Authors:
// Lawrence Pit (loz@cable.a2000.nl)
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
// Daniel Nauck (dna(at)mono-project(dot)de)
// Sebastien Pouliot <sebastien@ximian.com>
//
// Copyright (C) 2004,2009 Novell, Inc (http://www.novell.com)
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Text;
using System.Globalization;
using System.Collections;
namespace System.Net {
// Supported cookie formats are:
// Netscape: http://home.netscape.com/newsref/std/cookie_spec.html
// RFC 2109: http://www.ietf.org/rfc/rfc2109.txt
// RFC 2965: http://www.ietf.org/rfc/rfc2965.txt
[Serializable]
public sealed class Cookie
{
string comment;
Uri commentUri;
bool discard;
string domain;
DateTime expires;
bool httpOnly;
string name;
string path;
string port;
int [] ports;
bool secure;
DateTime timestamp;
string val;
int version;
static char [] reservedCharsName = new char [] {' ', '=', ';', ',', '\n', '\r', '\t'};
static char [] portSeparators = new char [] {'"', ','};
static string tspecials = "()<>@,;:\\\"/[]?={} \t"; // from RFC 2965, 2068
public Cookie ()
{
expires = DateTime.MinValue;
timestamp = DateTime.Now;
domain = String.Empty;
name = String.Empty;
val = String.Empty;
comment = String.Empty;
port = String.Empty;
}
public Cookie (string name, string value)
: this ()
{
Name = name;
Value = value;
}
public Cookie (string name, string value, string path)
: this (name, value)
{
Path = path;
}
public Cookie (string name, string value, string path, string domain)
: this (name, value, path)
{
Domain = domain;
}
public string Comment {
get { return comment; }
set { comment = value == null ? String.Empty : value; }
}
public Uri CommentUri {
get { return commentUri; }
set { commentUri = value; }
}
public bool Discard {
get { return discard; }
set { discard = value; }
}
public string Domain {
get { return domain; }
set {
if (String.IsNullOrEmpty (value)) {
domain = String.Empty;
HasDomain = false;
} else {
domain = value;
IPAddress test;
if (IPAddress.TryParse (value, out test))
HasDomain = false;
else
HasDomain = true;
}
}
}
/*
* Set this to false to disable same-origin checks.
*
* This should be done whenever the cookie does not actually
* contain a domain and we fallback to the Uri's hostname.
*
*/
internal bool HasDomain {
get; set;
}
public bool Expired {
get {
return expires <= DateTime.Now &&
expires != DateTime.MinValue;
}
set {
if (value)
expires = DateTime.Now;
}
}
public DateTime Expires {
get { return expires; }
set { expires = value; }
}
public bool HttpOnly {
get { return httpOnly; }
set { httpOnly = value; }
}
public string Name {
get { return name; }
set {
if (String.IsNullOrEmpty (value))
throw new CookieException ("Name cannot be empty");
if (value [0] == '$' || value.IndexOfAny (reservedCharsName) != -1) {
// see CookieTest, according to MS implementation
// the name value changes even though it's incorrect
name = String.Empty;
throw new CookieException ("Name contains invalid characters");
}
name = value;
}
}
public string Path {
get { return (path == null) ? String.Empty : path; }
set { path = (value == null) ? String.Empty : value; }
}
public string Port {
get { return port; }
set {
if (String.IsNullOrEmpty (value)) {
port = String.Empty;
return;
}
if (value [0] != '"' || value [value.Length - 1] != '"') {
throw new CookieException("The 'Port'='" + value + "' part of the cookie is invalid. Port must be enclosed by double quotes.");
}
port = value;
string [] values = port.Split (portSeparators);
ports = new int[values.Length];
for (int i = 0; i < ports.Length; i++) {
ports [i] = Int32.MinValue;
if (values [i].Length == 0)
continue;
try {
ports [i] = Int32.Parse (values [i]);
} catch (Exception e) {
throw new CookieException("The 'Port'='" + value + "' part of the cookie is invalid. Invalid value: " + values [i], e);
}
}
Version = 1;
}
}
internal int [] Ports {
get { return ports; }
set { ports = value; }
}
public bool Secure {
get { return secure; }
set { secure = value; }
}
public DateTime TimeStamp {
get { return timestamp; }
}
public string Value {
get { return val; }
set {
if (value == null) {
val = String.Empty;
return;
}
// LAMESPEC: According to .Net specs the Value property should not accept
// the semicolon and comma characters, yet it does. For now we'll follow
// the behaviour of MS.Net instead of the specs.
/*
if (value.IndexOfAny(reservedCharsValue) != -1)
throw new CookieException("Invalid value. Value cannot contain semicolon or comma characters.");
*/
val = value;
}
}
public int Version {
get { return version; }
set {
if ((value < 0) || (value > 10))
version = 0;
else
version = value;
}
}
public override bool Equals (Object comparand)
{
System.Net.Cookie c = comparand as System.Net.Cookie;
return c != null &&
String.Compare (this.name, c.name, true, CultureInfo.InvariantCulture) == 0 &&
String.Compare (this.val, c.val, false, CultureInfo.InvariantCulture) == 0 &&
String.Compare (this.Path, c.Path, false, CultureInfo.InvariantCulture) == 0 &&
String.Compare (this.domain, c.domain, true, CultureInfo.InvariantCulture) == 0 &&
this.version == c.version;
}
public override int GetHashCode ()
{
return hash(CaseInsensitiveHashCodeProvider.DefaultInvariant.GetHashCode(name),
val.GetHashCode (),
Path.GetHashCode (),
CaseInsensitiveHashCodeProvider.DefaultInvariant.GetHashCode (domain),
version);
}
private static int hash (int i, int j, int k, int l, int m)
{
return i ^ (j << 13 | j >> 19) ^ (k << 26 | k >> 6) ^ (l << 7 | l >> 25) ^ (m << 20 | m >> 12);
}
// returns a string that can be used to send a cookie to an Origin Server
// i.e., only used for clients
// see para 4.2.2 of RFC 2109 and para 3.3.4 of RFC 2965
// see also bug #316017
public override string ToString ()
{
return ToString (null);
}
internal string ToString (Uri uri)
{
if (name.Length == 0)
return String.Empty;
StringBuilder result = new StringBuilder (64);
if (version > 0)
result.Append ("$Version=").Append (version).Append ("; ");
result.Append (name).Append ("=").Append (val);
if (version == 0)
return result.ToString ();
if (!String.IsNullOrEmpty (path))
result.Append ("; $Path=").Append (path);
bool append_domain = (uri == null) || (uri.Host != domain);
if (append_domain && !String.IsNullOrEmpty (domain))
result.Append ("; $Domain=").Append (domain);
if (port != null && port.Length != 0)
result.Append ("; $Port=").Append (port);
return result.ToString ();
}
internal string ToClientString ()
{
if (name.Length == 0)
return String.Empty;
StringBuilder result = new StringBuilder (64);
if (version > 0)
result.Append ("Version=").Append (version).Append (";");
result.Append (name).Append ("=").Append (val);
if (path != null && path.Length != 0)
result.Append (";Path=").Append (QuotedString (path));
if (domain != null && domain.Length != 0)
result.Append (";Domain=").Append (QuotedString (domain));
if (port != null && port.Length != 0)
result.Append (";Port=").Append (port);
return result.ToString ();
}
// See par 3.6 of RFC 2616
string QuotedString (string value)
{
if (version == 0 || IsToken (value))
return value;
else
return "\"" + value.Replace("\"", "\\\"") + "\"";
}
bool IsToken (string value)
{
int len = value.Length;
for (int i = 0; i < len; i++) {
char c = value [i];
if (c < 0x20 || c >= 0x7f || tspecials.IndexOf (c) != -1)
return false;
}
return true;
}
}
}

View File

@@ -0,0 +1,180 @@
//
// System.Net.CookieCollection
//
// Authors:
// Lawrence Pit (loz@cable.a2000.nl)
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
// Sebastien Pouliot <sebastien@ximian.com>
//
// Copyright (C) 2004,2009 Novell, Inc (http://www.novell.com)
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Runtime.Serialization;
namespace System.Net
{
[Serializable]
#if NET_2_1
public sealed class CookieCollection : ICollection, IEnumerable {
#else
public class CookieCollection : ICollection, IEnumerable {
#endif
// not 100% identical to MS implementation
sealed class CookieCollectionComparer : IComparer<Cookie> {
public int Compare (Cookie x, Cookie y)
{
if (x == null || y == null)
return 0;
var ydomain = y.Domain.Length - (y.Domain[0] == '.' ? 1 : 0);
var xdomain = x.Domain.Length - (x.Domain[0] == '.' ? 1 : 0);
int result = ydomain - xdomain;
return result == 0 ? y.Path.Length - x.Path.Length : result;
}
}
static CookieCollectionComparer Comparer = new CookieCollectionComparer ();
List<Cookie> list = new List<Cookie> ();
internal IList<Cookie> List {
get { return list; }
}
// ICollection
public int Count {
get { return list.Count; }
}
public bool IsSynchronized {
get { return false; }
}
public Object SyncRoot {
get { return this; }
}
public void CopyTo (Array array, int index)
{
(list as IList).CopyTo (array, index);
}
public void CopyTo (Cookie [] array, int index)
{
list.CopyTo (array, index);
}
// IEnumerable
public IEnumerator GetEnumerator ()
{
return list.GetEnumerator ();
}
// This
// LAMESPEC: So how is one supposed to create a writable CookieCollection
// instance?? We simply ignore this property, as this collection is always
// writable.
public bool IsReadOnly {
get { return true; }
}
public void Add (Cookie cookie)
{
if (cookie == null)
throw new ArgumentNullException ("cookie");
int pos = SearchCookie (cookie);
if (pos == -1)
list.Add (cookie);
else
list [pos] = cookie;
}
internal void Sort ()
{
if (list.Count > 0)
list.Sort (Comparer);
}
int SearchCookie (Cookie cookie)
{
string name = cookie.Name;
string domain = cookie.Domain;
string path = cookie.Path;
for (int i = list.Count - 1; i >= 0; i--) {
Cookie c = list [i];
if (c.Version != cookie.Version)
continue;
if (0 != String.Compare (domain, c.Domain, true, CultureInfo.InvariantCulture))
continue;
if (0 != String.Compare (name, c.Name, true, CultureInfo.InvariantCulture))
continue;
if (0 != String.Compare (path, c.Path, true, CultureInfo.InvariantCulture))
continue;
return i;
}
return -1;
}
public void Add (CookieCollection cookies)
{
if (cookies == null)
throw new ArgumentNullException ("cookies");
foreach (Cookie c in cookies)
Add (c);
}
public Cookie this [int index] {
get {
if (index < 0 || index >= list.Count)
throw new ArgumentOutOfRangeException ("index");
return list [index];
}
}
public Cookie this [string name] {
get {
foreach (Cookie c in list) {
if (0 == String.Compare (c.Name, name, true, CultureInfo.InvariantCulture))
return c;
}
return null;
}
}
} // CookieCollection
} // System.Net

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,70 @@
//
// System.Net.CookieException.cs
//
// Author:
// Lawrence Pit (loz@cable.a2000.nl)
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System.Globalization;
using System.Runtime.Serialization;
namespace System.Net
{
[Serializable]
public class CookieException : FormatException, ISerializable
{
// Constructors
public CookieException () : base ()
{
}
internal CookieException (string msg) : base (msg)
{
}
internal CookieException (string msg, Exception e) : base (msg, e)
{
}
protected CookieException (SerializationInfo serializationInfo, StreamingContext streamingContext)
: base (serializationInfo, streamingContext)
{
}
#if !TARGET_JVM
// Methods
void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context)
{
base.GetObjectData (info, context);
}
#endif
public override void GetObjectData (SerializationInfo serializationInfo, StreamingContext streamingContext)
{
base.GetObjectData (serializationInfo, streamingContext);
}
}
}

View File

@@ -0,0 +1,270 @@
//
// System.Net.CookieParser
//
// Authors:
// Lawrence Pit (loz@cable.a2000.nl)
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
// Daniel Nauck (dna(at)mono-project(dot)de)
//
// (c) 2002 Lawrence Pit
// (c) 2003 Ximian, Inc. (http://www.ximian.com)
// (c) 2008 Daniel Nauck
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
namespace System.Net {
struct CookieParser
{
static readonly string[] cookieExpiresFormats =
new string[] { "r",
"ddd, dd'-'MMM'-'yyyy HH':'mm':'ss 'GMT'",
"ddd, dd'-'MMM'-'yy HH':'mm':'ss 'GMT'" };
readonly string header;
readonly int length;
int pos;
public CookieParser (string header)
{
this.header = header;
this.length = header.Length;
pos = 0;
}
public IEnumerable<Cookie> Parse ()
{
while (pos < length) {
Cookie cookie;
try {
cookie = DoParse ();
} catch {
while ((pos < length) && (header [pos] != ','))
pos++;
pos++;
continue;
}
yield return cookie;
}
}
Cookie DoParse ()
{
var name = GetCookieName ();
if (pos >= length)
return new Cookie (name, string.Empty);
var value = string.Empty;
if (header [pos] == '=') {
pos++;
value = GetCookieValue ();
}
var cookie = new Cookie (name, value);
if (pos >= length) {
return cookie;
} else if (header [pos] == ',') {
pos++;
return cookie;
} else if ((header [pos++] != ';') || (pos >= length)) {
return cookie;
}
while (pos < length) {
var argName = GetCookieName ();
string argVal = string.Empty;
if ((pos < length) && (header [pos] == '=')) {
pos++;
argVal = GetCookieValue ();
}
ProcessArg (cookie, argName, argVal);
if (pos >= length)
break;
if (header [pos] == ',') {
pos++;
break;
} else if (header [pos] != ';') {
break;
}
pos++;
}
return cookie;
}
void ProcessArg (Cookie cookie, string name, string val)
{
if ((name == null) || (name == string.Empty))
throw new InvalidOperationException ();
switch (name.ToUpperInvariant ()) {
case "COMMENT":
if (cookie.Comment == null)
cookie.Comment = val;
break;
case "COMMENTURL":
if (cookie.CommentUri == null)
cookie.CommentUri = new Uri (val);
break;
case "DISCARD":
cookie.Discard = true;
break;
case "DOMAIN":
if (cookie.Domain == "")
cookie.Domain = val;
break;
case "HTTPONLY":
cookie.HttpOnly = true;
break;
case "MAX-AGE": // RFC Style Set-Cookie2
if (cookie.Expires == DateTime.MinValue) {
try {
cookie.Expires = cookie.TimeStamp.AddSeconds (UInt32.Parse (val));
} catch {}
}
break;
case "EXPIRES": // Netscape Style Set-Cookie
if (cookie.Expires != DateTime.MinValue)
break;
if ((pos < length) && (header [pos] == ',') && IsWeekDay (val)) {
pos++;
val = val + ", " + GetCookieValue ();
}
cookie.Expires = TryParseCookieExpires (val);
break;
case "PATH":
cookie.Path = val;
break;
case "PORT":
if (cookie.Port == null)
cookie.Port = val;
break;
case "SECURE":
cookie.Secure = true;
break;
case "VERSION":
try {
cookie.Version = (int) UInt32.Parse (val);
} catch {}
break;
}
}
string GetCookieName ()
{
int k = pos;
while (k < length && Char.IsWhiteSpace (header [k]))
k++;
int begin = k;
while (k < length && header [k] != ';' && header [k] != ',' && header [k] != '=')
k++;
pos = k;
return header.Substring (begin, k - begin).Trim ();
}
string GetCookieValue ()
{
if (pos >= length)
return null;
int k = pos;
while (k < length && Char.IsWhiteSpace (header [k]))
k++;
int begin;
if (header [k] == '"'){
int j;
begin = k++;
while (k < length && header [k] != '"')
k++;
for (j = ++k; j < length && header [j] != ';' && header [j] != ','; j++)
;
pos = j;
} else {
begin = k;
while (k < length && header [k] != ';' && header [k] != ',')
k++;
pos = k;
}
return header.Substring (begin, k - begin).Trim ();
}
static bool IsWeekDay (string value)
{
switch (value.ToLowerInvariant ()) {
case "mon":
case "tue":
case "wed":
case "thu":
case "fri":
case "sat":
case "sun":
case "monday":
case "tuesday":
case "wednesday":
case "thursday":
case "friday":
case "saturday":
case "sunday":
return true;
default:
return false;
}
}
static DateTime TryParseCookieExpires (string value)
{
if (String.IsNullOrEmpty (value))
return DateTime.MinValue;
for (int i = 0; i < cookieExpiresFormats.Length; i++) {
try {
DateTime cookieExpiresUtc = DateTime.ParseExact (value, cookieExpiresFormats [i], CultureInfo.InvariantCulture);
//convert UTC/GMT time to local time
cookieExpiresUtc = DateTime.SpecifyKind (cookieExpiresUtc, DateTimeKind.Utc);
return TimeZone.CurrentTimeZone.ToLocalTime (cookieExpiresUtc);
} catch {}
}
//If we can't parse Expires, use cookie as session cookie (expires is DateTime.MinValue)
return DateTime.MinValue;
}
}
}

View File

@@ -0,0 +1,282 @@
//
// System.Net.CredentialCache.cs
//
// Author:
// Lawrence Pit (loz@cable.a2000.nl)
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections;
using System.Runtime.Serialization;
namespace System.Net {
public class CredentialCache : ICredentials, IEnumerable, ICredentialsByHost
{
static NetworkCredential empty = new NetworkCredential (String.Empty, String.Empty, String.Empty);
Hashtable cache;
Hashtable cacheForHost;
public CredentialCache ()
{
cache = new Hashtable ();
cacheForHost = new Hashtable ();
}
[MonoTODO ("Need EnvironmentPermission implementation first")]
public static ICredentials DefaultCredentials {
get {
// This is used for NTLM, Kerberos and Negotiate under MS
return empty;
}
}
// MS does might return a special ICredentials which does not allow getting the
// username/password information out of it for non-internal classes.
public static NetworkCredential DefaultNetworkCredentials {
get { return empty; }
}
public NetworkCredential GetCredential (Uri uriPrefix, string authType)
{
int longestPrefix = -1;
NetworkCredential result = null;
if (uriPrefix == null || authType == null)
return null;
string absPath = uriPrefix.AbsolutePath;
absPath = absPath.Substring (0, absPath.LastIndexOf ('/'));
IDictionaryEnumerator e = cache.GetEnumerator ();
while (e.MoveNext ()) {
CredentialCacheKey key = e.Key as CredentialCacheKey;
if (key.Length <= longestPrefix)
continue;
if (String.Compare (key.AuthType, authType, true) != 0)
continue;
Uri cachedUri = key.UriPrefix;
if (cachedUri.Scheme != uriPrefix.Scheme)
continue;
if (cachedUri.Port != uriPrefix.Port)
continue;
if (cachedUri.Host != uriPrefix.Host)
continue;
if (!absPath.StartsWith (key.AbsPath))
continue;
longestPrefix = key.Length;
result = (NetworkCredential) e.Value;
}
return result;
}
public IEnumerator GetEnumerator ()
{
return cache.Values.GetEnumerator ();
}
public void Add (Uri uriPrefix, string authType, NetworkCredential cred)
{
if (uriPrefix == null)
throw new ArgumentNullException ("uriPrefix");
if (authType == null)
throw new ArgumentNullException ("authType");
// throws ArgumentException when same key already exists.
cache.Add (new CredentialCacheKey (uriPrefix, authType), cred);
}
public void Remove (Uri uriPrefix, string authType)
{
if (uriPrefix == null)
throw new ArgumentNullException ("uriPrefix");
if (authType == null)
throw new ArgumentNullException ("authType");
cache.Remove (new CredentialCacheKey (uriPrefix, authType));
}
public NetworkCredential GetCredential (string host, int port, string authenticationType)
{
NetworkCredential result = null;
if (host == null || port < 0 || authenticationType == null)
return null;
IDictionaryEnumerator e = cacheForHost.GetEnumerator ();
while (e.MoveNext ()) {
CredentialCacheForHostKey key = e.Key as CredentialCacheForHostKey;
if (String.Compare (key.AuthType, authenticationType, true) != 0)
continue;
if (key.Host != host)
continue;
if (key.Port != port)
continue;
result = (NetworkCredential) e.Value;
}
return result;
}
public void Add (string host, int port, string authenticationType, NetworkCredential credential)
{
if (host == null)
throw new ArgumentNullException("host");
if (port < 0)
throw new ArgumentOutOfRangeException("port");
if (authenticationType == null)
throw new ArgumentOutOfRangeException("authenticationType");
cacheForHost.Add (new CredentialCacheForHostKey (host, port, authenticationType), credential);
}
public void Remove (string host, int port, string authenticationType)
{
if (host == null)
return;
if (authenticationType == null)
return;
cacheForHost.Remove (new CredentialCacheForHostKey (host, port, authenticationType));
}
class CredentialCacheKey {
Uri uriPrefix;
string authType;
string absPath;
int len;
int hash;
internal CredentialCacheKey (Uri uriPrefix, string authType)
{
this.uriPrefix = uriPrefix;
this.authType = authType;
this.absPath = uriPrefix.AbsolutePath;
this.absPath = absPath.Substring (0, absPath.LastIndexOf ('/'));
this.len = uriPrefix.AbsoluteUri.Length;
this.hash = uriPrefix.GetHashCode ()
+ authType.GetHashCode ();
}
public int Length {
get { return len; }
}
public string AbsPath {
get { return absPath; }
}
public Uri UriPrefix {
get { return uriPrefix; }
}
public string AuthType {
get { return authType; }
}
public override int GetHashCode ()
{
return hash;
}
public override bool Equals (object obj)
{
CredentialCacheKey key = obj as CredentialCacheKey;
return ((key != null) && (this.hash == key.hash));
}
public override string ToString ()
{
return absPath + " : " + authType + " : len=" + len;
}
}
class CredentialCacheForHostKey {
string host;
int port;
string authType;
int hash;
internal CredentialCacheForHostKey (string host, int port, string authType)
{
this.host = host;
this.port = port;
this.authType = authType;
this.hash = host.GetHashCode ()
+ port.GetHashCode ()
+ authType.GetHashCode ();
}
public string Host {
get { return host; }
}
public int Port {
get { return port; }
}
public string AuthType {
get { return authType; }
}
public override int GetHashCode ()
{
return hash;
}
public override bool Equals (object obj)
{
CredentialCacheForHostKey key = obj as CredentialCacheForHostKey;
return ((key != null) && (this.hash == key.hash));
}
public override string ToString ()
{
return host + " : " + authType;
}
}
}
}

View File

@@ -0,0 +1,39 @@
//
// System.Net.DecompressionMethods.cs
//
// Author:
// Dick Porter (dick@ximian.com)
//
// Copyright (C) 2007 Novell, Inc. (http://www.novell.com)
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
namespace System.Net
{
[Flags]
public enum DecompressionMethods {
None = 0,
GZip = 1,
Deflate = 2
}
}

View File

@@ -0,0 +1,57 @@
//
// System.Net.DefaultCertificatePolicy: Default policy applicable to
//
// Authors:
// Sebastien Pouliot <sebastien@ximian.com>
//
// Copyright (C) 2004 Novell (http://www.novell.com)
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System.Security.Cryptography.X509Certificates;
namespace System.Net {
internal class DefaultCertificatePolicy : ICertificatePolicy {
// This is the same default policy as used by the .NET
// framework. It accepts valid certificates and (valid
// but) expired certificates.
public bool CheckValidationResult (ServicePoint point, X509Certificate certificate, WebRequest request, int certificateProblem)
{
#if SECURITY_DEP
// If using default policy and the new callback is there, ignore this
if (ServicePointManager.ServerCertificateValidationCallback != null)
return true;
#endif
switch (certificateProblem) {
case 0: // No error
case -2146762495: // CERT_E_EXPIRED 0x800B0101 (WinError.h)
return true;
default:
return false;
}
}
}
}

View File

@@ -0,0 +1,460 @@
//
// System.Net.DigestClient.cs
//
// Authors:
// Greg Reinacker (gregr@rassoc.com)
// Sebastien Pouliot (spouliot@motus.com)
// Gonzalo Paniagua Javier (gonzalo@ximian.com
//
// Copyright 2002-2003 Greg Reinacker, Reinacker & Associates, Inc. All rights reserved.
// Portions (C) 2003 Motus Technologies Inc. (http://www.motus.com)
// (c) 2003 Novell, Inc. (http://www.novell.com)
//
// Original (server-side) source code available at
// http://www.rassoc.com/gregr/weblog/stories/2002/07/09/webServicesSecurityHttpDigestAuthenticationWithoutActiveDirectory.html
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections;
using System.Collections.Specialized;
using System.IO;
using System.Net;
using System.Security.Cryptography;
using System.Text;
namespace System.Net
{
//
// This works with apache mod_digest
//TODO:
// MD5-sess
// qop (auth-int)
//
// See RFC 2617 for details.
//
class DigestHeaderParser
{
string header;
int length;
int pos;
static string [] keywords = { "realm", "opaque", "nonce", "algorithm", "qop" };
string [] values = new string [keywords.Length];
public DigestHeaderParser (string header)
{
this.header = header.Trim ();
}
public string Realm {
get { return values [0]; }
}
public string Opaque {
get { return values [1]; }
}
public string Nonce {
get { return values [2]; }
}
public string Algorithm {
get { return values [3]; }
}
public string QOP {
get { return values [4]; }
}
public bool Parse ()
{
if (!header.ToLower ().StartsWith ("digest "))
return false;
pos = 6;
length = this.header.Length;
while (pos < length) {
string key, value;
if (!GetKeywordAndValue (out key, out value))
return false;
SkipWhitespace ();
if (pos < length && header [pos] == ',')
pos++;
int idx = Array.IndexOf (keywords, (key));
if (idx == -1)
continue;
if (values [idx] != null)
return false;
values [idx] = value;
}
if (Realm == null || Nonce == null)
return false;
return true;
}
void SkipWhitespace ()
{
char c = ' ';
while (pos < length && (c == ' ' || c == '\t' || c == '\r' || c == '\n')) {
c = header [pos++];
}
pos--;
}
string GetKey ()
{
SkipWhitespace ();
int begin = pos;
while (pos < length && header [pos] != '=') {
pos++;
}
string key = header.Substring (begin, pos - begin).Trim ().ToLower ();
return key;
}
bool GetKeywordAndValue (out string key, out string value)
{
key = null;
value = null;
key = GetKey ();
if (pos >= length)
return false;
SkipWhitespace ();
if (pos + 1 >= length || header [pos++] != '=')
return false;
SkipWhitespace ();
// note: Apache doesn't use " in all case (like algorithm)
if (pos + 1 >= length)
return false;
bool useQuote = false;
if (header [pos] == '"') {
pos++;
useQuote = true;
}
int beginQ = pos;
if (useQuote) {
pos = header.IndexOf ('"', pos);
if (pos == -1)
return false;
} else {
do {
char c = header [pos];
if (c == ',' || c == ' ' || c == '\t' || c == '\r' || c == '\n')
break;
} while (++pos < length);
if (pos >= length && beginQ == pos)
return false;
}
value = header.Substring (beginQ, pos - beginQ);
pos += 2;
return true;
}
}
class DigestSession
{
static RandomNumberGenerator rng;
DateTime lastUse;
static DigestSession ()
{
rng = RandomNumberGenerator.Create ();
}
private int _nc;
private HashAlgorithm hash;
private DigestHeaderParser parser;
private string _cnonce;
public DigestSession ()
{
_nc = 1;
lastUse = DateTime.Now;
}
public string Algorithm {
get { return parser.Algorithm; }
}
public string Realm {
get { return parser.Realm; }
}
public string Nonce {
get { return parser.Nonce; }
}
public string Opaque {
get { return parser.Opaque; }
}
public string QOP {
get { return parser.QOP; }
}
public string CNonce {
get {
if (_cnonce == null) {
// 15 is a multiple of 3 which is better for base64 because it
// wont end with '=' and risk messing up the server parsing
byte[] bincnonce = new byte [15];
rng.GetBytes (bincnonce);
_cnonce = Convert.ToBase64String (bincnonce);
Array.Clear (bincnonce, 0, bincnonce.Length);
}
return _cnonce;
}
}
public bool Parse (string challenge)
{
parser = new DigestHeaderParser (challenge);
if (!parser.Parse ()) {
return false;
}
// build the hash object (only MD5 is defined in RFC2617)
if ((parser.Algorithm == null) || (parser.Algorithm.ToUpper ().StartsWith ("MD5")))
hash = MD5.Create ();
return true;
}
private string HashToHexString (string toBeHashed)
{
if (hash == null)
return null;
hash.Initialize ();
byte[] result = hash.ComputeHash (Encoding.ASCII.GetBytes (toBeHashed));
StringBuilder sb = new StringBuilder ();
foreach (byte b in result)
sb.Append (b.ToString ("x2"));
return sb.ToString ();
}
private string HA1 (string username, string password)
{
string ha1 = String.Format ("{0}:{1}:{2}", username, Realm, password);
if (Algorithm != null && Algorithm.ToLower () == "md5-sess")
ha1 = String.Format ("{0}:{1}:{2}", HashToHexString (ha1), Nonce, CNonce);
return HashToHexString (ha1);
}
private string HA2 (HttpWebRequest webRequest)
{
string ha2 = String.Format ("{0}:{1}", webRequest.Method, webRequest.RequestUri.PathAndQuery);
if (QOP == "auth-int") {
// TODO
// ha2 += String.Format (":{0}", hentity);
}
return HashToHexString (ha2);
}
private string Response (string username, string password, HttpWebRequest webRequest)
{
string response = String.Format ("{0}:{1}:", HA1 (username, password), Nonce);
if (QOP != null)
response += String.Format ("{0}:{1}:{2}:", _nc.ToString ("X8"), CNonce, QOP);
response += HA2 (webRequest);
return HashToHexString (response);
}
public Authorization Authenticate (WebRequest webRequest, ICredentials credentials)
{
if (parser == null)
throw new InvalidOperationException ();
HttpWebRequest request = webRequest as HttpWebRequest;
if (request == null)
return null;
lastUse = DateTime.Now;
NetworkCredential cred = credentials.GetCredential (request.RequestUri, "digest");
if (cred == null)
return null;
string userName = cred.UserName;
if (userName == null || userName == "")
return null;
string password = cred.Password;
StringBuilder auth = new StringBuilder ();
auth.AppendFormat ("Digest username=\"{0}\", ", userName);
auth.AppendFormat ("realm=\"{0}\", ", Realm);
auth.AppendFormat ("nonce=\"{0}\", ", Nonce);
auth.AppendFormat ("uri=\"{0}\", ", request.Address.PathAndQuery);
if (Algorithm != null) { // hash algorithm (only MD5 in RFC2617)
auth.AppendFormat ("algorithm=\"{0}\", ", Algorithm);
}
auth.AppendFormat ("response=\"{0}\", ", Response (userName, password, request));
if (QOP != null) { // quality of protection (server decision)
auth.AppendFormat ("qop=\"{0}\", ", QOP);
}
lock (this) {
// _nc MUST NOT change from here...
// number of request using this nonce
if (QOP != null) {
auth.AppendFormat ("nc={0:X8}, ", _nc);
_nc++;
}
// until here, now _nc can change
}
if (CNonce != null) // opaque value from the client
auth.AppendFormat ("cnonce=\"{0}\", ", CNonce);
if (Opaque != null) // exact same opaque value as received from server
auth.AppendFormat ("opaque=\"{0}\", ", Opaque);
auth.Length -= 2; // remove ", "
return new Authorization (auth.ToString ());
}
public DateTime LastUse {
get { return lastUse; }
}
}
class DigestClient : IAuthenticationModule
{
static readonly Hashtable cache = Hashtable.Synchronized (new Hashtable ());
static Hashtable Cache {
get {
lock (cache.SyncRoot) {
CheckExpired (cache.Count);
}
return cache;
}
}
static void CheckExpired (int count)
{
if (count < 10)
return;
DateTime t = DateTime.MaxValue;
DateTime now = DateTime.Now;
ArrayList list = null;
foreach (int key in cache.Keys) {
DigestSession elem = (DigestSession) cache [key];
if (elem.LastUse < t &&
(elem.LastUse - now).Ticks > TimeSpan.TicksPerMinute * 10) {
t = elem.LastUse;
if (list == null)
list = new ArrayList ();
list.Add (key);
}
}
if (list != null) {
foreach (int k in list)
cache.Remove (k);
}
}
// IAuthenticationModule
public Authorization Authenticate (string challenge, WebRequest webRequest, ICredentials credentials)
{
if (credentials == null || challenge == null)
return null;
string header = challenge.Trim ();
if (header.ToLower ().IndexOf ("digest") == -1)
return null;
HttpWebRequest request = webRequest as HttpWebRequest;
if (request == null)
return null;
DigestSession currDS = new DigestSession();
if (!currDS.Parse (challenge))
return null;
int hashcode = request.Address.GetHashCode () ^ credentials.GetHashCode () ^ currDS.Nonce.GetHashCode ();
DigestSession ds = (DigestSession) Cache [hashcode];
bool addDS = (ds == null);
if (addDS)
ds = currDS;
else if (!ds.Parse (challenge))
return null;
if (addDS)
Cache.Add (hashcode, ds);
return ds.Authenticate (webRequest, credentials);
}
public Authorization PreAuthenticate (WebRequest webRequest, ICredentials credentials)
{
HttpWebRequest request = webRequest as HttpWebRequest;
if (request == null)
return null;
if (credentials == null)
return null;
int hashcode = request.Address.GetHashCode () ^ credentials.GetHashCode ();
DigestSession ds = (DigestSession) Cache [hashcode];
if (ds == null)
return null;
return ds.Authenticate (webRequest, credentials);
}
public string AuthenticationType {
get { return "Digest"; }
}
public bool CanPreAuthenticate {
get { return true; }
}
}
}

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More