SMTP Auth String Builder
/* * The protocol (specifically simple auth extension) needs to encode * data in base64. There are libraries to do this, but I coded it up * to avoid creating a library dependence. */ /* Return the base 64 character for the value 0-63. RFC 4648 */ inline char base64char(unsigned char val) { if(val <= 25) return 'A' + val; if(val <= 51) return 'a' - 26 + val; if(val <= 61) return '0' + val - 52; if(val == 62) return '+'; return '/'; } /* Create a authorization string containing the account and password encoded with base64. This absurdity is defined in RFCs 4954 and 4616 in some of the most remarkably opaque writing imaginable. */ string authstring(string acct, string passwd) { // The basic string is a an (empty) "authorization identity," // an account and password all separated by a null characters. string authstring = string(1,'\0') + acct + string(1,'\0') + passwd; /* Now we need to create the base64 version. Encode a block of bytes into a base64 string. Each group of three bytes is coded as four characters. aaaaaabb ccccdddd eeffffff aaaaaa bbcccc ddddee ffffff 3 2 1 0 Phase The algorithm below cycles through the four phases, which directs how to generate generate the output character. */ // Scan the range of characters inside the created string. unsigned char *scan = reinterpret_cast<unsigned char *>(authstring.data()); unsigned char *end = scan + authstring.size(); int phase = 0; // Current phase (see above). string ret = ""; // Return value. ret.reserve(4*((authstring.size()+2)/3)); // Should be size of result. // Process the input characters. while(scan < end) { // The next input byte, or 0 if none. unsigned char next = scan < end-1 ? scan[1] : 0; // Increment the phase. Well, decrement except 0 wraps to 3. phase = phase?phase-1:3; // Extract the character based on the phase. Also controls // increment of the input pointer, which differs by phase. switch(phase) { case 3: ret += base64char(*scan >> 2); break; case 2: ret += base64char(((*scan++ & 0x3) << 4) | (next >> 4)); break; case 1: ret += base64char(((*scan++ & 0xf) << 2) | ((next & 0xc0) >> 6)); break; case 0: ret += base64char(*scan++ & 0x3f); } } // If there's a partial group at the end, fill with =. while(phase--) ret += '='; return ret; }