Back to index

avfs  1.0.1
base64.c
Go to the documentation of this file.
00001 /* 
00002    Text->Base64 convertion, from RFC1521
00003    Copyright (C) 1999-2001 Joe Orton <joe@light.plus.com>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009    
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public
00016    License along with this library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00018    MA 02111-1307, USA
00019 
00020 */
00021 
00022 #ifdef HAVE_CONFIG_H
00023 #include "config.h"
00024 #endif
00025 
00026 #ifdef HAVE_STDLIB_H
00027 #include <stdlib.h>
00028 #endif
00029 #ifdef HAVE_STRING_H
00030 #include <string.h>
00031 #endif
00032 
00033 #include "ne_alloc.h"
00034 #include "base64.h"
00035 
00036 /* Base64 specification from RFC 1521 */
00037 
00038 static const char b64_alphabet[65] = { 
00039     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
00040     "abcdefghijklmnopqrstuvwxyz"
00041     "0123456789+/=" };
00042     
00043 char *base64(const char *text) 
00044 {
00045     /* The tricky thing about this is doing the padding at the end,
00046      * doing the bit manipulation requires a bit of concentration only */
00047     char *buffer, *point;
00048     int inlen, outlen;
00049     
00050     /* Use 'buffer' to store the output. Work out how big it should be...
00051      * This must be a multiple of 4 bytes */
00052 
00053     inlen = strlen(text);
00054     outlen = (inlen*4)/3;
00055     if ((inlen % 3) > 0) /* got to pad */
00056        outlen += 4 - (inlen % 3);
00057     
00058     buffer = ne_malloc(outlen + 1); /* +1 for the \0 */
00059     
00060     /* now do the main stage of conversion, 3 bytes at a time,
00061      * leave the trailing bytes (if there are any) for later */
00062 
00063     for (point=buffer; inlen>=3; inlen-=3, text+=3) {
00064        *(point++) = b64_alphabet[ (*text)>>2 ]; 
00065        *(point++) = b64_alphabet[ ((*text)<<4 & 0x30) | (*(text+1))>>4 ]; 
00066        *(point++) = b64_alphabet[ ((*(text+1))<<2 & 0x3c) | (*(text+2))>>6 ];
00067        *(point++) = b64_alphabet[ (*(text+2)) & 0x3f ];
00068     }
00069 
00070     /* Now deal with the trailing bytes */
00071     if (inlen > 0) {
00072        /* We always have one trailing byte */
00073        *(point++) = b64_alphabet[ (*text)>>2 ];
00074        *(point++) = b64_alphabet[ (((*text)<<4 & 0x30) |
00075                                  (inlen==2?(*(text+1))>>4:0)) ]; 
00076        *(point++) = (inlen==1?'=':b64_alphabet[ (*(text+1))<<2 & 0x3c ]);
00077        *(point++) = '=';
00078     }
00079 
00080     /* Null-terminate */
00081     *point = '\0';
00082 
00083     return buffer;
00084 }
00085 
00086 #ifdef BASE64_TEST
00087 
00088 /* Standalone tester */
00089 
00090 #include <stdio.h>
00091 
00092 /* Tester for Base64 algorithm */
00093 int main(int argc, char **argv) {
00094     char *out;
00095     if (argc != 2) {
00096        printf("Usage: %s plaintext\n", argv[0]);
00097        exit(-1);
00098     }
00099     out = base64(argv[1]);
00100     printf("Plain: [%s], Base64: [%s]\n", argv[1], out);
00101     return 0;
00102 }
00103 
00104 #endif /* BASE64_TEST */
00105