base64.cpp

Go to the documentation of this file.
00001 
00002 /*
00003 
00004     This code is public domain software.
00005 
00006 */
00007 
00008 #include "xmlrpc.h"
00009 
00010 
00011 namespace XMLRPC {
00012 
00013 
00014 //  base64 encoding
00015 //
00016 //  buf:     binary input data
00017 //  size:    size of input (bytes)
00018 //  return:  base64-encoded string (null-terminated)
00019 //           memory for output will be allocated here, free it later
00020 //
00021 char* base64_encode(const void* buf, size_t size)
00022 {
00023     static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00024 
00025     char* str = (char*) malloc((size+3)*4/3 + 1);
00026 
00027     char* p = str;
00028     unsigned char* q = (unsigned char*) buf;
00029     size_t i = 0;
00030 
00031     while(i < size) {
00032         int c = q[i++];
00033         c *= 256;
00034         if (i < size) c += q[i];
00035         i++;
00036 
00037         c *= 256;
00038         if (i < size) c += q[i];
00039         i++;
00040 
00041         *p++ = base64[(c & 0x00fc0000) >> 18];
00042         *p++ = base64[(c & 0x0003f000) >> 12];
00043 
00044         if (i > size + 1)
00045             *p++ = '=';
00046         else
00047             *p++ = base64[(c & 0x00000fc0) >> 6];
00048 
00049         if (i > size)
00050             *p++ = '=';
00051         else
00052             *p++ = base64[c & 0x0000003f];
00053     }
00054 
00055     *p = 0;
00056 
00057     return str;
00058 }
00059 
00060 
00061 //  single base64 character conversion
00062 //
00063 static int POS(char c)
00064 {
00065     if (c>='A' && c<='Z') return c - 'A';
00066     if (c>='a' && c<='z') return c - 'a' + 26;
00067     if (c>='0' && c<='9') return c - '0' + 52;
00068     if (c == '+') return 62;
00069     if (c == '/') return 63;
00070     if (c == '=') return -1;
00071 
00072     throw XMLRPC::Exception("invalid BASE64 encoding");
00073 }
00074 
00075 //  base64 decoding
00076 //
00077 //  s:       base64 string, must be null-terminated
00078 //  data:    output buffer for decoded data
00079 //  data_len size of decoded data
00080 //  return:  allocated data buffer
00081 //
00082 void* base64_decode(const char* s, size_t& data_len)
00083 {
00084     size_t len = strlen(s);
00085 
00086     if (len % 4)
00087         throw Exception("invalid BASE64 string length");
00088 
00089     unsigned char* data = (unsigned char*) malloc(len/4*3);
00090 
00091     int n[4];
00092     unsigned char* q = (unsigned char*) data;
00093 
00094     for(const char*p=s; *p; ) {
00095         n[0] = POS(*p++);
00096         n[1] = POS(*p++);
00097         n[2] = POS(*p++);
00098         n[3] = POS(*p++);
00099 
00100         if (n[0]==-1 || n[1]==-1)
00101             throw Exception("invalid BASE64 encoding");
00102 
00103         if (n[2]==-1 && n[3]!=-1)
00104             throw Exception("invalid BASE64 encoding");
00105 
00106         q[0] = (n[0] << 2) + (n[1] >> 4);
00107         if (n[2] != -1) q[1] = ((n[1] & 15) << 4) + (n[2] >> 2);
00108         if (n[3] != -1) q[2] = ((n[2] & 3) << 6) + n[3];
00109         q += 3;
00110     }
00111 
00112     data_len = q-data - (n[2]==-1) - (n[3]==-1);
00113 
00114     return data;
00115 }
00116 
00117 
00118 } // namespace XMLRPC