+2010-01-07 Sebastien Pouliot <sebastien@ximian.com>
+
+ * ToBase64Transform.cs: Static-ify some methods to make it easier
+ to use from System.Convert
+
2009-12-01 Sebastien Pouliot <sebastien@ximian.com>
* CryptoConfig_2_1.cs: Add mapping for SHA256 since it's used
[ComVisible (true)]
public class ToBase64Transform : ICryptoTransform {
+ private const int inputBlockSize = 3;
+ private const int outputBlockSize = 4;
private bool m_disposed;
public ToBase64Transform ()
}
public int InputBlockSize {
- get { return 3; }
+ get { return inputBlockSize; }
}
public int OutputBlockSize {
- get { return 4; }
+ get { return outputBlockSize; }
}
public void Clear()
// if (inputCount != this.InputBlockSize)
// throw new CryptographicException (Locale.GetText ("Invalid input length"));
+ InternalTransformBlock (inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset);
+ return this.OutputBlockSize;
+ }
+
+ internal static void InternalTransformBlock (byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
+ {
byte[] lookup = Base64Constants.EncodeTable;
int b1 = inputBuffer [inputOffset];
outputBuffer [outputOffset+1] = lookup [((b1 << 4) & 0x30) | (b2 >> 4)];
outputBuffer [outputOffset+2] = lookup [((b2 << 2) & 0x3c) | (b3 >> 6)];
outputBuffer [outputOffset+3] = lookup [b3 & 0x3f];
-
- return this.OutputBlockSize;
}
public byte[] TransformFinalBlock (byte[] inputBuffer, int inputOffset, int inputCount)
}
// Mono System.Convert depends on the ability to process multiple blocks
- internal byte[] InternalTransformFinalBlock (byte[] inputBuffer, int inputOffset, int inputCount)
+ internal static byte[] InternalTransformFinalBlock (byte[] inputBuffer, int inputOffset, int inputCount)
{
- int blockLen = this.InputBlockSize;
- int outLen = this.OutputBlockSize;
+ int blockLen = inputBlockSize;
+ int outLen = outputBlockSize;
int fullBlocks = inputCount / blockLen;
int tail = inputCount % blockLen;
int outputOffset = 0;
for (int i = 0; i < fullBlocks; i++) {
-
- TransformBlock (inputBuffer, inputOffset,
- blockLen, res, outputOffset);
-
+ InternalTransformBlock (inputBuffer, inputOffset, blockLen, res, outputOffset);
inputOffset += blockLen;
outputOffset += outLen;
}
+2010-01-07 Sebastien Pouliot <sebastien@ximian.com>
+
+ * Convert.cs: Fix line endings in ToBase64String (bug #568778)
+ and also the default line length. Code changed to not require
+ a BinaryReader over a MemoryStream to reduce memory requirements.
+
2010-01-07 Zoltan Varga <vargaz@gmail.com>
* TermInfoDriver.cs (GetCursorPosition): Avoid waiting 1 sec here.
// Fields
public static readonly object DBNull = System.DBNull.Value;
- static ToBase64Transform toBase64Transform = new ToBase64Transform();
[MethodImplAttribute (MethodImplOptions.InternalCall)]
extern static byte [] InternalFromBase64String (string str, bool allowWhitespaceOnly);
throw new ArgumentOutOfRangeException ("offsetIn + length > array.Length");
// note: normally ToBase64Transform doesn't support multiple block processing
- byte[] outArr = toBase64Transform.InternalTransformFinalBlock (inArray, offsetIn, length);
+ byte[] outArr = ToBase64Transform.InternalTransformFinalBlock (inArray, offsetIn, length);
char[] cOutArr = new ASCIIEncoding ().GetChars (outArr);
throw new ArgumentOutOfRangeException ("offset + length > array.Length");
// note: normally ToBase64Transform doesn't support multiple block processing
- byte[] outArr = toBase64Transform.InternalTransformFinalBlock (inArray, offset, length);
+ byte[] outArr = ToBase64Transform.InternalTransformFinalBlock (inArray, offset, length);
return (new ASCIIEncoding ().GetString (outArr));
}
if (offset > inArray.Length - length)
throw new ArgumentOutOfRangeException ("offset + length > array.Length");
+ if (length == 0)
+ return String.Empty;
+
if (options == Base64FormattingOptions.InsertLineBreaks)
return ToBase64StringBuilderWithLine (inArray, offset, length).ToString ();
else
- return Encoding.ASCII.GetString (toBase64Transform.InternalTransformFinalBlock (inArray, offset, length));
+ return Encoding.ASCII.GetString (ToBase64Transform.InternalTransformFinalBlock (inArray, offset, length));
}
[ComVisible (false)]
if (offsetIn > inArray.Length - length)
throw new ArgumentOutOfRangeException ("offsetIn + length > array.Length");
+ if (length == 0)
+ return 0;
+
// note: normally ToBase64Transform doesn't support multiple block processing
if (options == Base64FormattingOptions.InsertLineBreaks) {
StringBuilder sb = ToBase64StringBuilderWithLine (inArray, offsetIn, length);
sb.CopyTo (0, outArray, offsetOut, sb.Length);
return sb.Length;
} else {
- byte[] outArr = toBase64Transform.InternalTransformFinalBlock (inArray, offsetIn, length);
+ byte[] outArr = ToBase64Transform.InternalTransformFinalBlock (inArray, offsetIn, length);
char[] cOutArr = Encoding.ASCII.GetChars (outArr);
}
}
+ private const int MaxBytesPerLine = 57;
+
static StringBuilder ToBase64StringBuilderWithLine (byte [] inArray, int offset, int length)
{
- BinaryReader reader = new BinaryReader (new MemoryStream (inArray, offset, length));
- byte[] b = null;
-
StringBuilder sb = new StringBuilder ();
- do {
- // 54 bytes of input makes for 72 bytes of output.
- b = reader.ReadBytes (54);
- if (b.Length > 0)
- sb.AppendLine (Encoding.ASCII.GetString (toBase64Transform.InternalTransformFinalBlock (b, 0, b.Length)));
- } while (b.Length > 0);
+
+ int remainder;
+ int full = Math.DivRem (length, MaxBytesPerLine, out remainder);
+ for (int i = 0; i < full; i ++) {
+ byte[] data = ToBase64Transform.InternalTransformFinalBlock (inArray, offset, MaxBytesPerLine);
+ sb.AppendLine (Encoding.ASCII.GetString (data));
+ offset += MaxBytesPerLine;
+ }
+ // we never complete (i.e. the last line) with a new line
+ if (remainder == 0) {
+ int nll = Environment.NewLine.Length;
+ sb.Remove (sb.Length - nll, nll);
+ } else {
+ byte[] data = ToBase64Transform.InternalTransformFinalBlock (inArray, offset, remainder);
+ sb.Append (Encoding.ASCII.GetString (data));
+ }
return sb;
}
+2010-01-07 Sebastien Pouliot <sebastien@ximian.com>
+
+ * ConvertTest.cs: Add test case for #568778 and the default
+ line length.
+
2010-01-03 Zoltan Varga <vargaz@gmail.com>
* ArrayTest.cs: Add a test for #564095.
string s = Convert.ToBase64String (bs, Base64FormattingOptions.None);
Assert.IsTrue (!s.Contains ("\n"), "no new line");
}
+
+ static string ToBase64 (int len, Base64FormattingOptions options)
+ {
+ return Convert.ToBase64String (new byte [len], options);
+ }
+
+ [Test]
+ public void Base64String_LineEnds_InsertLineBreaks ()
+ {
+ string base64 = ToBase64 (0, Base64FormattingOptions.InsertLineBreaks);
+ Assert.IsFalse (base64.EndsWith (Environment.NewLine), "0-le");
+ Assert.AreEqual (String.Empty, base64, "0");
+
+ base64 = ToBase64 (1, Base64FormattingOptions.InsertLineBreaks);
+ Assert.IsFalse (base64.EndsWith (Environment.NewLine), "1-le");
+ Assert.AreEqual ("AA==", base64, "1");
+
+ base64 = ToBase64 (57, Base64FormattingOptions.InsertLineBreaks);
+ Assert.IsFalse (base64.Contains (Environment.NewLine), "57-nl"); // one lines
+ Assert.IsFalse (base64.EndsWith (Environment.NewLine), "57-le");
+ Assert.AreEqual ("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", base64, "55");
+
+ base64 = ToBase64 (58, Base64FormattingOptions.InsertLineBreaks);
+ Assert.IsTrue (base64.Contains (Environment.NewLine), "58-nl"); // two lines
+ Assert.IsTrue (base64.EndsWith ("AA=="), "58-le"); // no NewLine
+ }
+
+ [Test]
+ public void Base64String_LineEnds_None ()
+ {
+ string base64 = ToBase64 (0, Base64FormattingOptions.None);
+ Assert.IsFalse (base64.EndsWith (Environment.NewLine), "0-le");
+ Assert.AreEqual (String.Empty, base64, "0");
+
+ base64 = ToBase64 (1, Base64FormattingOptions.None);
+ Assert.IsFalse (base64.EndsWith (Environment.NewLine), "1-le");
+ Assert.AreEqual ("AA==", base64, "1");
+
+ base64 = ToBase64 (57, Base64FormattingOptions.None);
+ Assert.IsFalse (base64.Contains (Environment.NewLine), "57-nl"); // one lines
+ Assert.IsFalse (base64.EndsWith (Environment.NewLine), "57-le");
+ Assert.AreEqual ("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", base64, "55");
+
+ base64 = ToBase64 (58, Base64FormattingOptions.None);
+ Assert.IsFalse (base64.Contains (Environment.NewLine), "58-nl"); // one lines
+ Assert.IsTrue (base64.EndsWith ("AA=="), "58-le"); // no NewLine
+ }
#endif
/* Have experienced some problems with FromBase64CharArray using mono. Something
* about error in a unicode file.