Back to index

php5  5.3.10
base64.c
Go to the documentation of this file.
00001 static const char rcsid[] = "#(@) $Id: base64.c 242949 2007-09-26 15:44:16Z cvs2svn $";
00002 
00003 /*
00004 
00005           Encode or decode file as MIME base64 (RFC 1341)
00006 
00007                          by John Walker
00008                      http://www.fourmilab.ch/
00009 
00010               This program is in the public domain.
00011 
00012 */
00013 #include <stdio.h>
00014 
00015 /*  ENCODE  --       Encode binary file into base64.  */
00016 #include <stdlib.h>
00017 #include <ctype.h>
00018 
00019 #include "base64.h"
00020 
00021 static unsigned char dtable[512];
00022 
00023 void buffer_new(struct buffer_st *b)
00024 {
00025   b->length = 512;
00026   b->data = malloc(sizeof(char)*(b->length));
00027   b->data[0] = 0;
00028   b->ptr = b->data;
00029   b->offset = 0;
00030 }
00031 
00032 void buffer_add(struct buffer_st *b, char c)
00033 {
00034   *(b->ptr++) = c;
00035   b->offset++;
00036   if (b->offset == b->length) {
00037     b->length += 512;
00038     b->data = realloc(b->data, b->length);
00039     b->ptr = b->data + b->offset;
00040   }
00041 }
00042 
00043 void buffer_delete(struct buffer_st *b)
00044 {
00045   free(b->data);
00046   b->length = 0;
00047   b->offset = 0;
00048   b->ptr = NULL;
00049   b->data = NULL;
00050 }
00051 
00052 void base64_encode_xmlrpc(struct buffer_st *b, const char *source, int length)
00053 {
00054   int i, hiteof = 0;
00055   int offset = 0;
00056   int olen;
00057   
00058   olen = 0;
00059   
00060   buffer_new(b);
00061   
00062   /*   Fill dtable with character encodings.  */
00063   
00064   for (i = 0; i < 26; i++) {
00065     dtable[i] = 'A' + i;
00066     dtable[26 + i] = 'a' + i;
00067   }
00068   for (i = 0; i < 10; i++) {
00069     dtable[52 + i] = '0' + i;
00070   }
00071   dtable[62] = '+';
00072   dtable[63] = '/';
00073   
00074   while (!hiteof) {
00075     unsigned char igroup[3], ogroup[4];
00076     int c, n;
00077     
00078     igroup[0] = igroup[1] = igroup[2] = 0;
00079     for (n = 0; n < 3; n++) {
00080       c = *(source++);
00081       offset++;
00082       if (offset > length) {
00083        hiteof = 1;
00084        break;
00085       }
00086       igroup[n] = (unsigned char) c;
00087     }
00088     if (n > 0) {
00089       ogroup[0] = dtable[igroup[0] >> 2];
00090       ogroup[1] = dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
00091       ogroup[2] = dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
00092       ogroup[3] = dtable[igroup[2] & 0x3F];
00093       
00094       /* Replace characters in output stream with "=" pad
00095         characters if fewer than three characters were
00096         read from the end of the input stream. */
00097       
00098       if (n < 3) {
00099        ogroup[3] = '=';
00100        if (n < 2) {
00101          ogroup[2] = '=';
00102        }
00103       }
00104       for (i = 0; i < 4; i++) {
00105        buffer_add(b, ogroup[i]);
00106        if (!(b->offset % 72)) {
00107          /* buffer_add(b, '\r'); */
00108          buffer_add(b, '\n');
00109        }
00110       }
00111     }
00112   }
00113   /* buffer_add(b, '\r'); */
00114   buffer_add(b, '\n');
00115 }
00116 
00117 void base64_decode_xmlrpc(struct buffer_st *bfr, const char *source, int length)
00118 {
00119     int i;
00120     int offset = 0;
00121     int endoffile;
00122     int count;
00123 
00124     buffer_new(bfr);
00125 
00126     for (i = 0; i < 255; i++) {
00127        dtable[i] = 0x80;
00128     }
00129     for (i = 'A'; i <= 'Z'; i++) {
00130         dtable[i] = 0 + (i - 'A');
00131     }
00132     for (i = 'a'; i <= 'z'; i++) {
00133         dtable[i] = 26 + (i - 'a');
00134     }
00135     for (i = '0'; i <= '9'; i++) {
00136         dtable[i] = 52 + (i - '0');
00137     }
00138     dtable['+'] = 62;
00139     dtable['/'] = 63;
00140     dtable['='] = 0;
00141 
00142     endoffile = 0;
00143 
00144     /*CONSTANTCONDITION*/
00145     while (1) {
00146        unsigned char a[4], b[4], o[3];
00147 
00148        for (i = 0; i < 4; i++) {
00149            int c;
00150            while (1) {
00151              c = *(source++);
00152              offset++;
00153              if (offset > length) endoffile = 1;
00154              if (isspace(c) || c == '\n' || c == '\r') continue;
00155              break;
00156            }
00157 
00158            if (endoffile) {
00159              /*
00160               if (i > 0) {
00161                     fprintf(stderr, "Input file incomplete.\n");
00162                   exit(1);
00163               }
00164              */
00165               return;
00166            }
00167 
00168            if (dtable[c] & 0x80) {
00169              /*
00170              fprintf(stderr, "Offset %i length %i\n", offset, length);
00171              fprintf(stderr, "character '%c:%x:%c' in input file.\n", c, c, dtable[c]);
00172              exit(1);
00173              */
00174              i--;
00175              continue;
00176            }
00177            a[i] = (unsigned char) c;
00178            b[i] = (unsigned char) dtable[c];
00179        }
00180        o[0] = (b[0] << 2) | (b[1] >> 4);
00181        o[1] = (b[1] << 4) | (b[2] >> 2);
00182        o[2] = (b[2] << 6) | b[3];
00183         i = a[2] == '=' ? 1 : (a[3] == '=' ? 2 : 3);
00184        count = 0;
00185        while (count < i) {
00186          buffer_add(bfr, o[count++]);
00187        }
00188        if (i < 3) {
00189            return;
00190        }
00191     }
00192 }