[svn-upgrade] Integrating new upstream version, iodine (0.5.0)
[debian/iodine.git] / src / base64.c
index 512a1997e713dc1a01c1fad7fe6a6af70ba5d563..803d938a6c85e157235ebf913c05b727df046db1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006-2007 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
+ * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
 #include "common.h"
 #include "base64.h"
 
+#define BLKSIZE_RAW 3
+#define BLKSIZE_ENC 4
+
 static const char cb64[] = 
-       "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789.";
+       "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789+";
 static unsigned char rev64[128];
 static int reverse_init = 0;
 
+static int base64_encode(char *, size_t *, const void *, size_t);
+static int base64_decode(void *, size_t *, const char *, size_t);
+static int base64_handles_dots();
+static int base64_blksize_raw();
+static int base64_blksize_enc();
+
 #define REV64(x) rev64[(int) (x)]
-#define MODE   (cb64[62])
-#define P62    (cb64[62])
-#define P63    (cb64[63])
 
 static struct encoder base64_encoder =
 {
-       "BASE64",
+       "Base64",
        base64_encode,
        base64_decode,
        base64_handles_dots,
-       base64_handles_dots
+       base64_handles_dots,
+       base64_blksize_raw,
+       base64_blksize_enc
 };
 
 struct encoder
@@ -47,147 +55,25 @@ struct encoder
        return &base64_encoder;
 }
 
-int 
+static int 
 base64_handles_dots()
 {
        return 0;
 }
 
-static void
-findesc(int *count, unsigned char *esc, char c1, char c2, char c3, char c4)
+static int 
+base64_blksize_raw()
 {
-       int min1 = 0;
-       int min2 = 0;
-
-       int num1 = 0xFF; /* a very big number */
-       int num2 = 0xFE; /* a nearly as big number */
-
-       int i;
-
-       /* check if no more escapes needed */
-       if (count[62] == 0 && count[63] == 0) {
-               esc[0] = MODE;
-               esc[1] = MODE;
-               return;
-       }
-
-       for (i = 0; i < 62; i++) {
-               if (i == c1 || i == c2 || i == c3 || i == c4) {
-                       continue;
-               }
-
-               if (count[i] < num1) {
-                       min2 = min1;
-                       num2 = num1;
-                       min1 = i;
-                       num1 = count[i];
-               } else if (count[i] < num2) {
-                       min2 = i;
-                       num2 = count[i];
-               }
-       }
-
-       esc[0] = cb64[min1];
-       esc[1] = cb64[min2];
+       return BLKSIZE_RAW;
 }
-       
-static void
-escape_chars(char *buf, size_t buflen)
-{
-       int counter[64];
-       int escapes;
-       int reset;
-       int i;
-       unsigned char temp[4096];
-       unsigned char *r;
-       unsigned char *w;
-       unsigned char *e;
-       unsigned char esc[2];
 
-       memset(counter, 0, sizeof(counter));
-       esc[0] = P62;
-       esc[1] = P63;
-
-       /* first, find the number of times each token is used */
-       r = (unsigned char *) buf;
-       w = temp;
-       while (*r) {
-               counter[REV64(*r)]++;
-               *w++ = *r++;
-       }
-
-       /* check if work needed */
-       if (counter[62] == 0 && counter[63] == 0)
-               return;
-       
-       r = temp;
-       w = (unsigned char *) buf;
-       reset = 1;
-       escapes = 0;
-       /* check a block for esc chars */
-       while (*r) {
-               if (reset == 0 && escapes == 0 && (
-                   r[0] == esc[0] || r[1] == esc[0] ||r[2] == esc[0] ||r[2] == esc[0] ||
-                   r[0] == esc[1] || r[1] == esc[1] ||r[2] == esc[1] ||r[2] == esc[1])) {
-                       /* last set of escape chars were unused.
-                        * if we reset last escape switch then maybe we dont have to switch now */
-
-                       /* change the latest escape switch to 999 (RESET) */
-                       e[1] = MODE;
-                       e[2] = MODE;
-                        
-                       /* store default esc chars */
-                       esc[0] = P62;
-                       esc[1] = P63;
-
-                       reset = 1;
-               }
-               /* these two if blocks can not be combined because a block can contain both
-                * char 9 and/or . and the current escape chars. */
-               if (r[0] == esc[0] || r[1] == esc[0] ||r[2] == esc[0] ||r[2] == esc[0] ||
-                   r[0] == esc[1] || r[1] == esc[1] ||r[2] == esc[1] ||r[2] == esc[1]) {
-                       /* switch escape chars */
-                       escapes = 0;
-                       reset = 0;
-
-                       /* find 2 suitable escape chars */
-                       findesc(counter, esc, REV64(r[0]), REV64(r[1]), REV64(r[2]), REV64(r[3]));
-
-                       /* store escape switch position */
-                       e = w;
-
-                       /* write new escape chars */
-                       *w++ = MODE;
-                       *w++ = esc[0];
-                       *w++ = esc[1];
-               }
-               
-               /* update counter on remaining chars */
-               for (i = 0; i < 4; i++) {
-                       if (r[i])
-                               counter[REV64(r[i])]--;
-               }
-
-               /* do the escaping */
-               for (i = 0; i < 4; i++) {
-                       if (r[i] == P62) {
-                               r[i] = esc[0];
-                               escapes++;
-                       } else if (r[i] == P63) {
-                               r[i] = esc[1];
-                               escapes++;
-                       }
-               }       
-               
-               /* copy back to buf */
-               *w++ = *r++;
-               *w++ = *r++;
-               *w++ = *r++;
-               *w++ = *r++;
-       }
+static int 
+base64_blksize_enc()
+{
+       return BLKSIZE_ENC;
 }
 
-int 
+static int 
 base64_encode(char *buf, size_t *buflen, const void *data, size_t size)
 {
        size_t newsize;
@@ -209,9 +95,9 @@ base64_encode(char *buf, size_t *buflen, const void *data, size_t size)
        }
 
        /* how many chars can we encode within the buf */
-       maxsize = 3 * (*buflen / 4 - 1) - 1;
+       maxsize = BLKSIZE_RAW * (*buflen / BLKSIZE_ENC - 1) - 1;
        /* how big will the encoded data be */
-       newsize = 4 * (size / 3 + 1) + 1;
+       newsize = BLKSIZE_ENC * (size / BLKSIZE_RAW + 1) + 1;
        /* if the buffer is too small, eat some of the data */
        if (*buflen < newsize) {
                size = maxsize;
@@ -220,19 +106,17 @@ base64_encode(char *buf, size_t *buflen, const void *data, size_t size)
        p = s = (unsigned char *) buf;
        q = (unsigned char *)data;
 
-       for(i=0;i<size;i+=3) {
+       for(i=0;i<size;i+=BLKSIZE_RAW) {
                p[0] = cb64[((q[0] & 0xfc) >> 2)];
                p[1] = cb64[(((q[0] & 0x03) << 4) | ((q[1] & 0xf0) >> 4))];
                p[2] = (i+1 < size) ? cb64[((q[1] & 0x0f) << 2 ) | ((q[2] & 0xc0) >> 6)] : '\0';
                p[3] = (i+2 < size) ? cb64[(q[2] & 0x3f)] : '\0';
                
-               q += 3;
-               p += 4;
+               q += BLKSIZE_RAW;
+               p += BLKSIZE_ENC;
        }       
        *p = 0;
 
-       escape_chars(buf, *buflen);
-
        /* store number of bytes from data that was used */
        *buflen = size;
 
@@ -265,7 +149,7 @@ decode_token(const unsigned char *t, unsigned char *data, size_t len)
        return 3;
 }
 
-int
+static int
 base64_decode(void *buf, size_t *buflen, const char *str, size_t slen)
 {
        unsigned char *q;
@@ -273,9 +157,7 @@ base64_decode(void *buf, size_t *buflen, const char *str, size_t slen)
        size_t maxsize;
        const char *p;
        unsigned char c;
-       unsigned char block[4];
-       unsigned char prot62;
-       unsigned char prot63;
+       unsigned char block[BLKSIZE_ENC];
        int len;
        int i;
 
@@ -288,47 +170,26 @@ base64_decode(void *buf, size_t *buflen, const char *str, size_t slen)
        }
        
        /* chars needed to decode slen */
-       newsize = 3 * (slen / 4 + 1) + 1;
+       newsize = BLKSIZE_RAW * (slen / BLKSIZE_ENC + 1) + 1;
        /* encoded chars that fit in buf */
-       maxsize = 4 * (*buflen / 3 + 1) + 1;
+       maxsize = BLKSIZE_ENC * (*buflen / BLKSIZE_RAW + 1) + 1;
        /* if the buffer is too small, eat some of the data */
        if (*buflen < newsize) {
                slen = maxsize;
        }
        
-       prot62 = P62;
-       prot63 = P63;
 
        q = buf;
-       for (p = str; *p; p += 4) {
-               /* handle escape instructions */
-               if (*p == MODE) {
-                       p++;
-                       if (p[0] == MODE && p[1] == MODE) {
-                               /* reset escape chars */
-                               prot62 = P62;
-                               prot63 = P63;
-                               
-                               p += 2;
-                       } else {
-                               prot62 = *p++;
-                               prot63 = *p++;
-                       }
-               }
+       for (p = str; *p; p += BLKSIZE_ENC) {
                /* since the str is const, we unescape in another buf */
-               for (i = 0; i < 4; i++) {
+               for (i = 0; i < BLKSIZE_ENC; i++) {
                        block[i] = p[i];
-                       if (prot62 == block[i]) {
-                               block[i] = P62;
-                       } else if (prot63 == block[i]) {
-                               block[i] = P63;
-                       }
                }
                len = decode_token(block, (unsigned char *) q, slen);   
                q += len;
-               slen -= 4;
+               slen -= BLKSIZE_ENC;
                
-               if (len < 3)
+               if (len < BLKSIZE_RAW)
                        break;
        }
        *q = '\0';