2004-06-19 Gonzalo Paniagua Javier <gonzalo@ximian.com>
[mono.git] / mcs / class / System.Web / System.Web.Mail / ToUUEncodingTransform.cs
1 //
2 // System.Web.Mail.ToUUEncodingTransform.cs
3 //
4 // Author(s):
5 //   Per Arneng <pt99par@student.bth.se>
6 //
7 //
8 using System;
9 using System.Security.Cryptography;
10
11 namespace System.Web.Mail {
12
13     // This class transforms blocks of plaintext to UU encoding
14     internal class ToUUEncodingTransform : ICryptoTransform {
15         
16         public int InputBlockSize { get { return 45; } }
17         public int OutputBlockSize { get { return 61; } }
18
19         public bool CanTransformMultipleBlocks { get { return true; } }
20         public bool CanReuseTransform { get { return true; } }
21     
22         // transforms a block of bytes to UU encoding
23         public int TransformBlock( byte[] inputBuffer,
24                                    int inputOffset,
25                                    int inputCount,
26                                    byte[] outputBuffer,
27                                    int outputOffset
28                                    ) {
29             
30             // write the line length length+0x20
31             outputBuffer[ 0 ] = (byte)'M';
32             
33             // transform the block 3bytes at a time
34             for( int i=0;i<15;i++ ) {
35                 
36                 TransformTriplet( inputBuffer , inputOffset + i * 3 , 3,
37                                   outputBuffer , outputOffset + i * 4 + 1);
38             
39             }
40             
41             
42             return OutputBlockSize;
43         }
44         
45         // make a final uu transformations
46         public byte[] TransformFinalBlock(byte[] inputBuffer,
47                                           int inputOffset,
48                                           int inputCount
49                                           ) {
50             
51             // calculate how many 4-byte blocks there are
52             int tripletBlocks = inputCount / 3 + 1;
53             
54             // create a new buffer and copy the input data into that
55             byte[] buffer = new byte[ tripletBlocks * 3 ];
56             Buffer.BlockCopy( inputBuffer,inputOffset, buffer,0,inputCount);
57             
58             // create the outpur buffer and set the first byte
59             // to the length+0x20
60             byte[] outputBuffer = new byte[ tripletBlocks * 4 + 1 ];
61             outputBuffer[ 0 ] = (byte)(inputCount+0x20);
62             
63             // transform the block 3bytes at a time
64             for( int i =0 ; i < tripletBlocks ; i++ ) {
65                 TransformTriplet( inputBuffer , inputOffset + i * 3 , 3,
66                                   outputBuffer , i * 4 + 1);
67             }
68             
69             
70
71             return outputBuffer;
72                     
73         }
74         
75         // transforms a 3byte buffer to a 4byte uuencoded buffer
76         protected int TransformTriplet( byte[] inputBuffer,
77                                         int inputOffset,
78                                         int inputCount,
79                                         byte[] outputBuffer,
80                                         int outputOffset
81                                         ) {
82             
83             byte a = inputBuffer[ inputOffset + 0 ];
84             byte b = inputBuffer[ inputOffset + 1 ];
85             byte c = inputBuffer[ inputOffset + 2 ];
86             
87             outputBuffer[ outputOffset + 0 ] = 
88                 (byte)(0x20 + (( a >> 2                    ) & 0x3F));
89             
90             outputBuffer[ outputOffset + 1 ] = 
91                 (byte)(0x20 + (((a << 4) | ((b >> 4) & 0xF)) & 0x3F));
92             
93             outputBuffer[ outputOffset + 2 ] = 
94                 (byte)(0x20 + (((b << 2) | ((c >> 6) & 0x3)) & 0x3F));
95             
96             outputBuffer[ outputOffset + 3 ] = 
97                 (byte)(0x20 + (( c                         ) & 0x3F));
98             
99             // tanslate all 0x20 to 0x60 according to specs
100             for( int i = 0; i < 4; i++ ) {
101                 if( outputBuffer[ outputOffset + i ] == 0x20 ) {
102                     outputBuffer[ outputOffset + i ] = 0x60;
103                 }
104             }
105             
106             return 4;
107         }
108
109         public void Dispose() {}
110     }
111
112 }