[csmaild-cvs] csmaild/src/Common/Encoders Base64.cs,NONE,1.1
Brought to you by:
tamc
|
From: <ta...@us...> - 2003-08-08 22:39:31
|
Update of /cvsroot/csmaild/csmaild/src/Common/Encoders In directory sc8-pr-cvs1:/tmp/cvs-serv18360/src/Common/Encoders Added Files: Base64.cs Log Message: Updated VS.NET 2002 project files to reflect currect VS.NET 2003 project Moved message flags into a FlagList class (this makes flag extensions easier to support) Modified the TestClient for easier debugging of the server Added BASE64 decoder to common library Moved argument parsing from ImapCommand into the newly created types (representing various arguments parsed from the client) Added support for AUTHENTICATE PLAIN Added TODO document in the docs !!Some stuff surely has been broken with all this code moving around, it'll compile and run, but some functionality hasn't been verified yet!! --- NEW FILE: Base64.cs --- using System; namespace Common.Encoders { /// <summary> /// Summary description for Base64. /// </summary> public class Base64 { private Base64() { } private static string Base64Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /// <summary> /// Decodes a the BASE64 encoded string (assumes all extraneous characters (even whitespace) has been removed. /// </summary> /// <param name="input">The BASE64 encoded string</param> /// <returns>The byte array representing what was encoded</returns> public static byte[] Decode(string input) { int strLength = input.Length; if(strLength % 4 != 0) return null; byte[] output; int sz = strLength - (strLength / 4); int padChars = 0; // can be padded by 0, 1, or 2 equal characters if(input[strLength-1] == '=') { ++padChars; if(input[strLength-2] == '=') { ++padChars; output = new byte[sz-2]; // 2 equal signs } else output = new byte[sz-1]; // 1 equal signs } else output = new byte[sz]; // 0 equal signs // go through each block except the last one if there is padding int max = strLength - (padChars != 0 ? 4 : 0); int iidx, oidx; for(iidx = 0, oidx = 0; iidx < max; iidx+=4, oidx+=3) { int i1 = Base64Alphabet.IndexOf(input[iidx]); int i2 = Base64Alphabet.IndexOf(input[iidx+1]); int i3 = Base64Alphabet.IndexOf(input[iidx+2]); int i4 = Base64Alphabet.IndexOf(input[iidx+3]); if(i1 == -1 || i2 == -1 || i3 == -1 || i4 == -1) return null; byte o1 = (byte) ((i1 << 2) + ((i2 & 48) >> 4)); // 48 = 110000 byte o2 = (byte)(((i2 & 15) << 4) + ((i3 & 60) >> 2)); // 15 = 001111, 60 = 111100 byte o3 = (byte)(((i3 & 3) << 6) + i4 ); // 3 = 000011 output[oidx] = o1; output[oidx+1] = o2; output[oidx+2] = o3; } // they are all done except the last one (if it was padded), as it // is special and has padding, this code is basically a duplicate // of the loop above, just subsetted to ignore the padding if(padChars == 1) { int i1 = Base64Alphabet.IndexOf(input[iidx]); int i2 = Base64Alphabet.IndexOf(input[iidx+1]); int i3 = Base64Alphabet.IndexOf(input[iidx+2]); if(i1 == -1 || i2 == -1 || i3 == -1) return null; byte o1 = (byte) ((i1 << 2) + ((i2 & 48) >> 4)); // 48 = 110000 byte o2 = (byte)(((i2 & 15) << 4) + ((i3 & 60) >> 2)); // 15 = 001111, 60 = 111100 output[oidx] = o1; output[oidx+1] = o2; } else if(padChars == 0) { int i1 = Base64Alphabet.IndexOf(input[iidx]); int i2 = Base64Alphabet.IndexOf(input[iidx+1]); if(i1 == -1 || i2 == -1) return null; byte o1 = (byte) ((i1 << 2) + ((i2 & 48) >> 4)); // 48 = 110000 output[oidx] = o1; } return output; } } } /* Each 6-bit group is used as an index into an array of 64 printable characters. The character referenced by the index is placed in the output string. These characters, identified in Table 1, below, are selected so as to be universally representable, and the set excludes characters with particular significance to SMTP (e.g., ".", CR, LF) and to the multipart boundary delimiters defined in RFC 2046 (e.g., "-"). Table 1: The Base64 Alphabet Value Encoding Value Encoding Value Encoding Value Encoding 0 A 17 R 34 i 51 z 1 B 18 S 35 j 52 0 2 C 19 T 36 k 53 1 3 D 20 U 37 l 54 2 4 E 21 V 38 m 55 3 5 F 22 W 39 n 56 4 6 G 23 X 40 o 57 5 7 H 24 Y 41 p 58 6 8 I 25 Z 42 q 59 7 9 J 26 a 43 r 60 8 10 K 27 b 44 s 61 9 11 L 28 c 45 t 62 + 12 M 29 d 46 u 63 / 13 N 30 e 47 v 14 O 31 f 48 w (pad) = 15 P 32 g 49 x 16 Q 33 h 50 y Special processing is performed if fewer than 24 bits are available at the end of the data being encoded. A full encoding quantum is always completed at the end of a body. 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 6-bit groups. Padding at the end of the data is performed using the "=" character. Since all base64 input is an integral number of octets, only the following cases can arise: (1) the final quantum of encoding input is an integral multiple of 24 bits; here, the final unit of encoded output will be an integral multiple of 4 characters with no "=" padding, (2) the final quantum of encoding input is exactly 8 bits; here, the final unit of encoded output will be two characters followed by two "=" padding characters, or (3) the final quantum of encoding input is exactly 16 bits; here, the final unit of encoded output will be three characters followed by one "=" padding character. Because it is used only for padding at the end of the data, the occurrence of any "=" characters may be taken as evidence that the end of the data has been reached (without truncation in transit). No such assurance is possible, however, when the number of octets transmitted was a multiple of three and no "=" characters are present. Any characters outside of the base64 alphabet are to be ignored in base64-encoded data. Care must be taken to use the proper octets for line breaks if base64 encoding is applied directly to text material that has not been converted to canonical form. In particular, text line breaks must be converted into CRLF sequences prior to base64 encoding. The important thing to note is that this may be done directly by the encoder rather than in a prior canonicalization step in some implementations. NOTE: There is no need to worry about quoting potential boundary delimiters within base64-encoded bodies within multipart entities because no hyphen characters are used in the base64 encoding.*/ |