diff options
31 files changed, 2699 insertions, 555 deletions
diff --git a/mcs/class/Makefile b/mcs/class/Makefile index 03fe9689bb6..2cc26b415eb 100644 --- a/mcs/class/Makefile +++ b/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 \ diff --git a/mcs/class/Mono.Security/Mono.Security.Cryptography/MD5SHA1CryptoServiceProvider.cs b/mcs/class/Mono.Security/Mono.Security.Cryptography/MD5SHA1CryptoServiceProvider.cs new file mode 100755 index 00000000000..bf97dfd3a82 --- /dev/null +++ b/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 + } +} diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsCompressionMethod.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsCompressionMethod.cs new file mode 100755 index 00000000000..371ad6ec72f --- /dev/null +++ b/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 + } +} diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsNetworkStream.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsNetworkStream.cs new file mode 100644 index 00000000000..e30730eaf87 --- /dev/null +++ b/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 + } +} diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsProtocol.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsProtocol.cs new file mode 100644 index 00000000000..4315a1e2c5d --- /dev/null +++ b/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 + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSession.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSession.cs new file mode 100644 index 00000000000..1303c7c3b80 --- /dev/null +++ b/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 + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSessionContext.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSessionContext.cs new file mode 100644 index 00000000000..c9e85cee0d2 --- /dev/null +++ b/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 + } +} diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSessionSettings.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSessionSettings.cs new file mode 100644 index 00000000000..7614e99f207 --- /dev/null +++ b/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 + } +} diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSocket.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSocket.cs new file mode 100644 index 00000000000..dce8206a683 --- /dev/null +++ b/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 + } +}
\ No newline at end of file diff --git a/mcs/class/System.Data.ObjectSpaces/System.Data.ObjectSpaces/PersistenceErrorBehaviour.cs b/mcs/class/System.Data.ObjectSpaces/System.Data.ObjectSpaces/PersistenceErrorBehaviour.cs new file mode 100755 index 00000000000..7f24e7c36f4 --- /dev/null +++ b/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
\ No newline at end of file diff --git a/mcs/class/System.Data.ObjectSpaces/System.Data.ObjectSpaces/PersisteneceErrorType.cs b/mcs/class/System.Data.ObjectSpaces/System.Data.ObjectSpaces/PersisteneceErrorType.cs new file mode 100755 index 00000000000..d87e7a5bc0a --- /dev/null +++ b/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
\ No newline at end of file diff --git a/mcs/class/System.Data/System.Data.Odbc/ChangeLog b/mcs/class/System.Data/System.Data.Odbc/ChangeLog index c0f54b6a92a..04b7beb0a27 100644 --- a/mcs/class/System.Data/System.Data.Odbc/ChangeLog +++ b/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> diff --git a/mcs/class/System.Data/System.Data.Odbc/OdbcTransaction.cs b/mcs/class/System.Data/System.Data.Odbc/OdbcTransaction.cs index 429b4275e2e..64ad630d617 100644 --- a/mcs/class/System.Data/System.Data.Odbc/OdbcTransaction.cs +++ b/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 @@ namespace System.Data.Odbc 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);
- }
-
}
}
diff --git a/mcs/class/System.Web/System.Web.Compilation/ChangeLog b/mcs/class/System.Web/System.Web.Compilation/ChangeLog index 65799b10786..3b967405564 100644 --- a/mcs/class/System.Web/System.Web.Compilation/ChangeLog +++ b/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 diff --git a/mcs/class/System.Web/System.Web.Compilation/PageCompiler.cs b/mcs/class/System.Web/System.Web.Compilation/PageCompiler.cs index 75b90fbcd6e..66ac137d4f6 100644 --- a/mcs/class/System.Web/System.Web.Compilation/PageCompiler.cs +++ b/mcs/class/System.Web/System.Web.Compilation/PageCompiler.cs @@ -80,18 +80,6 @@ namespace System.Web.Compilation 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); } diff --git a/mcs/class/System.Web/System.Web.UI.WebControls/ChangeLog b/mcs/class/System.Web/System.Web.UI.WebControls/ChangeLog index ed3d7261370..a97ae03790c 100644 --- a/mcs/class/System.Web/System.Web.UI.WebControls/ChangeLog +++ b/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 diff --git a/mcs/class/System.Web/System.Web.UI.WebControls/CheckBoxList.cs b/mcs/class/System.Web/System.Web.UI.WebControls/CheckBoxList.cs index 8c183e103d8..a080a8ff092 100644 --- a/mcs/class/System.Web/System.Web.UI.WebControls/CheckBoxList.cs +++ b/mcs/class/System.Web/System.Web.UI.WebControls/CheckBoxList.cs @@ -198,7 +198,10 @@ namespace System.Web.UI.WebControls 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;
diff --git a/mcs/class/System.Web/System.Web.UI/ChangeLog b/mcs/class/System.Web/System.Web.UI/ChangeLog index 27cc7f8b423..1f60570d3fb 100644 --- a/mcs/class/System.Web/System.Web.UI/ChangeLog +++ b/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 diff --git a/mcs/class/System.Web/System.Web.UI/LosFormatter.cs b/mcs/class/System.Web/System.Web.UI/LosFormatter.cs index e2dec1984bf..ec9885b85a6 100644 --- a/mcs/class/System.Web/System.Web.UI/LosFormatter.cs +++ b/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 @@ namespace System.Web.UI { 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) + { + WebTrace.PushContext ("LosFormatter.SerializeObject"); + if (value == null) { + WebTrace.WriteLine ("value is null"); + WebTrace.PopContext (); + return; + } + + Type t = value.GetType (); + if (t.IsArray) + t = typeof (Array); + + if (specialTypes.Contains (t)) { + WriteObject w = (WriteObject) specialTypes [t]; + w (this, output, value); + WebTrace.WriteLine ("special type: {0}", value.GetType ()); + WebTrace.PopContext (); + return; + } + + if (idToType.Contains (t)) { + char c = (char) idToType [t]; + string s = EscapeSpecialChars (value.ToString ()); + output.Write (String.Format ("{0}<{1}>", c, value.ToString ())); + WebTrace.WriteLine ("regular type: {0}", value.GetType ()); + WebTrace.PopContext (); + return; + } + + SerializeBinary (output, value); + WebTrace.PopContext (); + } } -}
\ No newline at end of file +} + diff --git a/mcs/class/System.Web/System.Web.UI/ObjectStateFormatter.cs b/mcs/class/System.Web/System.Web.UI/ObjectStateFormatter.cs index 4ba666c6471..90d104b4af4 100644 --- a/mcs/class/System.Web/System.Web.UI/ObjectStateFormatter.cs +++ b/mcs/class/System.Web/System.Web.UI/ObjectStateFormatter.cs @@ -7,7 +7,7 @@ // (C) 2003 Ben Maurer // -//#define TRACE +#define TRACE using System.Collections; using System.Drawing; diff --git a/mcs/class/System.Web/System.Web.UI/Page.cs b/mcs/class/System.Web/System.Web.UI/Page.cs index 39cede35bb2..8e0574bf63a 100755 --- a/mcs/class/System.Web/System.Web.UI/Page.cs +++ b/mcs/class/System.Web/System.Web.UI/Page.cs @@ -7,7 +7,6 @@ // Andreas Nahr (ClassDevelopment@A-SoftTech.com) // // (C) 2002,2003 Ximian, Inc. (http://www.ximian.com) -// (c) 2003 Novell, Inc. (http://www.novell.com) // using System; @@ -16,11 +15,9 @@ using System.Collections.Specialized; using System.ComponentModel; using System.ComponentModel.Design; using System.ComponentModel.Design.Serialization; -using System.Globalization; using System.IO; using System.Security.Principal; using System.Text; -using System.Threading; using System.Web; using System.Web.Caching; using System.Web.SessionState; @@ -36,6 +33,7 @@ namespace System.Web.UI [RootDesignerSerializer ("Microsoft.VSDesigner.WebForms.RootCodeDomSerializer, " + Consts.AssemblyMicrosoft_VSDesigner, "System.ComponentModel.Design.Serialization.CodeDomSerializer, " + Consts.AssemblySystem_Design, true)] public class Page : TemplateControl, IHttpHandler { + private string _culture; private bool _viewState = true; private bool _viewStateMac = false; private string _errorPage; @@ -46,6 +44,7 @@ public class Page : TemplateControl, IHttpHandler private bool _traceEnabled; private TraceMode _traceModeValue; private int _transactionMode; + private string _UICulture; private HttpContext _context; private ValidatorCollection _validators; private bool renderingForm; @@ -134,7 +133,7 @@ public class Page : TemplateControl, IHttpHandler [EditorBrowsable (EditorBrowsableState.Never)] protected string Culture { - set { Thread.CurrentThread.CurrentCulture = new CultureInfo (value); } + set { _culture = value; } } [Browsable (false)] @@ -197,9 +196,10 @@ public class Page : TemplateControl, IHttpHandler get { return _isValid; } } + [MonoTODO] [EditorBrowsable (EditorBrowsableState.Never)] protected int LCID { - set { Thread.CurrentThread.CurrentCulture = new CultureInfo (value); } + set { throw new NotImplementedException (); } } [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] @@ -273,7 +273,7 @@ public class Page : TemplateControl, IHttpHandler [EditorBrowsable (EditorBrowsableState.Never)] protected string UICulture { - set { Thread.CurrentThread.CurrentUICulture = new CultureInfo (value); } + set { _UICulture = value; } } [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] @@ -617,24 +617,14 @@ public class Page : TemplateControl, IHttpHandler public void ProcessRequest (HttpContext context) { _context = context; + WebTrace.PushContext ("Page.ProcessRequest ()"); + WebTrace.WriteLine ("Entering"); WireupAutomaticEvents (); + WebTrace.WriteLine ("Finished hookup"); //-- Control execution lifecycle in the docs - - // Save culture information because it can be modified in FrameworkInitialize() - CultureInfo culture = Thread.CurrentThread.CurrentCulture; - CultureInfo uiculture = Thread.CurrentThread.CurrentUICulture; + WebTrace.WriteLine ("FrameworkInitialize"); FrameworkInitialize (); - - try { - InternalProcessRequest (); - } finally { - Thread.CurrentThread.CurrentCulture = culture; - Thread.CurrentThread.CurrentUICulture = uiculture; - } - } - - void InternalProcessRequest () - { + WebTrace.WriteLine ("InitRecursive"); InitRecursive (null); renderingForm = false; if (IsPostBack) { @@ -642,20 +632,27 @@ public class Page : TemplateControl, IHttpHandler ProcessPostData (DeterminePostBackMode (), false); } + WebTrace.WriteLine ("LoadRecursive"); LoadRecursive (); if (IsPostBack) { ProcessPostData (secondPostData, true); RaiseChangedEvents (); RaisePostBackEvents (); } + WebTrace.WriteLine ("PreRenderRecursiveInternal"); PreRenderRecursiveInternal (); + WebTrace.WriteLine ("SavePageViewState"); SavePageViewState (); //-- - HtmlTextWriter output = new HtmlTextWriter (_context.Response.Output); + HtmlTextWriter output = new HtmlTextWriter (context.Response.Output); + WebTrace.WriteLine ("RenderControl"); RenderControl (output); _context = null; + WebTrace.WriteLine ("UnloadRecursive"); UnloadRecursive (true); + WebTrace.WriteLine ("End"); + WebTrace.PopContext (); } internal void RaisePostBackEvents () @@ -807,12 +804,15 @@ public class Page : TemplateControl, IHttpHandler internal void LoadPageViewState() { + WebTrace.PushContext ("LoadPageViewState"); object sState = LoadPageStateFromPersistenceMedium (); + WebTrace.WriteLine ("sState = '{0}'", sState); if (sState != null) { Pair pair = (Pair) sState; LoadViewStateRecursive (pair.First); _requiresPostBack = pair.Second as ArrayList; } + WebTrace.PopContext (); } internal void SavePageViewState () diff --git a/mcs/class/System.Web/System.Web.UI/PageParser.cs b/mcs/class/System.Web/System.Web.UI/PageParser.cs index 72556e539b8..3c9e8db058e 100644 --- a/mcs/class/System.Web/System.Web.UI/PageParser.cs +++ b/mcs/class/System.Web/System.Web.UI/PageParser.cs @@ -8,7 +8,6 @@ // using System; using System.Collections; -using System.Globalization; using System.Text; using System.Web; using System.Web.Compilation; @@ -23,9 +22,6 @@ namespace System.Web.UI string responseEncoding; string contentType; int codepage = -1; - int lcid = -1; - string culture; - string uiculture; // FIXME: this is here just for DesignTimeTemplateParser. Anything to do? internal PageParser () @@ -98,98 +94,21 @@ namespace System.Web.UI contentType = GetString (atts, "ContentType", null); - string lcidStr = GetString (atts, "LCID", null); - if (lcidStr != null) { - try { - lcid = (int) UInt32.Parse (lcidStr); - } catch { - ThrowParseException ("Invalid value for LCID: " + lcid); - } - - CultureInfo ci = null; - try { - ci = new CultureInfo (lcid); - } catch { - ThrowParseException ("Unsupported LCID: " + lcid); - } - - if (ci.IsNeutralCulture) { - string suggestedCulture = SuggestCulture (ci.Name); - string fmt = "LCID attribute must be set to a non-neutral Culture."; - if (suggestedCulture != null) { - ThrowParseException (fmt + " Please try one of these: " + - suggestedCulture); - } else { - ThrowParseException (fmt); - } - } - } - - culture = GetString (atts, "Culture", null); - if (culture != null) { - if (lcidStr != null) - ThrowParseException ("Culture and LCID are mutually exclusive."); - - CultureInfo ci = null; - try { - ci = new CultureInfo (culture); - } catch { - ThrowParseException ("Unsupported Culture: " + culture); - } - - if (ci.IsNeutralCulture) { - string suggestedCulture = SuggestCulture (culture); - string fmt = "Culture attribute must be set to a non-neutral Culture."; - if (suggestedCulture != null) - ThrowParseException (fmt + - " Please try one of these: " + suggestedCulture); - else - ThrowParseException (fmt); - } - } - - uiculture = GetString (atts, "UICulture", null); - if (uiculture != null) { - CultureInfo ci = null; - try { - ci = new CultureInfo (uiculture); - } catch { - ThrowParseException ("Unsupported Culture: " + uiculture); - } - - if (ci.IsNeutralCulture) { - string suggestedCulture = SuggestCulture (uiculture); - string fmt = "UICulture attribute must be set to a non-neutral Culture."; - if (suggestedCulture != null) - ThrowParseException (fmt + - " Please try one of these: " + suggestedCulture); - else - ThrowParseException (fmt); - } - } - // Ignored by now GetString (atts, "Buffer", null); GetString (atts, "ClientTarget", null); + GetString (atts, "Culture", null); GetString (atts, "EnableViewStateMac", null); GetString (atts, "ErrorPage", null); + GetString (atts, "LCID", null); GetString (atts, "Trace", null); GetString (atts, "TraceMode", null); + GetString (atts, "UICulture", null); GetBool (atts, "ValidateRequest", true); base.ProcessMainAttributes (atts); } - static string SuggestCulture (string culture) - { - string retval = null; - foreach (CultureInfo ci in CultureInfo.GetCultures (CultureTypes.SpecificCultures)) { - if (ci.Name.StartsWith (culture)) - retval += ci.Name + " "; - } - return retval; - } - protected override Type CompileIntoType () { AspGenerator generator = new AspGenerator (this); @@ -204,12 +123,18 @@ namespace System.Web.UI get { return readonlySessionState; } } - internal override Type DefaultBaseType { - get { return typeof (Page); } + internal override Type DefaultBaseType + { + get { + return typeof (Page); + } } - internal override string DefaultDirectiveName { - get { return "page"; } + internal override string DefaultDirectiveName + { + get { + return "page"; + } } internal string ResponseEncoding { @@ -223,18 +148,6 @@ namespace System.Web.UI internal int CodePage { get { return codepage; } } - - internal string Culture { - get { return culture; } - } - - internal string UICulture { - get { return uiculture; } - } - - internal int LCID { - get { return lcid; } - } } } diff --git a/mcs/class/System.Web/System.Web.UI/TODO b/mcs/class/System.Web/System.Web.UI/TODO new file mode 100644 index 00000000000..de529b87f86 --- /dev/null +++ b/mcs/class/System.Web/System.Web.UI/TODO @@ -0,0 +1,42 @@ +AttributeCollection +BaseParser +BasePartialCachingControl +CompiledTemplateBuilder +ConstructorNeedsTagAttribute +ControlBuilder +ControlBuilderAttribute +ControlCollection +CssStyleCollection +DataBinder +DataBinding +DataBindingCollection +DataBindingHandlerAttribute +DataBoundLiteralControl +DesignTimeParseData +DesignTimeTemplateParser +EmptyControlCollection +Html32TextWriter +HtmlTextWriter +ImageClickEventArgs +LosFormatter +Page +PageParser +ParseChildrenAttribute +PartialCachingAttribute +PartialCachingControl +PersistChildrenAttribute +PersistanceModeAttribute +RootBuilder +SimpleWebHandlerParser +StateBag +StaticPartialCachingControl +TagPrefixAttribute +TemplateBuilder +TemplateContainerAttribute +TemplateControl +TemplateControlParser +ToolboxDataAttribute +UserControl +ValidationPropertyAttribute +ValidatorCollection +WebServiceProvider diff --git a/mcs/class/System.Web/System.Web.Util/ChangeLog b/mcs/class/System.Web/System.Web.Util/ChangeLog index 3877dd069d9..20b8897f497 100644 --- a/mcs/class/System.Web/System.Web.Util/ChangeLog +++ b/mcs/class/System.Web/System.Web.Util/ChangeLog @@ -1,8 +1,3 @@ -2003-12-01 Gonzalo Paniagua Javier <gonzalo@ximian.com> - - * UrlUtils.cs: don't forget basePath when relative path is not rooted. - Fixes bug #51522. - 2003-11-27 Gonzalo Paniagua Javier <gonzalo@ximian.com> * UrlUtils.cs: fix bug introduced with last change that makes relative diff --git a/mcs/class/System.Web/System.Web.Util/UrlUtils.cs b/mcs/class/System.Web/System.Web.Util/UrlUtils.cs index 4ea92bbed8a..5c6e765f97b 100644 --- a/mcs/class/System.Web/System.Web.Util/UrlUtils.cs +++ b/mcs/class/System.Web/System.Web.Util/UrlUtils.cs @@ -134,15 +134,14 @@ namespace System.Web.Util return Reduce (basePath + slash + relPath); } - if (basePath == null || basePath == "") { - basePath = HttpRuntime.AppDomainAppVirtualPath; - if (basePath.Length <= 1) - basePath = String.Empty; - } - - return Reduce (basePath + "/" + relPath); - } - +
+ string vPath = HttpRuntime.AppDomainAppVirtualPath;
+ if (vPath.Length <= 1)
+ vPath = String.Empty;
+
+ return Reduce (vPath + "/" + relPath);
+ }
+
public static bool IsValidProtocol(string protocol)
{
if(protocol.Length < 1)
diff --git a/mcs/class/System/Test/system_linux_test.args b/mcs/class/System/Test/system_linux_test.args new file mode 100644 index 00000000000..48b00f0b2dd --- /dev/null +++ b/mcs/class/System/Test/system_linux_test.args @@ -0,0 +1,37 @@ +Microsoft.CSharp/CodeGeneratorFromCompileUnitTest.cs +Microsoft.CSharp/CodeGeneratorFromExpressionTest.cs +Microsoft.CSharp/CodeGeneratorFromNamespaceTest.cs +Microsoft.CSharp/CodeGeneratorFromStatementTest.cs +Microsoft.CSharp/CodeGeneratorFromTypeTest.cs +Microsoft.CSharp/CodeGeneratorTestBase.cs +System/UriBuilderTest.cs +System/UriTest.cs +System.Collections.Specialized/BasicOperationsTest.cs +System.Collections.Specialized/BitVector32Test.cs +System.Collections.Specialized/HybridDictionaryTest.cs +System.Collections.Specialized/ListDictionaryTest.cs +System.Collections.Specialized/NameValueCollectionTest.cs +System.Collections.Specialized/StringCollectionTest.cs +System.ComponentModel/EventHandlerListTests.cs +System.Diagnostics/TraceTest.cs +System.Diagnostics/SwitchesTest.cs +System.Diagnostics/DiagnosticsConfigurationHandlerTest.cs +System.Net/CookieCollectionTest.cs +System.Net/CookieTest.cs +System.Net/CredentialCacheTest.cs +System.Net/DnsTest.cs +System.Net/FileWebRequestTest.cs +System.Net/HttpWebRequestTest.cs +System.Net/IPAddressTest.cs +System.Net/IPEndPointTest.cs +System.Net/ServicePointManagerTest.cs +System.Net/ServicePointTest.cs +System.Net/SocketPermissionTest.cs +System.Net/WebHeaderCollectionTest.cs +System.Net/WebProxyTest.cs +System.Net/WebRequestTest.cs +System.Net.Sockets/TcpClientTest.cs +System.Net.Sockets/TcpListenerTest.cs +System.Text.RegularExpressions/PerlTest.cs +System.Text.RegularExpressions/PerlTrials.cs +System.Text.RegularExpressions/RegexTrial.cs diff --git a/mcs/class/corlib/System.Collections/ChangeLog b/mcs/class/corlib/System.Collections/ChangeLog index e00e8262382..9279fd93c4a 100644 --- a/mcs/class/corlib/System.Collections/ChangeLog +++ b/mcs/class/corlib/System.Collections/ChangeLog @@ -1,20 +1,3 @@ -2003-12-01 Gonzalo Paniagua Javier <gonzalo@ximian.com> - - * Queue.cs: patch from Carlos Barcenilla. - public class Queue - - method: ICollection.Clone() - - Optimized. Removed unneeded instructions. - - method: public static Queue Synchronized (Queue queue) - - ArgumentNullException.ParamName must be "queue", not null. - - method: public virtual void TrimToSize() - - Must increment modCount. - - private class SyncQueue - - method: public override object Clone () - - Must return a synchronized (SyncStack) instance. - - method: public override void TrimToSize () - - Not implemented. - 2003-11-13 Andreas Nahr <ClassDevelopment@A-SoftTech.com> * IEnumerator.cs: Added missing attribute diff --git a/mcs/class/corlib/System.Collections/Queue.cs b/mcs/class/corlib/System.Collections/Queue.cs index 97fd82a74e4..94e5e178f0d 100644 --- a/mcs/class/corlib/System.Collections/Queue.cs +++ b/mcs/class/corlib/System.Collections/Queue.cs @@ -94,16 +94,29 @@ namespace System.Collections { public virtual object Clone () { Queue newQueue; - newQueue = new Queue (this.capacity, this.growFactor); + newQueue = new Queue (); // FIXME: improve this... + newQueue.contents = new object[this.contents.Length]; Array.Copy (this.contents, 0, newQueue.contents, 0, - this.capacity); + this.contents.Length); newQueue.head = this.head; newQueue.count = this.count; + newQueue.capacity = this.capacity; + newQueue.growFactor = this.growFactor; return newQueue; } + // FIXME: should override Equals? + + // from Queue spec + +/* + public virtual bool IsReadOnly { + get { return false; } + } +*/ + public virtual void Clear () { modCount++; head = 0; @@ -157,7 +170,7 @@ namespace System.Collections { public static Queue Synchronized (Queue queue) { if (queue == null) { - throw new ArgumentNullException ("queue"); + throw new ArgumentNullException (); } return new SyncQueue (queue); } @@ -169,7 +182,6 @@ namespace System.Collections { } public virtual void TrimToSize() { - modCount++; object[] trimmed = new object [count]; CopyTo (trimmed, 0); contents = trimmed; @@ -230,7 +242,7 @@ namespace System.Collections { public override object Clone () { lock (queue) { - return new SyncQueue((Queue) queue.Clone ()); + return queue.Clone (); } } @@ -250,12 +262,6 @@ namespace System.Collections { } } - public override void TrimToSize () { - lock (queue) { - queue.TrimToSize (); - } - } - public override bool Contains (object obj) { lock (queue) { return queue.Contains (obj); diff --git a/mcs/class/corlib/System.Reflection/common.src b/mcs/class/corlib/System.Reflection/common.src deleted file mode 100644 index 022b6768fcc..00000000000 --- a/mcs/class/corlib/System.Reflection/common.src +++ /dev/null @@ -1,25 +0,0 @@ -Assembly.cs -AssemblyNameFlags.cs -BindingFlags.cs -CallingConventions.cs -ConstructorInfo.cs -DefaultMemberAttribute.cs -EventAttributes.cs -EventInfo.cs -FieldAttributes.cs -FieldInfo.cs -ICustomAttributeProvider.cs -MemberFilter.cs -MemberInfo.cs -MemberTypes.cs -MethodAttributes.cs -MethodBase.cs -MethodImplAttributes.cs -MethodInfo.cs -Module.cs -ParameterAttributes.cs -PropertyAttributes.cs -PropertyInfo.cs -ResourceAttributes.cs -ResourceLocation.cs -TypeAttributes.cs diff --git a/mcs/class/corlib/Test/System.Collections/ChangeLog b/mcs/class/corlib/Test/System.Collections/ChangeLog index fb0e42488bd..0494c6dcc0a 100644 --- a/mcs/class/corlib/Test/System.Collections/ChangeLog +++ b/mcs/class/corlib/Test/System.Collections/ChangeLog @@ -1,7 +1,3 @@ -2003-12-01 Gonzalo Paniagua Javier <gonzalo@ximian.com> - - * QueueTest.cs: added more tests. Patch from Carlos Barcenilla. - 2003-11-10 Zoltan Varga <vargaz@freemail.hu> * StackTest.cs: Applied patch from Carlos A. Barcenilla to fix minor diff --git a/mcs/class/corlib/Test/System.Collections/QueueTest.cs b/mcs/class/corlib/Test/System.Collections/QueueTest.cs index 550ebbf1d7b..db17bb0d342 100644 --- a/mcs/class/corlib/Test/System.Collections/QueueTest.cs +++ b/mcs/class/corlib/Test/System.Collections/QueueTest.cs @@ -16,14 +16,13 @@ using NUnit.Framework; namespace MonoTests.System.Collections {
- [TestFixture]
- public class QueueTest : Assertion {
+ public class QueueTest : TestCase {
protected Queue q1;
protected Queue q2;
protected Queue emptyQueue;
- protected void SetUp () {
+ protected override void SetUp () {
q1 = new Queue (10);
for (int i = 0; i < 100; i++)
q1.Enqueue (i);
@@ -35,171 +34,17 @@ namespace MonoTests.System.Collections { emptyQueue = new Queue ();
}
- public void TestConstructorException1 ()
- {
- try
- {
- Queue q = new Queue(-1, 2);
- Fail("Should throw an exception");
- } catch (ArgumentOutOfRangeException e) {
- AssertEquals("Exception's ParamName must be \"capacity\"", "capacity", e.ParamName);
- }
- }
-
- public void TestConstructorException2 ()
- {
- try
- {
- Queue q = new Queue(10, 0);
- Fail("Should throw an exception because growFactor < 1");
- }
- catch (ArgumentOutOfRangeException e)
- {
- AssertEquals("Exception's ParamName must be \"growFactor\"", "growFactor", e.ParamName);
- }
- }
-
- public void TestConstructorException3 ()
- {
- try
- {
- Queue q = new Queue(10, 11);
- Fail("Should throw an exception because growFactor > 10");
- }
- catch (ArgumentOutOfRangeException e)
- {
- AssertEquals("Exception's ParamName must be \"growFactor\"", "growFactor", e.ParamName);
- }
- }
-
- public void TestConstructorException4 ()
- {
- try
- {
- Queue q = new Queue(null);
- Fail("Should throw an exception because col == null");
- }
- catch (ArgumentNullException e)
- {
- AssertEquals("Exception's ParamName must be \"col\"", "col", e.ParamName);
- }
- }
-
- public void TestICollectionConstructor ()
- {
- Queue q = new Queue(new int[] {1, 2, 3, 4, 5});
- AssertEquals("count", 5, q.Count);
- for (int i=1; i <=5; i++)
- {
- AssertEquals(i, q.Dequeue());
- }
- }
-
- public void TestConstructors ()
- {
- SetUp();
+ public void TestConstructors () {
Assert (q1.Count == 100);
Assert (q2.Count == 50);
Assert (emptyQueue.Count == 0);
+ // TODO: Test Queue (ICollection)
}
- public void TestCount()
- {
- SetUp();
-
- AssertEquals("Count #1", 100, q1.Count);
- for (int i = 1; i <=50; i ++)
- {
- q1.Dequeue();
- }
- AssertEquals("Count #2", 50, q1.Count);
- for (int i = 1; i <=50; i ++)
- {
- q1.Enqueue(i);
- }
- AssertEquals("Count #3", 100, q1.Count);
-
- AssertEquals("Count #4", 50, q2.Count);
-
- AssertEquals("Count #5", 0, emptyQueue.Count);
- }
-
- public void TestIsSynchronized()
- {
- SetUp();
- Assert("IsSynchronized should be false", !q1.IsSynchronized);
- Assert("IsSynchronized should be false", !q2.IsSynchronized);
- Assert("IsSynchronized should be false", !emptyQueue.IsSynchronized);
- }
-
- public void TestSyncRoot()
- {
- SetUp();
- AssertEquals("SyncRoot q1", q1, q1.SyncRoot);
- AssertEquals("SyncRoot q2", q2, q2.SyncRoot);
- AssertEquals("SyncRoot emptyQueue", emptyQueue, emptyQueue.SyncRoot);
-
- Queue q1sync = Queue.Synchronized(q1);
- AssertEquals("SyncRoot value of a synchronized queue", q1, q1sync.SyncRoot);
- }
-
- public void TestCopyToException1 ()
- {
- SetUp();
- try
- {
- q1.CopyTo(null, 1);
- Fail("must throw ArgumentNullException");
- } catch (ArgumentNullException e) {
- AssertEquals("Exception's ParamName must be \"array\"", "array", e.ParamName);
- }
- }
-
-
- public void TestCopyToException2 ()
- {
- SetUp();
- try
- {
- q1.CopyTo(new int[2,2], 1);
- Fail("must throw ArgumentException");
- }
- catch (ArgumentException)
- {
- }
- }
-
- public void TestCopyToException3 ()
- {
- SetUp();
- try
- {
- q1.CopyTo(new int[3], -1);
- Fail("must throw ArgumentOutOfRangeException");
- }
- catch (ArgumentOutOfRangeException e)
- {
- AssertEquals("Exception's ParamName must be \"index\"", "index", e.ParamName);
- }
- }
-
- public void TestCopyToException4 ()
- {
- SetUp();
- try
- {
- q1.CopyTo(new int[3], 1);
- Fail("must throw ArgumentException");
- }
- catch (ArgumentException) {}
- }
-
-
- public void TestCopyTo ()
-{
-
- SetUp();
+ // TODO: should test all methods from ICollection,
+ // but it should be done in ICollectionTest.cs... ??
+ public void TestCopyTo () {
int[] a1 = new int[100];
int[] a2 = new int[60];
@@ -235,7 +80,6 @@ namespace MonoTests.System.Collections { }
public void TestEnumerator () {
- SetUp();
int i;
IEnumerator e;
e = q1.GetEnumerator ();
@@ -264,41 +108,7 @@ namespace MonoTests.System.Collections { e = q1.GetEnumerator ();
}
- public void TestEnumeratorException1 ()
- {
- SetUp();
- IEnumerator e;
-
- e = q1.GetEnumerator();
- q1.Enqueue(6);
- try {
- e.MoveNext();
- Fail("MoveNext must throw InvalidOperationException after Enqueue");
- } catch (InvalidOperationException) {}
-
-
- e = q1.GetEnumerator();
- q1.Enqueue(6);
- try
- {
- e.Reset();
- Fail("Reset must throw InvalidOperationException after Enqueue");
- }
- catch (InvalidOperationException) {}
-
- e = q1.GetEnumerator();
- q1.TrimToSize();
- try
- {
- e.Reset();
- Fail("Reset must throw InvalidOperationException after TrimToSize");
- }
- catch (InvalidOperationException) {}
-
- }
-
public void TestClone () {
- SetUp();
Queue q3 = (Queue) q2.Clone ();
Assert (q3.Count == q2.Count);
for (int i = 0; i < 50; i++)
@@ -307,8 +117,7 @@ namespace MonoTests.System.Collections { Assert (q2.Count == 0);
}
- public void TestClear () {
- SetUp();
+ public void ClearTest () {
q1.Clear ();
Assert (q1.Count == 0);
q2.Clear ();
@@ -317,8 +126,7 @@ namespace MonoTests.System.Collections { Assert (emptyQueue.Count == 0);
}
- public void TestContains () {
- SetUp();
+ public void ContainsTest () {
for (int i = 0; i < 100; i++) {
Assert (q1.Contains (i));
Assert (!emptyQueue.Contains (i));
@@ -327,14 +135,9 @@ namespace MonoTests.System.Collections { else
Assert (q2.Contains (i));
}
-
- Assert("q1 does not contain null", !q1.Contains(null));
- q1.Enqueue(null);
- Assert("q1 contains null", q1.Contains(null));
}
- public void TestEnqueueDequeuePeek () {
- SetUp();
+ public void EnqueueDequeuePeekTest () {
int q1size = q1.Count;
int q2size = q2.Count;
q2.Enqueue (null);
@@ -362,7 +165,7 @@ namespace MonoTests.System.Collections { }
}
- public void TestDequeue() {
+ public void DequeueTest() {
Queue queue = new Queue();
string[] tmp = new string[50];
int i;
@@ -370,70 +173,16 @@ namespace MonoTests.System.Collections { tmp[i] = "Data #" + i;
queue.Enqueue(tmp[i]);
}
-
- i = 0;
+
while(queue.Count>0){
+ i--;
string z = (string) queue.Dequeue();
AssertEquals (tmp[i], tmp[i], z);
- i++;
}
}
- [ExpectedException(typeof(InvalidOperationException))]
- public void TestDequeueEmpty()
- {
- Queue q= new Queue();
- q.Dequeue();
- }
-
- public void TestToArray()
- {
- SetUp();
- object[] a = q1.ToArray();
- for (int i = 0; i < 100; i++)
- {
- AssertEquals("Queue-Array mismatch",q1.Dequeue(),(int) a[i]);
- }
-
- object[] b = emptyQueue.ToArray();
- AssertEquals("b should be a zero-lenght array", 0, b.Length);
- }
-
- public void TestTrimToSize()
- {
- SetUp();
- for (int i=0; i < 50; i++)
- {
- q1.Dequeue();
- }
- q1.TrimToSize();
- // FIXME: I can't figure out how to test if TrimToSize actually worked!
- }
-
// TODO: test Syncronized operation
- public void TestSynchronizedException()
- {
- try
- {
- Queue.Synchronized(null);
- Fail("Must throw ArgumentNullException");
- }
- catch (ArgumentNullException e)
- {
- AssertEquals("Exception's ParamName must be \"queue\"", "queue", e.ParamName);
- }
- }
-
- public void TestSynchronizedClone()
- {
- SetUp();
- Queue q1sync =Queue.Synchronized(q1);
- AssertEquals("q1sync.IsSyncronized", true, q1sync.IsSynchronized);
- Queue q1syncclone = (Queue) q1sync.Clone();
- AssertEquals("clone must be synchronized too", true, q1syncclone.IsSynchronized);
- }
-
}
}
|