Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

This commit was manufactured by cvs2svn to create tag 'MCS_0_29'.

svn path=/tags/MCS_0_29/mcs/; revision=20653
  • Loading branch information...
commit 6e43a5d927ef22ded84720ba9497b8f54f2ef8a4 12 parents 0c047b7 + 0fae05d + f204bdc + e61457e + 4e4824a + af3e77e + 24375f1 + 4094303 + 68cbdfe + 860e2b7 + 3654067 + 35dc226
nobody authored
Showing with 2,699 additions and 555 deletions.
  1. +1 −1  mcs/class/Makefile
  2. +127 −0 mcs/class/Mono.Security/Mono.Security.Cryptography/MD5SHA1CryptoServiceProvider.cs
  3. +37 −0 mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsCompressionMethod.cs
  4. +369 −0 mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsNetworkStream.cs
  5. +34 −0 mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsProtocol.cs
  6. +265 −0 mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSession.cs
  7. +289 −0 mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSessionContext.cs
  8. +218 −0 mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSessionSettings.cs
  9. +664 −0 mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSocket.cs
  10. +21 −0 mcs/class/System.Data.ObjectSpaces/System.Data.ObjectSpaces/PersistenceErrorBehaviour.cs
  11. +23 −0 mcs/class/System.Data.ObjectSpaces/System.Data.ObjectSpaces/PersisteneceErrorType.cs
  12. +8 −10 mcs/class/System.Data/System.Data.Odbc/ChangeLog
  13. +1 −33 mcs/class/System.Data/System.Data.Odbc/OdbcTransaction.cs
  14. +0 −7 mcs/class/System.Web/System.Web.Compilation/ChangeLog
  15. +0 −12 mcs/class/System.Web/System.Web.Compilation/PageCompiler.cs
  16. +0 −5 mcs/class/System.Web/System.Web.UI.WebControls/ChangeLog
  17. +4 −1 mcs/class/System.Web/System.Web.UI.WebControls/CheckBoxList.cs
  18. +0 −17 mcs/class/System.Web/System.Web.UI/ChangeLog
  19. +485 −11 mcs/class/System.Web/System.Web.UI/LosFormatter.cs
  20. +1 −1  mcs/class/System.Web/System.Web.UI/ObjectStateFormatter.cs
  21. +22 −22 mcs/class/System.Web/System.Web.UI/Page.cs
  22. +13 −100 mcs/class/System.Web/System.Web.UI/PageParser.cs
  23. +42 −0 mcs/class/System.Web/System.Web.UI/TODO
  24. +0 −5 mcs/class/System.Web/System.Web.Util/ChangeLog
  25. +8 −9 mcs/class/System.Web/System.Web.Util/UrlUtils.cs
  26. +37 −0 mcs/class/System/Test/system_linux_test.args
  27. +0 −17 mcs/class/corlib/System.Collections/ChangeLog
  28. +17 −11 mcs/class/corlib/System.Collections/Queue.cs
  29. +0 −25 mcs/class/corlib/System.Reflection/common.src
  30. +0 −4 mcs/class/corlib/Test/System.Collections/ChangeLog
  31. +13 −264 mcs/class/corlib/Test/System.Collections/QueueTest.cs
View
2  mcs/class/Makefile
@@ -43,7 +43,7 @@ SUBDIRS = \
ICSharpCode.SharpZipLib \
ByteFX.Data \
Commons.Xml.Relaxng \
- Novell.Directory.Ldap \
+ Mono.Directory.LDAP \
Mono.Security.Win32 \
Novell.Directory.Ldap \
System.DirectoryServices \
View
127 mcs/class/Mono.Security/Mono.Security.Cryptography/MD5SHA1CryptoServiceProvider.cs
@@ -0,0 +1,127 @@
+/* Transport Security Layer (TLS)
+ * Copyright (c) 2003 Carlos Guzmán Álvarez
+ *
+ * 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.Security.Cryptography;
+
+namespace Mono.Security.Cryptography
+{
+ internal class MD5SHA1CryptoServiceProvider : HashAlgorithm
+ {
+ #region FIELDS
+
+ private HashAlgorithm md5;
+ private HashAlgorithm sha;
+ private bool hashing;
+
+ #endregion
+
+ #region CONSTRUCTORS
+
+ public MD5SHA1CryptoServiceProvider()
+ {
+ this.md5 = new MD5CryptoServiceProvider();
+ this.sha = new SHA1CryptoServiceProvider();
+
+ // Set HashSizeValue
+ this.HashSizeValue = this.md5.HashSize + this.sha.HashSize;
+ }
+
+ #endregion
+
+ #region METHODS
+
+ public override void Initialize()
+ {
+ this.md5.Initialize();
+ this.sha.Initialize();
+ this.hashing = false;
+ }
+
+ protected override byte[] HashFinal()
+ {
+ if (!hashing)
+ {
+ this.hashing = true;
+ }
+ // Finalize the original hash
+ this.md5.TransformFinalBlock(new byte[0], 0, 0);
+ this.sha.TransformFinalBlock(new byte[0], 0, 0);
+
+ byte[] hash = new byte[36];
+
+ System.Array.Copy(this.md5.Hash, 0, hash, 0, 16);
+ System.Array.Copy(this.sha.Hash, 0, hash, 16, 20);
+
+ return hash;
+ }
+
+ protected override void HashCore(
+ byte[] array,
+ int ibStart,
+ int cbSize)
+ {
+ if (!hashing)
+ {
+ hashing = true;
+ }
+ this.md5.TransformBlock(array, ibStart, cbSize, array, ibStart);
+ this.sha.TransformBlock(array, ibStart, cbSize, array, ibStart);
+ }
+
+ public byte[] CreateSignature(RSA rsa)
+ {
+ if (rsa == null)
+ {
+ throw new CryptographicUnexpectedOperationException ("missing key");
+ }
+
+ #warning "MD5SHA1 hash is not supported by .NET"
+ RSAPKCS1SignatureFormatter f = new RSAPKCS1SignatureFormatter(rsa);
+ f.SetHashAlgorithm("MD5SHA1");
+
+ return f.CreateSignature(this.Hash);
+ }
+
+ public bool VerifySignature(RSA rsa, byte[] rgbSignature)
+ {
+ if (rsa == null)
+ {
+ throw new CryptographicUnexpectedOperationException ("missing key");
+ }
+ if (rgbSignature == null)
+ {
+ throw new ArgumentNullException ("rgbSignature");
+ }
+
+ #warning "MD5SHA1 hash is not supported by .NET"
+ RSAPKCS1SignatureDeformatter d = new RSAPKCS1SignatureDeformatter(rsa);
+ d.SetHashAlgorithm("MD5SHA1");
+
+ return d.VerifySignature(this.Hash, rgbSignature);
+ }
+
+ #endregion
+ }
+}
View
37 mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsCompressionMethod.cs
@@ -0,0 +1,37 @@
+/* Transport Security Layer (TLS)
+ * Copyright (c) 2003 Carlos Guzmán Álvarez
+ *
+ * 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;
+
+namespace Mono.Security.Protocol.Tls
+{
+ // Information about compression methods allowed by TLS
+ // can be found in:
+ // draft-ietf-tls-compression-05.txt (http://www.ietf.org/internet-drafts/draft-ietf-tls-compression-05.txt)
+ public enum TlsCompressionMethod : byte
+ {
+ None = 0,
+ Zlib = 1
+ }
+}
View
369 mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsNetworkStream.cs
@@ -0,0 +1,369 @@
+/* Transport Security Layer (TLS)
+ * Copyright (c) 2003 Carlos Guzmán Álvarez
+ *
+ * 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.IO;
+using System.Net;
+using System.Net.Sockets;
+
+namespace Mono.Security.Protocol.Tls
+{
+ public class TlsNetworkStream : Stream, IDisposable
+ {
+ #region PROPERTIES
+
+ private TlsSocket socket;
+ private bool ownsSocket;
+ private bool canRead;
+ private bool canWrite;
+ private bool disposed;
+
+ #endregion
+
+ #region PROPERTIES
+
+ public override bool CanRead
+ {
+ get { return canRead; }
+ }
+
+ public override bool CanSeek
+ {
+ get { return false; }
+ }
+
+ public override bool CanWrite
+ {
+ get { return canWrite; }
+ }
+
+ public override long Length
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ public override long Position
+ {
+ get { throw new NotSupportedException(); }
+ set { throw new NotSupportedException(); }
+
+ }
+
+ public bool DataAvailable
+ {
+ get
+ {
+ if (socket == null)
+ {
+ throw new IOException();
+ }
+
+ if (this.socket.Session.IsSecure)
+ {
+ if ((this.socket.InputBuffer.Length - this.socket.InputBuffer.Position) > 0)
+ {
+ return true;
+ }
+ }
+
+ // If there are bytes in the socket buffer return true
+ // otherwise false
+ return this.socket.Available != 0;
+ }
+ }
+
+ #endregion
+
+ #region DESTRUCTOR
+
+ ~TlsNetworkStream()
+ {
+ this.Dispose(false);
+ }
+
+ #endregion
+
+ #region IDISPOSABLE
+
+ void IDisposable.Dispose()
+ {
+ this.Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!disposed)
+ {
+ if (disposing)
+ {
+ if (this.socket != null)
+ {
+ if (this.ownsSocket)
+ {
+ try
+ {
+ this.socket.Shutdown(SocketShutdown.Both);
+ }
+ catch{}
+ finally
+ {
+ this.socket.Close();
+ }
+ }
+ }
+ this.ownsSocket = false;
+ this.canRead = false;
+ this.canWrite = false;
+ this.socket = null;
+ }
+
+ disposed = true;
+ }
+ }
+
+ #endregion
+
+ #region PROTECTED_PROPERTIES
+
+ protected bool Readable
+ {
+ get { return this.canRead; }
+ set { this.canRead = value;}
+ }
+
+ protected TlsSocket Socket
+ {
+ get { return socket; }
+ }
+
+ protected bool Writeable
+ {
+ get { return this.canWrite; }
+ set { this.canWrite = value; }
+ }
+
+ #endregion
+
+ #region CONSTRUCTORS
+
+ public TlsNetworkStream(TlsSocket socket)
+ : this(socket, FileAccess.ReadWrite, false)
+ {
+ }
+
+ public TlsNetworkStream(TlsSocket socket, bool ownsSocket)
+ : this(socket, FileAccess.ReadWrite, ownsSocket)
+ {
+ }
+
+ public TlsNetworkStream(TlsSocket socket, FileAccess access)
+ : this(socket, FileAccess.ReadWrite, false)
+ {
+ }
+
+ public TlsNetworkStream(TlsSocket socket, FileAccess access, bool ownsSocket)
+ {
+ if (socket == null)
+ {
+ throw new ArgumentNullException("socket is a null reference.");
+ }
+ if (!socket.Blocking)
+ {
+ throw new IOException("socket is in a nonblocking state.");
+ }
+ if (socket.SocketType != SocketType.Stream)
+ {
+ throw new IOException("The SocketType property of socket is not SocketType.Stream.");
+ }
+ if (!socket.Connected)
+ {
+ throw new IOException("socket is not connected.");
+ }
+
+ this.socket = socket;
+ this.ownsSocket = ownsSocket;
+ switch (access)
+ {
+ case FileAccess.Read:
+ this.canRead = true;
+ break;
+
+ case FileAccess.ReadWrite:
+ this.canRead = true;
+ this.canWrite = true;
+ break;
+
+ case FileAccess.Write:
+ this.canWrite = true;
+ break;
+ }
+ }
+
+ #endregion
+
+ #region METHODS
+
+ public override IAsyncResult BeginRead(
+ byte[] buffer,
+ int offset,
+ int count,
+ AsyncCallback callback,
+ object state)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override IAsyncResult BeginWrite(
+ byte[] buffer,
+ int offset,
+ int count,
+ AsyncCallback callback,
+ object state)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override int EndRead(IAsyncResult asyncResult)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override void EndWrite(IAsyncResult asyncResult)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override void Close()
+ {
+ ((IDisposable)this).Dispose();
+ }
+
+ public override void Flush()
+ {
+ }
+
+ public override int Read(byte[] buffer, int offset, int size)
+ {
+ if (buffer == null)
+ {
+ throw new ArgumentNullException("buffer is a null reference.");
+ }
+ if (offset < 0)
+ {
+ throw new ArgumentOutOfRangeException("offset is less than 0.");
+ }
+ if (offset > buffer.Length)
+ {
+ throw new ArgumentOutOfRangeException("offset is greater than the length of buffer.");
+ }
+ if (size < 0)
+ {
+ throw new ArgumentOutOfRangeException("size is less than 0.");
+ }
+ if (size > (buffer.Length - offset))
+ {
+ throw new ArgumentOutOfRangeException("size is less than the length of buffer minus the value of the offset parameter.");
+ }
+ if (disposed)
+ {
+ throw new ObjectDisposedException("The NetworkStream is closed.");
+ }
+ if (!socket.Connected)
+ {
+ throw new IOException("The underlying Socket is closed.");
+ }
+
+ try
+ {
+ return socket.Receive(buffer, offset, size, SocketFlags.None);
+ }
+ catch (TlsException ex)
+ {
+ throw ex;
+ }
+ catch (Exception ex)
+ {
+ throw new IOException("IO exception during read.", ex);
+ }
+ }
+
+ public override long Seek(long offset, SeekOrigin origin)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override void SetLength(long value)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override void Write(byte[] buffer, int offset, int size)
+ {
+ if (buffer == null)
+ {
+ throw new ArgumentNullException("buffer is a null reference.");
+ }
+ if (offset < 0)
+ {
+ throw new ArgumentOutOfRangeException("offset is less than 0.");
+ }
+ if (offset > buffer.Length)
+ {
+ throw new ArgumentOutOfRangeException("offset is greater than the length of buffer.");
+ }
+ if (size < 0)
+ {
+ throw new ArgumentOutOfRangeException("size is less than 0.");
+ }
+ if (size > (buffer.Length - offset))
+ {
+ throw new ArgumentOutOfRangeException("size is less than the length of buffer minus the value of the offset parameter.");
+ }
+ if (disposed)
+ {
+ throw new ObjectDisposedException("The NetworkStream is closed.");
+ }
+ if (!socket.Connected)
+ {
+ throw new IOException("The underlying Socket is closed.");
+ }
+
+ try
+ {
+ socket.Send(buffer, offset, size, SocketFlags.None);
+ }
+ catch (TlsException ex)
+ {
+ throw ex;
+ }
+ catch (Exception ex)
+ {
+ throw new IOException("IO exception during Write.", ex);
+ }
+ }
+
+ #endregion
+ }
+}
View
34 mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsProtocol.cs
@@ -0,0 +1,34 @@
+/* Transport Security Layer (TLS)
+ * Copyright (c) 2003 Carlos Guzmán Álvarez
+ *
+ * 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;
+
+namespace Mono.Security.Protocol.Tls
+{
+ public enum TlsProtocol : short
+ {
+ Tls1 = (0x03 << 8) | 0x01,
+ Ssl3 = (0x03 << 8) | 0x00
+ }
+}
View
265 mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSession.cs
@@ -0,0 +1,265 @@
+/* Transport Security Layer (TLS)
+ * Copyright (c) 2003 Carlos Guzmán Álvarez
+ *
+ * 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.IO;
+using System.Collections;
+using System.Text;
+using System.Net;
+using System.Net.Sockets;
+using System.Security.Cryptography;
+
+using Mono.Security.Protocol.Tls.Alerts;
+
+namespace Mono.Security.Protocol.Tls
+{
+ public sealed class TlsSession
+ {
+ #region EVENTS
+
+ public event TlsWarningAlertEventHandler WarningAlert;
+
+ #endregion
+
+ #region FIELDS
+
+ private byte[] sessionId;
+ private TlsSessionContext context;
+ private TlsSessionSettings settings;
+ private TlsSocket socket;
+ private TlsNetworkStream networkStream;
+ private bool isSecure;
+ private TlsSessionState state;
+
+ #endregion
+
+ #region PROPERTIES
+
+ public byte[] SessionId
+ {
+ get { return sessionId; }
+ }
+
+ public TlsNetworkStream NetworkStream
+ {
+ get { return networkStream; }
+ }
+
+ public TlsSessionState State
+ {
+ get { return state; }
+ }
+
+ #endregion
+
+ #region INTERNAL_PROPERTIES
+
+ internal TlsSessionContext Context
+ {
+ get { return context; }
+ }
+
+ internal bool IsSecure
+ {
+ get { return isSecure; }
+ set { isSecure = value; }
+ }
+
+ internal TlsSessionSettings Settings
+ {
+ get { return settings; }
+ }
+
+ #endregion
+
+ #region CONSTRUCTORS
+
+ public TlsSession(TlsSessionSettings settings)
+ {
+ this.settings = settings;
+ this.context = new TlsSessionContext();
+ this.sessionId = new byte[0];
+
+ // Initialize socket for connection
+ this.initializeSocket();
+ }
+
+ #endregion
+
+ #region EXCEPTION_METHODS
+
+ internal TlsException CreateException(TlsAlertLevel alertLevel, TlsAlertDescription alertDesc)
+ {
+ return CreateException(TlsAlert.GetAlertMessage(alertDesc));
+ }
+
+ internal TlsException CreateException(string format, params object[] args)
+ {
+ StringBuilder message = new StringBuilder();
+ message.AppendFormat(format, args);
+
+ return CreateException(message.ToString());
+ }
+
+ internal TlsException CreateException(string message)
+ {
+ this.state = TlsSessionState.Broken;
+
+ // Throw an exception will made the connection unavailable
+ // for this both streams will be closed
+ closeStreams();
+
+ return new TlsException(message);
+ }
+
+ #endregion
+
+ #region METHODS
+
+ public void Open()
+ {
+ try
+ {
+ this.context.Protocol = settings.Protocol;
+ this.context.CompressionMethod = settings.CompressionMethod;
+ this.context.SupportedCiphers = TlsCipherSuiteFactory.GetSupportedCiphers(context.Protocol);
+ this.state = TlsSessionState.OpeningSecure;
+ this.socket.DoHandshake();
+ this.state = TlsSessionState.OpenSecure;
+ }
+ catch (TlsException ex)
+ {
+ this.state = TlsSessionState.Broken;
+ throw ex;
+ }
+ catch (Exception ex)
+ {
+ this.state = TlsSessionState.Broken;
+ this.closeStreams();
+ throw ex;
+ }
+ }
+
+ public void Close()
+ {
+ try
+ {
+ this.state = TlsSessionState.Closing;
+
+ if (isSecure)
+ {
+ TlsCloseNotifyAlert alert = new TlsCloseNotifyAlert(this);
+
+ // Write close notify
+ this.socket.SendAlert(alert);
+
+ // Check that the session is finished by the client and by server
+ if (!this.context.ConnectionEnd)
+ {
+ throw new TlsException("Invalid session termination");
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ this.state = TlsSessionState.Broken;
+ throw ex;
+ }
+ finally
+ {
+ // Close streams
+ closeStreams();
+
+ this.state = TlsSessionState.Closed;
+ }
+ }
+
+ #endregion
+
+ #region INTERNAL_METHODS
+
+ internal void RaiseWarningAlert(TlsAlertLevel level, TlsAlertDescription description)
+ {
+ if (WarningAlert != null)
+ {
+ WarningAlert(this, new TlsWarningAlertEventArgs(level, description));
+ }
+ }
+
+ internal void SetSessionId(byte[] sessionId)
+ {
+ this.sessionId = sessionId;
+ }
+
+ #endregion
+
+ #region PRIVATE_METHODS
+
+ private void initializeSocket()
+ {
+ try
+ {
+ this.state = TlsSessionState.Opening;
+
+ // Initialize socket
+ IPAddress hostadd = Dns.Resolve(settings.ServerName).AddressList[0];
+ IPEndPoint EPhost = new IPEndPoint(hostadd, settings.ServerPort);
+
+ // Create the socket
+ socket = new TlsSocket(
+ this,
+ AddressFamily.InterNetwork,
+ SocketType.Stream,
+ ProtocolType.IP);
+
+ // Make the socket to connect to the Server
+ socket.Connect(EPhost);
+ networkStream = new TlsNetworkStream(socket, true);
+
+ this.state = TlsSessionState.Open;
+ }
+ catch (Exception ex)
+ {
+ this.state = TlsSessionState.Broken;
+ throw ex;
+ }
+ }
+
+ private void closeStreams()
+ {
+ // Reset session state
+ this.context.IsActual = false;
+
+ // Close the socket and the networkStream
+ this.networkStream.Close();
+
+ // Reset session information
+ this.isSecure = false;
+ this.context = new TlsSessionContext();
+ this.sessionId = new byte[0];
+ }
+
+ #endregion
+ }
+}
View
289 mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSessionContext.cs
@@ -0,0 +1,289 @@
+/* Transport Security Layer (TLS)
+ * Copyright (c) 2003 Carlos Guzmán Álvarez
+ *
+ * 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.Security.Cryptography;
+
+using Mono.Security.Cryptography;
+using Mono.Security.Protocol.Tls.Handshake;
+
+namespace Mono.Security.Protocol.Tls
+{
+ internal class TlsSessionContext
+ {
+ #region FIELDS
+
+ // Protocol version
+ private TlsProtocol protocol;
+
+ // Compression method
+ private TlsCompressionMethod compressionMethod;
+
+ // Information sent and request by the server in the Handshake protocol
+ private TlsServerSettings serverSettings;
+
+ // Cipher suite information
+ private CipherSuite cipher;
+ private TlsCipherSuiteCollection supportedCiphers;
+
+ // Misc
+ private bool isActual;
+ private bool helloDone;
+ private bool handshakeFinished;
+ private bool connectionEnd;
+
+ // Sequence numbers
+ private long writeSequenceNumber;
+ private long readSequenceNumber;
+
+ // Random data
+ private byte[] clientRandom;
+ private byte[] serverRandom;
+ private byte[] randomCS;
+ private byte[] randomSC;
+
+ // Key information
+ private byte[] masterSecret;
+ private byte[] clientWriteMAC;
+ private byte[] serverWriteMAC;
+ private byte[] clientWriteKey;
+ private byte[] serverWriteKey;
+ private byte[] clientWriteIV;
+ private byte[] serverWriteIV;
+
+ // Handshake hashes
+ private TlsStream handshakeMessages;
+
+ #endregion
+
+ #region INTERNAL_CONSTANTS
+
+ internal const short MAX_FRAGMENT_SIZE = 16384; // 2^14
+
+ #endregion
+
+ #region PROPERTIES
+
+ public TlsProtocol Protocol
+ {
+ get { return this.protocol; }
+ set { this.protocol = value; }
+ }
+
+ public TlsCompressionMethod CompressionMethod
+ {
+ get { return this.compressionMethod; }
+ set { this.compressionMethod = value; }
+ }
+
+ public TlsServerSettings ServerSettings
+ {
+ get { return this.serverSettings; }
+ set { this.serverSettings = value; }
+ }
+
+ public bool IsActual
+ {
+ get { return this.isActual; }
+ set { this.isActual = value; }
+ }
+
+ public bool HelloDone
+ {
+ get { return helloDone; }
+ set { helloDone = value; }
+ }
+
+ public bool HandshakeFinished
+ {
+ get { return handshakeFinished; }
+ set { handshakeFinished = value; }
+ }
+
+ public bool ConnectionEnd
+ {
+ get { return this.connectionEnd; }
+ set { this.connectionEnd = value; }
+ }
+
+ public CipherSuite Cipher
+ {
+ get { return this.cipher; }
+ set { this.cipher = value; }
+ }
+
+ public TlsCipherSuiteCollection SupportedCiphers
+ {
+ get { return supportedCiphers; }
+ set { supportedCiphers = value; }
+ }
+
+ public TlsStream HandshakeMessages
+ {
+ get { return this.handshakeMessages; }
+ }
+
+ public long WriteSequenceNumber
+ {
+ get { return this.writeSequenceNumber; }
+ set { this.writeSequenceNumber = value; }
+ }
+
+ public long ReadSequenceNumber
+ {
+ get { return this.readSequenceNumber; }
+ set { this.readSequenceNumber = value; }
+ }
+
+ public byte[] ClientRandom
+ {
+ get { return this.clientRandom; }
+ set { this.clientRandom = value; }
+ }
+
+ public byte[] ServerRandom
+ {
+ get { return this.serverRandom; }
+ set { this.serverRandom = value; }
+ }
+
+ public byte[] RandomCS
+ {
+ get { return this.randomCS; }
+ set { this.randomCS = value; }
+ }
+
+ public byte[] RandomSC
+ {
+ get { return this.randomSC; }
+ set { this.randomSC = value; }
+ }
+
+ public byte[] MasterSecret
+ {
+ get { return this.masterSecret; }
+ set { this.masterSecret = value; }
+ }
+
+ public byte[] ClientWriteMAC
+ {
+ get { return this.clientWriteMAC; }
+ set { this.clientWriteMAC = value; }
+ }
+
+ public byte[] ServerWriteMAC
+ {
+ get { return this.serverWriteMAC; }
+ set { this.serverWriteMAC = value; }
+ }
+
+ public byte[] ClientWriteKey
+ {
+ get { return this.clientWriteKey; }
+ set { this.clientWriteKey = value; }
+ }
+
+ public byte[] ServerWriteKey
+ {
+ get { return this.serverWriteKey; }
+ set { this.serverWriteKey = value; }
+ }
+
+ public byte[] ClientWriteIV
+ {
+ get { return this.clientWriteIV; }
+ set { this.clientWriteIV = value; }
+ }
+
+ public byte[] ServerWriteIV
+ {
+ get { return this.serverWriteIV; }
+ set { this.serverWriteIV = value; }
+ }
+
+ #endregion
+
+ #region CONSTRUCTORS
+
+ public TlsSessionContext()
+ {
+ this.protocol = TlsProtocol.Tls1;
+ this.compressionMethod = TlsCompressionMethod.None;
+ this.serverSettings = new TlsServerSettings();
+ this.handshakeMessages = new TlsStream();
+ }
+
+ #endregion
+
+ #region METHODS
+
+ public int GetUnixTime()
+ {
+ DateTime now = DateTime.Now.ToUniversalTime();
+ TimeSpan unixTime = now.Subtract(new DateTime(1970, 1, 1));
+
+ return (int)unixTime.TotalSeconds;
+ }
+
+ public byte[] GetSecureRandomBytes(int count)
+ {
+ byte[] secureBytes = new byte[count];
+
+ RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
+ rng.GetNonZeroBytes(secureBytes);
+
+ return secureBytes;
+ }
+
+ public void ClearKeyInfo()
+ {
+ // Clear Master Secret
+ this.masterSecret = null;
+
+ // Clear client and server random
+ this.clientRandom = null;
+ this.serverRandom = null;
+ this.randomCS = null;
+ this.randomSC = null;
+
+ // Clear client keys
+ this.clientWriteKey = null;
+ this.clientWriteIV = null;
+
+ // Clear server keys
+ this.serverWriteKey = null;
+ this.serverWriteIV = null;
+
+ // Clear MAC keys if protocol is different than Ssl3
+ if (this.protocol != TlsProtocol.Ssl3)
+ {
+ this.clientWriteMAC = null;
+ this.serverWriteMAC = null;
+ }
+ }
+
+ #endregion
+ }
+}
View
218 mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSessionSettings.cs
@@ -0,0 +1,218 @@
+/* Transport Security Layer (TLS)
+ * Copyright (c) 2003 Carlos Guzmán Álvarez
+ *
+ * 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.Security.Cryptography.X509Certificates;
+
+namespace Mono.Security.Protocol.Tls
+{
+ public sealed class TlsSessionSettings
+ {
+ #region FIELDS
+
+ private string serverName;
+ private int serverPort;
+ private Encoding encoding;
+ private TlsProtocol protocol;
+ private TlsCompressionMethod compressionMethod;
+ private X509CertificateCollection certificates;
+
+ #endregion
+
+ #region PROPERTIES
+
+ public string ServerName
+ {
+ get { return serverName; }
+ set { serverName = value; }
+ }
+
+ public int ServerPort
+ {
+ get { return serverPort; }
+ set { serverPort = value; }
+ }
+
+ public Encoding Encoding
+ {
+ get { return encoding; }
+ set { encoding = value; }
+ }
+
+ public TlsProtocol Protocol
+ {
+ get { return protocol; }
+ set
+ {
+ if (value != TlsProtocol.Tls1 &&
+ value != TlsProtocol.Ssl3)
+ {
+ throw new NotSupportedException("Specified protocol is not supported");
+ }
+ protocol = value;
+ }
+ }
+
+ public TlsCompressionMethod CompressionMethod
+ {
+ get { return compressionMethod; }
+ set
+ {
+ if (value != TlsCompressionMethod.None)
+ {
+ throw new NotSupportedException("Specified compression method is not supported");
+ }
+ compressionMethod = value;
+ }
+ }
+
+ public X509CertificateCollection Certificates
+ {
+ get { return certificates; }
+ set { certificates = value; }
+ }
+
+ #endregion
+
+ #region CONSTRUCTORS
+
+ public TlsSessionSettings()
+ {
+ this.protocol = TlsProtocol.Tls1;
+ this.compressionMethod = TlsCompressionMethod.None;
+ this.certificates = new X509CertificateCollection();
+ this.serverName = "localhost";
+ this.serverPort = 443;
+ this.encoding = Encoding.Default;
+ }
+
+ public TlsSessionSettings(TlsProtocol protocol) : this()
+ {
+ this.Protocol = protocol;
+ }
+
+ public TlsSessionSettings(TlsProtocol protocol, Encoding encoding) : this(protocol)
+ {
+ this.encoding = encoding;
+ }
+
+ public TlsSessionSettings(string serverName) : this()
+ {
+ this.serverName = serverName;
+ }
+
+ public TlsSessionSettings(string serverName, Encoding encoding) : this()
+ {
+ this.serverName = serverName;
+ this.encoding = encoding;
+ }
+
+ public TlsSessionSettings(string serverName, int serverPort) : this()
+ {
+ this.serverName = serverName;
+ this.serverPort = serverPort;
+ }
+
+ public TlsSessionSettings(string serverName, int serverPort, Encoding encoding) : this()
+ {
+ this.serverName = serverName;
+ this.serverPort = serverPort;
+ this.encoding = encoding;
+ }
+
+ public TlsSessionSettings(TlsProtocol protocol, string serverName) : this(protocol)
+ {
+ this.serverName = serverName;
+ }
+
+ public TlsSessionSettings(TlsProtocol protocol, string serverName, Encoding encoding) : this(protocol)
+ {
+ this.serverName = serverName;
+ this.encoding = encoding;
+ }
+
+
+ public TlsSessionSettings(TlsProtocol protocol, string serverName, int serverPort) : this(protocol)
+ {
+ this.serverName = serverName;
+ this.serverPort = serverPort;
+ }
+
+ public TlsSessionSettings(TlsProtocol protocol, string serverName, int serverPort, Encoding encoding) : this(protocol)
+ {
+ this.serverName = serverName;
+ this.serverPort = serverPort;
+ this.encoding = encoding;
+ }
+
+ public TlsSessionSettings(TlsProtocol protocol, X509CertificateCollection certificates) : this(protocol)
+ {
+ this.certificates = certificates;
+ }
+
+ public TlsSessionSettings(TlsProtocol protocol, X509CertificateCollection certificates, Encoding encoding) : this(protocol)
+ {
+ this.certificates = certificates;
+ this.encoding = encoding;
+ }
+
+ public TlsSessionSettings(TlsProtocol protocol, X509CertificateCollection certificates, string serverName, int serverPort) : this(protocol)
+ {
+ this.certificates = certificates;
+ this.serverName = serverName;
+ this.serverPort = serverPort;
+ }
+
+ public TlsSessionSettings(TlsProtocol protocol, X509CertificateCollection certificates, string serverName, int serverPort, Encoding encoding) : this(protocol)
+ {
+ this.certificates = certificates;
+ this.serverName = serverName;
+ this.serverPort = serverPort;
+ this.encoding = encoding;
+ }
+
+ public TlsSessionSettings(TlsProtocol protocol, X509Certificate[] certificates)
+ : this(protocol, new X509CertificateCollection(certificates))
+ {
+ }
+
+ public TlsSessionSettings(TlsProtocol protocol, X509Certificate[] certificates, Encoding encoding)
+ : this(protocol, new X509CertificateCollection(certificates), encoding)
+ {
+ }
+
+ public TlsSessionSettings(TlsProtocol protocol, X509Certificate[] certificates, string serverName, int serverPort) :
+ this(protocol, new X509CertificateCollection(certificates), serverName, serverPort)
+ {
+ }
+
+ public TlsSessionSettings(TlsProtocol protocol, X509Certificate[] certificates, string serverName, int serverPort, Encoding encoding) :
+ this(protocol, new X509CertificateCollection(certificates), serverName, serverPort, encoding)
+ {
+ }
+
+ #endregion
+ }
+}
View
664 mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSocket.cs
@@ -0,0 +1,664 @@
+/* Transport Security Layer (TLS)
+ * Copyright (c) 2003 Carlos Guzmán Álvarez
+ *
+ * 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.IO;
+using System.Net;
+using System.Collections;
+using System.Net.Sockets;
+using System.Security.Cryptography;
+
+using Mono.Security.Protocol.Tls;
+using Mono.Security.Protocol.Tls.Alerts;
+using Mono.Security.Protocol.Tls.Handshake;
+using Mono.Security.Protocol.Tls.Handshake.Client;
+
+namespace Mono.Security.Protocol.Tls
+{
+ public sealed class TlsSocket : Socket
+ {
+ #region FIELDS
+
+ private TlsSession session;
+ private BufferedStream inputBuffer;
+
+ #endregion
+
+ #region PROPERTIES
+
+ internal TlsSession Session
+ {
+ get { return this.session; }
+ }
+
+ internal BufferedStream InputBuffer
+ {
+ get { return this.inputBuffer; }
+ }
+
+ #endregion
+
+ #region CONSTRUCTORS
+
+ private TlsSocket(
+ AddressFamily addressFamily,
+ SocketType socketType,
+ ProtocolType protocolType
+ ) : base(addressFamily, socketType, protocolType)
+ {
+ this.inputBuffer = new BufferedStream(new MemoryStream());
+ }
+
+ public TlsSocket(
+ TlsSession session,
+ AddressFamily addressFamily,
+ SocketType socketType,
+ ProtocolType protocolType
+ ) : this(addressFamily, socketType, protocolType)
+ {
+ this.session = session;
+ }
+
+ #endregion
+
+ #region REPLACED_METHODS
+
+ public new void Close()
+ {
+ this.resetBuffer();
+ base.Close();
+ if (this.session.State != TlsSessionState.Closing &&
+ this.session.State != TlsSessionState.Closed)
+ {
+ this.session.Close();
+ }
+ }
+
+ public new int Receive(byte[] buffer)
+ {
+ return this.Receive(buffer, 0, buffer != null ? buffer.Length : 0, SocketFlags.None);
+ }
+
+ public new int Receive(byte[] buffer, SocketFlags socketFlags)
+ {
+ return this.Receive(buffer, 0, buffer != null ? buffer.Length : 0, socketFlags);
+ }
+
+ public new int Receive(byte[] buffer, int size, SocketFlags socketFlags)
+ {
+ return this.Receive(buffer, 0, size, socketFlags);
+ }
+
+ public new int Receive(byte[] buffer, int offset, int size, SocketFlags socketFlags)
+ {
+ if (!this.session.IsSecure)
+ {
+ return base.Receive(buffer, offset, size, socketFlags);
+ }
+
+ // If actual buffer is full readed reset it
+ if (this.inputBuffer.Position == this.inputBuffer.Length)
+ {
+ this.resetBuffer();
+ }
+
+ // Check if we have space in the middle buffer
+ // if not Read next TLS record and update the inputBuffer
+ while ((this.inputBuffer.Length - this.inputBuffer.Position) < size)
+ {
+ // Read next record and write it into the inputBuffer
+ long position = this.inputBuffer.Position;
+ byte[] record = this.receiveRecord();
+
+ if (record.Length > 0)
+ {
+ // Write new data to the inputBuffer
+ this.inputBuffer.Seek(0, SeekOrigin.End);
+ this.inputBuffer.Write(record, 0, record.Length);
+
+ // Restore buffer position
+ this.inputBuffer.Seek(position, SeekOrigin.Begin);
+ }
+
+ if (base.Available == 0)
+ {
+ break;
+ }
+ }
+
+ return this.inputBuffer.Read(buffer, offset, size);
+ }
+
+ public new int Send(byte[] buffer)
+ {
+ return this.Send(buffer, 0, buffer != null ? buffer.Length : 0, SocketFlags.None);
+ }
+
+ public new int Send(byte[] buffer, SocketFlags socketFlags)
+ {
+ return this.Send(buffer, 0, buffer != null ? buffer.Length : 0, socketFlags);
+ }
+
+ public new int Send(byte[] buffer, int size, SocketFlags socketFlags)
+ {
+ return this.Send(buffer, 0, size, socketFlags);
+ }
+
+ public new int Send(byte[] buffer, int offset, int size, SocketFlags socketFlags)
+ {
+ if (!this.session.IsSecure)
+ {
+ return base.Send(buffer, offset, size, socketFlags);
+ }
+
+ // Send the buffer as a TLS record
+ byte[] recordData = new byte[size];
+ System.Array.Copy(buffer, offset, recordData, 0, size);
+
+ return this.sendRecord(TlsContentType.ApplicationData, recordData);
+ }
+
+ #endregion
+
+ #region TLS_RECORD_METHODS
+
+ private byte[] receiveRecord()
+ {
+ if (this.session.Context.ConnectionEnd)
+ {
+ throw this.session.CreateException("The session is finished and it's no longer valid.");
+ }
+
+ TlsContentType contentType = (TlsContentType)this.ReadByte();
+ TlsProtocol protocol = (TlsProtocol)this.ReadShort();
+ short length = this.ReadShort();
+
+ // Read Record data
+ int received = 0;
+ byte[] buffer = new byte[length];
+ while (received != length)
+ {
+ received += base.Receive(
+ buffer, received, buffer.Length - received, SocketFlags.None);
+ }
+
+ TlsStream message = new TlsStream(buffer);
+
+ // Check that the message has a valid protocol version
+ if (protocol != this.session.Context.Protocol)
+ {
+ throw session.CreateException("Invalid protocol version on message received from server");
+ }
+
+ // Decrypt message contents if needed
+ if (contentType == TlsContentType.Alert && length == 2)
+ {
+ }
+ else
+ {
+ if (session.Context.IsActual &&
+ contentType != TlsContentType.ChangeCipherSpec)
+ {
+ message = this.decryptRecordFragment(
+ contentType,
+ protocol,
+ message.ToArray());
+ }
+ }
+
+ byte[] result = message.ToArray();
+
+ // Process record
+ switch (contentType)
+ {
+ case TlsContentType.Alert:
+ this.processAlert((TlsAlertLevel)message.ReadByte(),
+ (TlsAlertDescription)message.ReadByte());
+ break;
+
+ case TlsContentType.ChangeCipherSpec:
+ // Reset sequence numbers
+ this.session.Context.ReadSequenceNumber = 0;
+ break;
+
+ case TlsContentType.ApplicationData:
+ break;
+
+ case TlsContentType.Handshake:
+ while (!message.EOF)
+ {
+ this.processHandshakeMessage(message);
+ }
+ // Update handshakes of current messages
+ this.session.Context.HandshakeMessages.Write(message.ToArray());
+ break;
+
+ default:
+ throw session.CreateException("Unknown record received from server.");
+ }
+
+ return result;
+ }
+
+ #endregion
+
+ #region TLS_CRYPTO_METHODS
+
+ private byte[] encryptRecordFragment(TlsContentType contentType, byte[] fragment)
+ {
+ // Calculate message MAC
+ byte[] mac = this.session.Context.Cipher.ComputeClientRecordMAC(contentType, fragment);
+
+ // Encrypt the message
+ byte[] ecr = this.session.Context.Cipher.EncryptRecord(fragment, mac);
+
+ // Set new IV
+ if (this.session.Context.Cipher.CipherMode == CipherMode.CBC)
+ {
+ byte[] iv = new byte[this.session.Context.Cipher.IvSize];
+ System.Array.Copy(ecr, ecr.Length - iv.Length, iv, 0, iv.Length);
+ this.session.Context.Cipher.UpdateClientCipherIV(iv);
+ }
+
+ // Update sequence number
+ this.session.Context.WriteSequenceNumber++;
+
+ return ecr;
+ }
+
+ private TlsStream decryptRecordFragment(TlsContentType contentType,
+ TlsProtocol protocol,
+ byte[] fragment)
+ {
+ byte[] dcrFragment = null;
+ byte[] dcrMAC = null;
+
+ // Decrypt message
+ this.session.Context.Cipher.DecryptRecord(fragment, ref dcrFragment, ref dcrMAC);
+
+ // Set new IV
+ if (this.session.Context.Cipher.CipherMode == CipherMode.CBC)
+ {
+ byte[] iv = new byte[session.Context.Cipher.IvSize];
+ System.Array.Copy(fragment, fragment.Length - iv.Length, iv, 0, iv.Length);
+ this.session.Context.Cipher.UpdateServerCipherIV(iv);
+ }
+
+ // Check MAC code
+ byte[] mac = this.session.Context.Cipher.ComputeServerRecordMAC(contentType, dcrFragment);
+
+ // Check that the mac is correct
+ if (mac.Length != dcrMAC.Length)
+ {
+ throw new TlsException("Invalid MAC received from server.");
+ }
+ for (int i = 0; i < mac.Length; i++)
+ {
+ if (mac[i] != dcrMAC[i])
+ {
+ throw new TlsException("Invalid MAC received from server.");
+ }
+ }
+
+ // Update sequence number
+ this.session.Context.ReadSequenceNumber++;
+
+ return new TlsStream(dcrFragment);
+ }
+
+ #endregion
+
+ #region TLS_SEND_METHODS
+
+ internal int SendAlert(TlsAlert alert)
+ {
+ // Write record
+ int bytesSent = this.sendRecord(TlsContentType.Alert, alert.ToArray());
+
+ // Update session
+ alert.UpdateSession();
+
+ // Reset message contents
+ alert.Reset();
+
+ return bytesSent;
+ }
+
+ private int sendRecord(TlsHandshakeType type)
+ {
+ TlsHandshakeMessage msg = createClientHandshakeMessage(type);
+
+ // Write record
+ int bytesSent = this.sendRecord(msg.ContentType, msg.EncodeMessage());
+
+ // Update session
+ msg.UpdateSession();
+
+ // Reset message contents
+ msg.Reset();
+
+ return bytesSent;
+ }
+
+ private int sendChangeCipherSpec()
+ {
+ // Send Change Cipher Spec message
+ int bytesSent = this.sendRecord(TlsContentType.ChangeCipherSpec, new byte[] {1});
+
+ // Reset sequence numbers
+ this.session.Context.WriteSequenceNumber = 0;
+
+ // Make the pending state to be the current state
+ this.session.Context.IsActual = true;
+
+ // Send Finished message
+ bytesSent += this.sendRecord(TlsHandshakeType.Finished);
+
+ return bytesSent;
+ }
+
+ private int sendRecord(TlsContentType contentType, byte[] recordData)
+ {
+ if (this.session.Context.ConnectionEnd)
+ {
+ throw this.session.CreateException("The session is finished and it's no longer valid.");
+ }
+
+ int bytesSent = 0;
+ byte[][] fragments = fragmentData(recordData);
+ for (int i = 0; i < fragments.Length; i++)
+ {
+ byte[] fragment = fragments[i];
+
+ if (this.session.Context.IsActual)
+ {
+ // Encrypt fragment
+ fragment = this.encryptRecordFragment(contentType, fragment);
+ }
+
+ // Write tls message
+ TlsStream record = new TlsStream();
+ record.Write((byte)contentType);
+ record.Write((short)this.session.Context.Protocol);
+ record.Write((short)fragment.Length);
+ record.Write(fragment);
+
+ // Write record
+ bytesSent += base.Send(record.ToArray());
+
+ // Reset record data
+ record.Reset();
+ }
+
+ return bytesSent;
+ }
+
+ private byte[][] fragmentData(byte[] messageData)
+ {
+ ArrayList d = new ArrayList();
+
+ int position = 0;
+
+ while (position < messageData.Length)
+ {
+ short fragmentLength = 0;
+ byte[] fragmentData;
+ if ((messageData.Length - position) > TlsSessionContext.MAX_FRAGMENT_SIZE)
+ {
+ fragmentLength = TlsSessionContext.MAX_FRAGMENT_SIZE;
+ }
+ else
+ {
+ fragmentLength = (short)(messageData.Length - position);
+ }
+ fragmentData = new byte[fragmentLength];
+
+ System.Array.Copy(messageData, position, fragmentData, 0, fragmentLength);
+
+ d.Add(fragmentData);
+
+ position += fragmentLength;
+ }
+
+ byte[][] result = new byte[d.Count][];
+ for (int i = 0; i < d.Count; i++)
+ {
+ result[i] = (byte[])d[i];
+ }
+
+ return result;
+ }
+
+ #endregion
+
+ #region MESSAGE_PROCESSING
+
+ private void processHandshakeMessage(TlsStream handMsg)
+ {
+ TlsHandshakeType handshakeType = (TlsHandshakeType)handMsg.ReadByte();
+ TlsHandshakeMessage message = null;
+
+ // Read message length
+ int length = handMsg.ReadInt24();
+
+ // Read message data
+ byte[] data = new byte[length];
+ handMsg.Read(data, 0, length);
+
+ // Create and process the server message
+ message = this.createServerHandshakeMessage(handshakeType, data);
+
+ // Update session
+ if (message != null)
+ {
+ message.UpdateSession();
+ }
+ }
+
+ private void processAlert(TlsAlertLevel alertLevel, TlsAlertDescription alertDesc)
+ {
+ switch (alertLevel)
+ {
+ case TlsAlertLevel.Fatal:
+ throw this.session.CreateException(alertLevel, alertDesc);
+
+ case TlsAlertLevel.Warning:
+ default:
+ switch (alertDesc)
+ {
+ case TlsAlertDescription.CloseNotify:
+ this.session.Context.ConnectionEnd = true;
+ break;
+
+ default:
+ this.session.RaiseWarningAlert(alertLevel, alertDesc);
+ break;
+ }
+ break;
+ }
+ }
+
+ #endregion
+
+ #region MISC_METHODS
+
+ private void resetBuffer()
+ {
+ this.inputBuffer.SetLength(0);
+ this.inputBuffer.Position = 0;
+ }
+
+ private byte ReadByte()
+ {
+ byte[] b = new byte[1];
+ base.Receive(b);
+
+ return b[0];
+ }
+
+ private short ReadShort()
+ {
+ byte[] b = new byte[2];
+ base.Receive(b);
+
+ short val = BitConverter.ToInt16(b, 0);
+
+ return System.Net.IPAddress.HostToNetworkOrder(val);
+ }
+
+ #endregion
+
+ #region HANDSHAKE_METHODS
+
+ /*
+ Client Server
+
+ ClientHello -------->
+ ServerHello
+ Certificate*
+ ServerKeyExchange*
+ CertificateRequest*
+ <-------- ServerHelloDone
+ Certificate*
+ ClientKeyExchange
+ CertificateVerify*
+ [ChangeCipherSpec]
+ Finished -------->
+ [ChangeCipherSpec]
+ <-------- Finished
+ Application Data <-------> Application Data
+
+ Fig. 1 - Message flow for a full handshake
+ */
+
+ internal void DoHandshake()
+ {
+ // Reset isSecure field
+ this.session.IsSecure = false;
+
+ // Send client hello
+ this.sendRecord(TlsHandshakeType.ClientHello);
+
+ // Read server response
+ while (!this.session.Context.HelloDone)
+ {
+ // Read next record
+ this.receiveRecord();
+ }
+
+ // Send client certificate if requested
+ if (this.session.Context.ServerSettings.CertificateRequest)
+ {
+ this.sendRecord(TlsHandshakeType.Certificate);
+ }
+
+ // Send Client Key Exchange
+ this.sendRecord(TlsHandshakeType.ClientKeyExchange);
+
+ // Now initialize session cipher with the generated keys
+ this.session.Context.Cipher.InitializeCipher();
+
+ // Send certificate verify if requested
+ if (this.session.Context.ServerSettings.CertificateRequest)
+ {
+ this.sendRecord(TlsHandshakeType.CertificateVerify);
+ }
+
+ // Send Cipher Spec protocol
+ this.sendChangeCipherSpec();
+
+ // Read Cipher Spec protocol
+ this.receiveRecord();
+
+ // Read server finished
+ if (!this.session.Context.HandshakeFinished)
+ {
+ this.receiveRecord();
+ }
+
+ // Clear Key Info
+ this.session.Context.ClearKeyInfo();
+
+ // Set isSecure
+ this.session.IsSecure = true;
+ }
+
+ private TlsHandshakeMessage createClientHandshakeMessage(TlsHandshakeType type)
+ {
+ switch (type)
+ {
+ case TlsHandshakeType.ClientHello:
+ return new TlsClientHello(session);
+
+ case TlsHandshakeType.Certificate:
+ return new TlsClientCertificate(session);
+
+ case TlsHandshakeType.ClientKeyExchange:
+ return new TlsClientKeyExchange(session);
+
+ case TlsHandshakeType.CertificateVerify:
+ return new TlsClientCertificateVerify(session);
+
+ case TlsHandshakeType.Finished:
+ return new TlsClientFinished(session);
+
+ default:
+ throw new InvalidOperationException("Unknown client handshake message type: " + type.ToString() );
+ }
+ }
+
+ private TlsHandshakeMessage createServerHandshakeMessage(TlsHandshakeType type, byte[] buffer)
+ {
+ switch (type)
+ {
+ case TlsHandshakeType.HelloRequest:
+ this.sendRecord(TlsHandshakeType.ClientHello);
+ return null;
+
+ case TlsHandshakeType.ServerHello:
+ return new TlsServerHello(session, buffer);
+
+ case TlsHandshakeType.Certificate:
+ return new TlsServerCertificate(session, buffer);
+
+ case TlsHandshakeType.ServerKeyExchange:
+ return new TlsServerKeyExchange(session, buffer);
+
+ case TlsHandshakeType.CertificateRequest:
+ return new TlsServerCertificateRequest(session, buffer);
+
+ case TlsHandshakeType.ServerHelloDone:
+ return new TlsServerHelloDone(session, buffer);
+
+ case TlsHandshakeType.Finished:
+ return new TlsServerFinished(session, buffer);
+
+ default:
+ throw this.session.CreateException("Unknown server handshake message received ({0})", type.ToString());
+ }
+ }
+
+ #endregion
+ }
+}
View
21 mcs/class/System.Data.ObjectSpaces/System.Data.ObjectSpaces/PersistenceErrorBehaviour.cs
@@ -0,0 +1,21 @@
+//
+// System.Data.ObjectSpaces.PersistenceErrorBehaviour.cs - The behaviour to follow when a persistence error occurs
+//
+// Author:
+// Mark Easton (mark.easton@blinksoftware.co.uk)
+//
+// (C) BLiNK Software Ltd. http://www.blinksoftware.co.uk
+//
+
+#if NET_1_2
+
+namespace System.Data.ObjectSpaces
+{
+ public enum PersistenceErrorBehaviour
+ {
+ ThrowAtFirstError,
+ ThrowAfterCompletion
+ }
+}
+
+#endif
View
23 mcs/class/System.Data.ObjectSpaces/System.Data.ObjectSpaces/PersisteneceErrorType.cs
@@ -0,0 +1,23 @@
+//
+// System.Data.ObjectSpaces.PersistenceErrorType.cs - The type of persistence error
+//
+// Author:
+// Mark Easton (mark.easton@blinksoftware.co.uk)
+//
+// (C) BLiNK Software Ltd. http://www.blinksoftware.co.uk
+//
+
+#if NET_1_2
+
+namespace System.Data.ObjectSpaces
+{
+ public enum PersistenceErrorType
+ {
+ Inserting,
+ Deleting,
+ Updating,
+ Unknown
+ }
+}
+
+#endif
View
18 mcs/class/System.Data/System.Data.Odbc/ChangeLog
@@ -1,16 +1,14 @@
-2003-12-01 Gonzalo Paniagua Javier <gonzalo@ximian.com>
-
- * OdbcTransaction.cs: applied patch from Jeff Seifert that makes
- this class implement IDbTransaction interface.
-
2002-11-01 Daniel Morgan <danmorg@sc.rr.com>
- * OdbcDataReader.cs: - uncommented code, but I put a FIXME:
- according to Brian, this does not work on MS .NET however, we need it
- for Mono for now. schemaRow.AcceptChanges(),
- - implement IEnumerable.GetEnumerator()
+ * OdbcDataReader.cs: - uncommented code, but
+ I put a FIXME: according to Brian,
+ this does not work on MS .NET
+ however, we need it for Mono
+ for now. schemaRow.AcceptChanges(),
+ - implement IEnumerable.GetEnumerator()
- * libodbc.cs: changed the DllImport from "odbc32.dll" to "odbc32"
+ * libodbc.cs: changed the DllImport from "odbc32.dll"
+ to "odbc32"
2002-10-21 Gonzalo Paniagua Javier <gonzalo@ximian.com>
View
34 mcs/class/System.Data/System.Data.Odbc/OdbcTransaction.cs
@@ -14,9 +14,8 @@ namespace System.Data.Odbc
/// <summary>
/// Summary description for OdbcTransaction.
/// </summary>
- public class OdbcTransaction : MarshalByRefObject, IDbTransaction
+ public class OdbcTransaction : MarshalByRefObject
{
- private bool disposed = false;
private OdbcConnection connection;
private IsolationLevel isolationlevel;
@@ -80,36 +79,5 @@ public void Rollback()
else
throw new InvalidOperationException();
}
-
- public IDbConnection Connection
- {
- get {
- return connection;
- }
- }
-
- public IsolationLevel IsolationLevel
- {
- get {
- return isolationlevel;
- }
- }
-
- private void Dispose (bool disposing)
- {
- if (!disposed) {
- if (disposing) {
- Rollback ();
- }
- disposed = true;
- }
- }
-
- public void Dispose ()
- {
- Dispose (true);
- GC.SuppressFinalize (this);
- }
-
}
}
View
7 mcs/class/System.Web/System.Web.Compilation/ChangeLog
@@ -1,10 +1,3 @@
-2003-11-30 Gonzalo Paniagua Javier <gonzalo@ximian.com>
-
- * PageCompiler.cs: assign LCID, Culture and/or UICulture in
- FrameworInitialize() if provided in @Page.
-
- Fixes bug #51511.
-
2003-11-20 Gonzalo Paniagua Javier <gonzalo@ximian.com>
* TemplateControlCompiler.cs: support for expressions of
View
12 mcs/class/System.Web/System.Web.Compilation/PageCompiler.cs
@@ -80,18 +80,6 @@ protected override void AddStatementsToFrameworkInitialize (CodeMemberMethod met
method.Statements.Add (invoke);
}
- int lcid = pageParser.LCID;
- if (lcid != -1)
- method.Statements.Add (CreatePropertyAssign ("LCID", lcid));
-
- string culture = pageParser.Culture;
- if (culture != null)
- method.Statements.Add (CreatePropertyAssign ("Culture", culture));
-
- culture = pageParser.UICulture;
- if (culture != null)
- method.Statements.Add (CreatePropertyAssign ("UICulture", culture));
-
base.AddStatementsToFrameworkInitialize (method);
}
View
5 mcs/class/System.Web/System.Web.UI.WebControls/ChangeLog
@@ -1,8 +1,3 @@
-2003-11-30 Jackson Harper <jackson@ximian.com>
-
- * CheckBoxList.cs: A checkbox will have null post data if it is
- unselected. This fixes bug #51516.
-
2003-11-29 Jackson Harper <jackson@ximian.com>
* DataGrid.cs: Display paging controls even when there is no
View
5 mcs/class/System.Web/System.Web.UI.WebControls/CheckBoxList.cs
@@ -198,7 +198,10 @@ bool IPostBackDataHandler.LoadPostData(string postDataKey, NameValueCollection p
if(index >= 0 && index < Items.Count)
{
string v = postCollection [postDataKey];
- bool exists = (v != null);
+ if (v == null)
+ return false;
+
+ bool exists = (v.Trim () != "");
if(Items[index].Selected != exists)
{
Items[index].Selected = exists;
View
17 mcs/class/System.Web/System.Web.UI/ChangeLog
@@ -1,20 +1,3 @@
-2003-11-30 Ben Maurer <bmaurer@users.sourceforge.net>
-
- * LosFormatter.cs: Use ObjectStateFormatter. Pretty big size
- reduction.
-
- * ObjectStateFormatter.cs: Comment out tracing.
-
-2003-11-30 Gonzalo Paniagua Javier <gonzalo@ximian.com>
-
- * Page.cs: fixed UICulture, LCID and Culture. Set the thread
- [UI]Culture before processing the request.
-
- * PageParser.cs: read Culture, UICulture and LCID attributes. Added
- properties for these. Partially contributed by Mohammad Damt.
-
- Fixes bug #51511.
-
2003-11-27 Jackson Harper <jackson@ximian.com>
* TemplateParser.cs: Ignore aspCompat attribute. This fixes bug
View
496 mcs/class/System.Web/System.Web.UI/LosFormatter.cs
<
@@ -2,22 +2,85 @@
// System.Web.UI.LosFormatter
//
// Authors:
-// Ben Maurer (bmaurer@users.sourceforge.net)
+// Gonzalo Paniagua Javier (gonzalo@ximian.com)
//
-// (C) 2003 Ben Maurer
+// (C) 2002 Ximian, Inc (http://www.ximian.com)
//
+using System;
+using System.Collections;
+using System.Drawing;
using System.IO;
+using System.Runtime.Serialization.Formatters.Binary;
+using System.Text;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using System.Web.Util;
+namespace System.Web.UI
+{
+ public sealed class LosFormatter
+ {
+ delegate void WriteObject (LosFormatter formatter, TextWriter writer, object value);
+ static char [] specialChars = new char [] {'<', '>', ';'};
-namespace System.Web.UI {
- public sealed class LosFormatter {
+ const char booleanID = 'o';
+ const char stringID = 's';
+ const char charID = 'c';
+ const char int16ID = 'i';
+ const char int32ID = 'I';
+ const char int64ID = 'l';
+ const char colorID = 'C';
+ const char pairID = 'p';
+ const char tripletID = 't';
+ const char arrayListID = 'L';
+ const char hashtableID = 'h';
+ const char binaryID = 'b';
+ const char arrayID = 'a';
+ const char dateTimeID = 'd';
+ const char unitID = 'u';
+ const char fontUnitID = 'f';
+
+ static Hashtable specialTypes;
+ static Hashtable idToType;
+
+ static LosFormatter ()
+ {
+ specialTypes = new Hashtable ();
+ specialTypes.Add (typeof (Boolean), new WriteObject (WriteBoolean));
+ specialTypes.Add (typeof (Pair), new WriteObject (WritePair));
+ specialTypes.Add (typeof (Triplet), new WriteObject (WriteTriplet));
+ specialTypes.Add (typeof (Color), new WriteObject (WriteColor));
+ specialTypes.Add (typeof (ArrayList), new WriteObject (WriteArrayList));
+ specialTypes.Add (typeof (Hashtable), new WriteObject (WriteHashtable));
+ specialTypes.Add (typeof (Array), new WriteObject (WriteArray));
+ specialTypes.Add (typeof (DateTime), new WriteObject (WriteDateTime));
+ specialTypes.Add (typeof (Unit), new WriteObject (WriteUnit));
+ specialTypes.Add (typeof (FontUnit), new WriteObject (WriteFontUnit));
- ObjectStateFormatter osf = new ObjectStateFormatter ();
+ idToType = new Hashtable ();
+ idToType.Add (typeof (string), stringID);
+ idToType.Add (typeof (char), charID);
+ idToType.Add (typeof (Int16), int16ID);
+ idToType.Add (typeof (Int32), int32ID);
+ idToType.Add (typeof (Int64), int64ID);
+ idToType.Add (typeof (Boolean), booleanID);
+ idToType.Add (typeof (Pair), pairID);
+ idToType.Add (typeof (Triplet), tripletID);
+ idToType.Add (typeof (Color), colorID);
+ idToType.Add (typeof (ArrayList), arrayListID);
+ idToType.Add (typeof (Hashtable), hashtableID);
+ idToType.Add (typeof (Array), arrayID);
+ idToType.Add (typeof (Unit), unitID);
+ idToType.Add (typeof (FontUnit), fontUnitID);
+ }
public object Deserialize (Stream stream)
{
- return osf.Deserialize (stream);
+ if (stream == null)
+ throw new ArgumentNullException ("stream");
+
+ return Deserialize (new StreamReader (stream));
}
public object Deserialize (TextReader input)
@@ -30,20 +93,431 @@ public object Deserialize (TextReader input)
public object Deserialize (string input)
{
- return osf.Deserialize (input);
+ if (input == null)
+ throw new ArgumentNullException ("input");
+
+ if (input == "")
+ return null;
+
+ string real_input = Encoding.UTF8.GetString (Convert.FromBase64String (input));
+ return DeserializeObject (real_input);
+ }
+
+ private static string UnEscapeSpecialChars (string str)
+ {
+ if (str.IndexOf ('\\') == -1)
+ return str;
+
+ string result = str.Replace ("\\;", ";");
+ result = result.Replace ("\\>", ">");
+ result = result.Replace ("\\<", "<");
+ result = result.Replace ("\\\\", "\\");
+ return result;
+ }
+
+ private static string GetEnclosedString (string input)
+ {
+ if (input [0] != '<')
+ throw new ArgumentException (input);
+
+ int count = 1;
+ bool escaped = false;
+ StringBuilder result = new StringBuilder ();
+ for (int i = 1; count != 0 && i < input.Length; i++) {
+ char c = input [i];
+ if (escaped)
+ escaped = false;
+ else if (c == '\\')
+ escaped = true;
+ else if (c == '<')
+ count++;
+ else if (c == '>')
+ count--;
+
+ result.Append (c);
+ }
+
+ result.Length--;
+ return result.ToString ();
+ }
+
+ private static string [] GetStringValues (string input)
+ {
+ if (input == null || input.Length == 0)
+ return new string [0];
+
+ int length = input.Length;
+ bool escaped = false;
+ int opened = 0;
+ ArrayList list = new ArrayList ();
+ StringBuilder builder = new StringBuilder ();
+ for (int i = 0; i < length; i++) {
+ char c = input [i];
+ if (escaped)
+ escaped = false;
+ else if (c == '\\')
+ escaped = true;
+ else if (c == '<')
+ opened++;
+ else if (c == '>')
+ opened--;
+ else if (c == ';' && opened == 0) {
+ list.Add (builder.ToString ());
+ builder = new StringBuilder ();
+ continue;
+ }
+
+ builder.Append (c);
+ }
+
+ list.Add (builder.ToString ());
+
+ string [] result = new string [list.Count];
+ list.CopyTo (result, 0);
+ return result;
+ }
+
+ private object DeserializeObject (string input)
+ {
+ if (input == null || input.Length < 2)
+ return null;
+
+ object obj;
+ string enclosed = GetEnclosedString (input.Substring (1));
+ string [] splitted;
+
+ switch (input [0]) {
+ case booleanID:
+ obj = enclosed.Length == 1;
+ break;
+ case stringID:
+ obj = UnEscapeSpecialChars (enclosed);
+ break;
+ case int16ID:
+ obj = Int16.Parse (enclosed);
+ break;
+ case int32ID:
+ obj = Int32.Parse (enclosed);
+ break;
+ case int64ID:
+ obj = Int64.Parse (enclosed);
+ break;
+ case colorID:
+ obj = Color.FromArgb (Int32.Parse (enclosed));
+ break;
+ case pairID:
+ Pair pair = new Pair ();
+ obj = pair;
+ splitted = GetStringValues (enclosed);
+ if (splitted.Length > 0) {
+ pair.First = DeserializeObject (splitted [0]);
+ if (splitted.Length > 1)
+ pair.Second = DeserializeObject (splitted [1]);
+ }
+ break;
+ case tripletID:
+ Triplet triplet = new Triplet ();
+ obj = triplet;
+ splitted = GetStringValues (enclosed);
+ if (splitted.Length == 0)
+ break;
+ triplet.First = DeserializeObject (splitted [0]);
+ if (splitted.Length < 2)
+ break;
+ triplet.Second = DeserializeObject (splitted [1]);
+ if (splitted.Length < 3)
+ break;
+ triplet.Third = DeserializeObject (splitted [2]);
+ break;
+ case arrayListID:
+ case arrayID:
+ ArrayList list = new ArrayList ();
+ obj = list;
+ splitted = GetStringValues (enclosed);
+ foreach (string s in splitted) {
+ object o = DeserializeObject (s);
+ list.Add (o);
+ }
+
+ if (input [0] == arrayID)
+ obj = list.ToArray (typeof (object));
+
+ break;
+ case hashtableID:
+ object key;
+ object value;
+ Hashtable hash = new Hashtable ();
+ obj = hash;
+ splitted = GetStringValues (enclosed);
+ int length = splitted.Length;
+ for (int i = 0; i < length; i++) {
+ key = DeserializeObject (splitted [i++]);
+ if (i < length)
+ value = DeserializeObject (splitted [i]);
+ else
+ value = null;
+
+ hash.Add (key, value);
+ }
+ break;
+ case binaryID:
+ byte [] buffer = Convert.FromBase64String (enclosed);
+ MemoryStream ms = new MemoryStream (buffer);
+ BinaryFormatter fmt = new BinaryFormatter ();
+ obj = fmt.Deserialize (ms);
+ break;
+ case dateTimeID:
+ obj = new DateTime (Int64.Parse (enclosed));
+ break;
+ case unitID:
+ obj = Unit.Parse (enclosed);
+ break;
+ case fontUnitID:
+ obj = FontUnit.Parse (enclosed);
+ break;
+ default:
+ throw new ArgumentException ("input");
+ }
+
+ return obj;
}
public void Serialize (Stream stream, object value)
{
- osf.Serialize (stream, value);
+ if (stream == null)
+ throw new ArgumentNullException ("stream");
+
+ if (value == null)
+ throw new ArgumentNullException ("value");
+
+ StreamWriter writer = new StreamWriter (stream);
+ Serialize (writer, value);
+ writer.Flush ();
}
public void Serialize (TextWriter output, object value)
{
+ if (value == null)
+ return;
+
if (output == null)
throw new ArgumentNullException ("output");
+
+ StringBuilder builder = new StringBuilder ();
+ StringWriter writer = new StringWriter (builder);
+ SerializeObject (writer, value);
+ byte [] bytes = Encoding.UTF8.GetBytes (builder.ToString ());
+ output.Write (Convert.ToBase64String (bytes));
+ }
+
+ private static void WriteBoolean (LosFormatter formatter, TextWriter output, object value)
+ {
+ if (value == null)
+ return;
+
+ output.Write (booleanID);
+ bool b = (bool) value;
+ output.Write (b ? "<t>" : "<>");
+ }
+
+ private static void WritePair (LosFormatter formatter, TextWriter output, object value)
+ {
+ if (value == null)
+ return;
- output.Write (osf.Serialize (value));
- }
+ output.Write (pairID);
+ Pair pair = (Pair) value;
+ output.Write ('<');
+ formatter.SerializeObject (output, pair.First);
+ output.Write (';');
+ formatter.SerializeObject (output, pair.Second);
+ output.Write ('>');
+ }
+
+ private static void WriteTriplet (LosFormatter formatter, TextWriter output, object value)
+ {
+ if (value == null)
+ return;
+
+ output.Write (tripletID);
+ Triplet triplet = (Triplet) value;
+ output.Write ('<');
+ formatter.SerializeObject (output, triplet.First);
+ output.Write (';');
+ formatter.SerializeObject (output, triplet.Second);
+ output.Write (';');
+ formatter.SerializeObject (output, triplet.Third);
+ output.Write ('>');
+ }
+
+ private static void WriteColor (LosFormatter formatter, TextWriter output, object value)
+ {
+ if (value == null)
+ return;
+
+ Color c = (Color) value;
+ output.Write (String.Format ("{0}<{1}>", colorID, c.ToArgb ()));
+ }
+
+ private static void WriteArrayList (LosFormatter formatter, TextWriter output, object value)
+ {
+ if (value == null)
+ return;
+
+ output.Write (arrayListID);
+ output.Write ('<');
+ ArrayList list = (ArrayList) value;
+ for (int i = 0; i < list.Count; i++) {
+ formatter.SerializeObject (output, list [i]);
+ if (i != list.Count - 1)
+ output.Write (';');
+ }
+ output.Write('>');
+ }
+
+ private static void WriteArray (LosFormatter formatter, TextWriter output, object value)
+ {
+ if (value == null)
+ return;
+
+ output.Write (arrayID);
+ output.Write ('<');
+ Array array = (Array) value;
+ for (int i = 0; i < array.Length; i++) {
+ formatter.SerializeObject (output, array.GetValue (i));
+ if (i != array.Length - 1)
+ output.Write (';');
+ }
+ output.Write('>');
+ }
+
+ private static void WriteHashtable (LosFormatter formatter, TextWriter output, object value)
+ {
+ if (value == null)
+ return;
+
+ output.Write (hashtableID);
+ output.Write ('<');
+ Hashtable hash = (Hashtable) value;
+ int i = 0;
+ foreach (DictionaryEntry entry in hash) {
+ formatter.SerializeObject (output, entry.Key);
+ output.Write (';');
+ formatter.SerializeObject (output, entry.Value);
+ if (i != hash.Count - 1)
+ output.Write (';');
+ i++;
+ }
+ output.Write('>');
+ }
+
+ private static void WriteDateTime (LosFormatter formatter, TextWriter output, object value)
+ {
+ if (value == null)
+ return;
+
+ output.Write (dateTimeID);
+ output.Write ('<');
+ output.Write (((DateTime) value).Ticks);
+ output.Write('>');
+ }
+
+ static void WriteUnit (LosFormatter formatter, TextWriter output, object value)
+ {
+ if (value == null)
+ return;
+
+ output.Write (unitID);
+ output.Write ('<');
+ output.Write (((Unit) value).ToString ());
+ output.Write('>');
+ }
+
+ static void WriteFontUnit (LosFormatter formatter, TextWriter output, object value)
+ {
+ if (value == null)
+ return;
+
+ output.Write (fontUnitID);
+ output.Write ('<');
+ output.Write (((FontUnit) value).ToString ());
+ output.Write('>');
+ }
+
+ private static string EscapeSpecialChars (string str)
+ {
+ if (str.IndexOfAny (specialChars) == -1)
+ return str;
+
+ string result = str.Replace ("\\", "\\\\");
+ result = result.Replace ("<", "\\<");
+ result = result.Replace (">", "\\>");
+ result = result.Replace (";", "\\;");
+ return result;
+ }
+
+ private void SerializeBinary (TextWriter output, object value)
+ {
+ WebTrace.PushContext ("LosFormatter.SerializeBinary");
+ /* This is just for debugging purposes */
+ /*if (value is Array) {
+ Array array = (Array) value;
+ for (int i = 0; i < array.Length; i++) {
+ object o = array.GetValue (i);
+ if (o == null)
+ WebTrace.WriteLine ("\t{0} is null", i);
+ else
+ WebTrace.WriteLine ("\t{0} {1} {2}", i, o.GetType (), o);
+ }
+ }
+ */
+
+ BinaryFormatter fmt = new BinaryFormatter ();
+ MemoryStream stream = new MemoryStream ();
+
+ fmt.Serialize (stream, value);
+ output.Write (binaryID);
+ output.Write ('<');
+ byte [] buffer = stream.GetBuffer ();
+ output.Write (Convert.ToBase64String (buffer));
+ output.Write ('>');
+
+ WebTrace.PopContext ();
+ }
+
+ private void SerializeObject (TextWriter output, object value)
+ {