/* Package Name : twhttpd * File Name : base64.c * Author : Sam NG * All rights reserved. * * This package is an secure HTTP application proxy writen by Sam Ng. * The software is free for commercial and non-commercial use as long as * the following conditions are aheared to. * * Copyright remains Sam NG's, and as such any Copyright notices in * the code are not to be removed. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY SAM NG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ #include #include #include #include #include #include "config.h" /* Base-64 decoding. This represents binary data as printable ASCII ** characters. Three 8-bit binary bytes are turned into four 6-bit ** values, like so: ** ** [11111111] [22222222] [33333333] ** ** [111111] [112222] [222233] [333333] ** ** Then the 6-bit values are represented using the characters "A-Za-z0-9+/". */ static int b64_decode_table[256] = { -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 00-0F */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 10-1F */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63, /* 20-2F */ 52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1, /* 30-3F */ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, /* 40-4F */ 15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1, /* 50-5F */ -1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40, /* 60-6F */ 41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1, /* 70-7F */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 80-8F */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 90-9F */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* A0-AF */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* B0-BF */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* C0-CF */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* D0-DF */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* E0-EF */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 /* F0-FF */ }; static char b64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" ; /* Do base-64 decoding on a string. Ignore any non-base64 bytes. ** Return the actual number of bytes generated. The decoded size will ** be at most 3/4 the size of the encoded, and may be smaller if there ** are padding characters (blanks, newlines). */ int b64_decode(char *str, char *buf, int max_buf) { char c; char* cp; int buf_idx, phase; int d, prev_d; buf_idx = 0; phase = 0; for ( cp = str; *cp != '\0'; ++cp ) { d = b64_decode_table[*cp]; if ( d != -1 ) { switch ( phase ) { case 0: ++phase; break; case 1: c = ( ( prev_d << 2 ) | ( ( d & 0x30 ) >> 4 ) ); if ( buf_idx < max_buf ) buf[buf_idx++] = c; ++phase; break; case 2: c = ( ( ( prev_d & 0xf ) << 4 ) | ( ( d & 0x3c ) >> 2 ) ); if ( buf_idx < max_buf ) buf[buf_idx++] = c; ++phase; break; case 3: c = ( ( ( prev_d & 0x03 ) << 6 ) | d ); if ( buf_idx < max_buf ) buf[buf_idx++] = c; phase = 0; break; } prev_d = d; } } return buf_idx; } /* do base64 encode * return strlen of encoded string, -1 if error * note str is binary input, probably not null terminated */ int b64_encode(char *str, int str_len, char *buf, int max_buf) { int i=0; /* b64 ecnode is 76char per line */ while( str_len > 0 ) { /* new line needed?? */ if ( i >= B64_CPL ) { i = 0; if ( max_buf < 1 ) return -1; *buf = '\n'; max_buf--; buf++; } else { i++; } /* enough buffer space?? */ if ( max_buf >= 4 ) max_buf -= 4; else return -1; if ( str_len >= 3 ) { str_len -= 3; *buf = b64_table[(*str >> 2)]; *(buf+1) = b64_table[((*str & 0x03) << 4) | (*(str+1) >> 4)]; *(buf+2) = b64_table[((*(str+1) & 0x0F) << 2) | (*(str+2) >> 6)]; *(buf+3) = b64_table[*(str+2) & 0x3F]; buf += 4; str += 3; } else if ( str_len == 2 ) { str_len -= 2; *buf = b64_table[(*str >> 2)]; *(buf+1) = b64_table[((*str & 0x03) << 4) | (*(str+1) >> 4)]; *(buf+2) = b64_table[((*(str+1) & 0x0F) << 2)]; *(buf+3) = '='; buf += 4; str += 2; } else /* if ( str_len == 1 ) */ { str_len -= 1; *buf = b64_table[(*str >> 2)]; *(buf+1) = b64_table[((*str & 0x03) << 4)]; *(buf+2) = '='; *(buf+3) = '='; buf += 4; str += 1; } } /* add end of string in buf */ if ( max_buf < 1 ) return -1; *buf = '\0'; return strlen(buf); }