2005-01-31 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mcs / class / corlib / System.Security.Cryptography / ToBase64Transform.cs
index ff464b0e380c1aba07441f7665973588318637fb..0d6a8c4b4c050649b31a3e09f4b9a39430b0686a 100644 (file)
@@ -4,8 +4,30 @@
 // Author:
 //   Sergey Chaban (serge@wildwestsoftware.com)
 //
+// (C) 2004 Novell (http://www.novell.com)
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
 
-using System;
+using System.Globalization;
 
 namespace System.Security.Cryptography {
 
@@ -13,53 +35,29 @@ namespace System.Security.Cryptography {
 
                private bool m_disposed;
 
-               /// <summary>
-               ///  Default constructor.
-               /// </summary>
                public ToBase64Transform ()
                {
                }
 
-               ~ToBase64Transform () 
+               ~ToBase64Transform ()
                {
                        Dispose (false);
                }
 
-               /// <summary>
-               /// </summary>
                public bool CanTransformMultipleBlocks {
-                       get {
-                               return false;
-                       }
+                       get { return false; }
                }
 
-               public bool CanReuseTransform {
-                       get { return false; }
+               public virtual bool CanReuseTransform {
+                       get { return true; }
                }
 
-               /// <summary>
-               ///  Returns the input block size for the Base64 encoder.
-               /// </summary>
-               /// <remarks>
-               ///  The returned value is always 3.
-               /// </remarks>
                public int InputBlockSize {
-                       get {
-                               return 3;
-                       }
+                       get { return 3; }
                }
 
-
-               /// <summary>
-               ///  Returns the output block size for the Base64 encoder.
-               /// </summary>
-               /// <remarks>
-               ///  The value returned by this property is always 4.
-               /// </remarks>
                public int OutputBlockSize {
-                       get {
-                               return 4;
-                       }
+                       get { return 4; }
                }
 
                public void Clear() 
@@ -84,18 +82,41 @@ namespace System.Security.Cryptography {
                        }
                }
 
-               /// <summary>
-               /// </summary>
-               public int TransformBlock (byte [] inputBuffer,
-                                                  int inputOffset,
-                                                  int inputCount,
-                                                  byte [] outputBuffer,
-                                                  int outputOffset)
+               // LAMESPEC: It's not clear from docs what should be happening 
+               // here if inputCount > InputBlockSize. It just "Converts the 
+               // specified region of the specified byte array" and that's all.
+               public int TransformBlock (byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
                {
-                       if (inputCount != this.InputBlockSize)
-                               throw new CryptographicException();
-
-                       byte [] lookup = Base64Table.EncodeTable;
+                       if (m_disposed)
+                               throw new ObjectDisposedException ("TransformBlock");
+                       if (inputBuffer == null)
+                               throw new ArgumentNullException ("inputBuffer");
+                       if (outputBuffer == null)
+                               throw new ArgumentNullException ("outputBuffer");
+                       if (inputCount < 0)
+                               throw new ArgumentException ("inputCount", "< 0");
+                       if (inputCount > inputBuffer.Length)
+                               throw new ArgumentException ("inputCount", Locale.GetText ("Overflow"));
+                       if (inputOffset < 0)
+                               throw new ArgumentOutOfRangeException ("inputOffset", "< 0");
+                       // ordered to avoid possible integer overflow
+                       if (inputOffset > inputBuffer.Length - inputCount)
+                               throw new ArgumentException ("inputOffset", Locale.GetText ("Overflow"));
+                       // ordered to avoid possible integer overflow
+#if NET_2_0
+                       if (outputOffset < 0)
+                               throw new ArgumentOutOfRangeException ("outputOffset", "< 0");
+                       if (outputOffset > outputBuffer.Length - inputCount)
+                               throw new ArgumentException ("outputOffset", Locale.GetText ("Overflow"));
+#else
+                       if ((outputOffset < 0) || (outputOffset > outputBuffer.Length - inputCount))
+                               throw new IndexOutOfRangeException ("outputOffset");
+#endif
+/// To match MS implementation
+//                     if (inputCount != this.InputBlockSize)
+//                             throw new CryptographicException (Locale.GetText ("Invalid input length"));
+
+                       byte[] lookup = Base64Constants.EncodeTable;
 
                        int b1 = inputBuffer [inputOffset];
                        int b2 = inputBuffer [inputOffset + 1];
@@ -109,31 +130,31 @@ namespace System.Security.Cryptography {
                        return this.OutputBlockSize;
                }
 
-
-
-
-               // LAMESPEC: It's not clear from Beta2 docs what should be
-               // happening here if inputCount > InputBlockSize.
-               // It just "Converts the specified region of the specified
-               // byte array" and that's all.
-               // Beta2 implementation throws some strange (and undocumented)
-               // exception in such case. The exception is thrown by
-               // System.Convert and not the method itself.
-               // Anyhow, this implementation just encodes blocks of any size,
-               // like any usual Base64 encoder.
-
-               /// <summary>
-               /// </summary>
-               public byte [] TransformFinalBlock (byte [] inputBuffer,
-                                                           int inputOffset,
-                                                           int inputCount)
+               public byte[] TransformFinalBlock (byte[] inputBuffer, int inputOffset, int inputCount)
+               {
+                       if (m_disposed)
+                               throw new ObjectDisposedException ("TransformFinalBlock");
+                       if (inputBuffer == null)
+                               throw new ArgumentNullException ("inputBuffer");
+                       if (inputCount < 0)
+                               throw new ArgumentException ("inputCount", "< 0");
+                       if (inputOffset > inputBuffer.Length - inputCount)
+                               throw new ArgumentException ("inputCount", Locale.GetText ("Overflow"));
+                       if (inputCount > this.InputBlockSize)
+                               throw new ArgumentOutOfRangeException (Locale.GetText ("Invalid input length"));
+                       
+                       return InternalTransformFinalBlock (inputBuffer, inputOffset, inputCount);
+               }
+               
+               // Mono System.Convert depends on the ability to process multiple blocks                
+               internal byte[] InternalTransformFinalBlock (byte[] inputBuffer, int inputOffset, int inputCount)
                {
                        int blockLen = this.InputBlockSize;
                        int outLen = this.OutputBlockSize;
                        int fullBlocks = inputCount / blockLen;
                        int tail = inputCount % blockLen;
 
-                       byte [] res = new byte [(inputCount != 0)
+                       byte[] res = new byte [(inputCount != 0)
                                                ? ((inputCount + 2) / blockLen) * outLen
                                                : 0];
 
@@ -148,11 +169,9 @@ namespace System.Security.Cryptography {
                                outputOffset += outLen;
                        }
 
-
-                       byte [] lookup = Base64Table.EncodeTable;
+                       byte[] lookup = Base64Constants.EncodeTable;
                        int b1,b2;
 
-
                        // When fewer than 24 input bits are available
                        // in an input group, zero bits are added
                        // (on the right) to form an integral number of
@@ -180,73 +199,9 @@ namespace System.Security.Cryptography {
                                // one-byte padding
                                res [outputOffset+3] = (byte)'=';
                                break;
-
-                       default:
-                               break;
                        }
 
                        return res;
                }
-
-       } // ToBase64Transform
-
-
-
-       
-       [MonoTODO ("Put me in a separate file")]
-       internal sealed class Base64Table {
-
-               // This is the Base64 alphabet as described in RFC 2045
-               // (Table 1, page 25).
-               private static string ALPHABET =
-                       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-               private static byte[] encodeTable;
-               private static byte[] decodeTable;
-
-
-               static Base64Table ()
-               {
-                       int len = ALPHABET.Length;
-
-                       encodeTable = new byte [len];
-
-                       for (int i=0; i < len; i++) {
-                               encodeTable [i] = (byte) ALPHABET [i];
-                       }
-
-
-                       decodeTable = new byte [1 + (int)'z'];
-
-                       for (int i=0; i < decodeTable.Length; i++) {
-                               decodeTable [i] = Byte.MaxValue;
-                       }
-
-                       for (int i=0; i < len; i++) {
-                               char ch = ALPHABET [i];
-                               decodeTable [(int)ch] = (byte) i;
-                       }
-               }
-
-
-               private Base64Table ()
-               {
-                       // Never instantiated.
-               }
-
-
-               internal static byte [] EncodeTable {
-                       get {
-                               return encodeTable;
-                       }
-               }
-
-               internal static byte [] DecodeTable {
-                       get {
-                               return decodeTable;
-                       }
-               }
-
-       } // Base64Table
-
-} // System.Security.Cryptography
+       }
+}