rohrpost

A commandline mail client to change the world as we see it.
git clone git://r-36.net/rohrpost
Log | Files | Refs | README | LICENSE

base64.c (2214B)


      1 /*
      2  * Copy me if you can.
      3  * by 20h
      4  */
      5 
      6 #include <unistd.h>
      7 #include <stdlib.h>
      8 #include <string.h>
      9 #include <strings.h>
     10 
     11 #include "ind.h"
     12 
     13 char be[] =
     14 	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
     15 
     16 int
     17 readnwstr(char *buf, char *str, int *p, int max, int l)
     18 {
     19 	int i, j;
     20 
     21 	for (i = 0; *p < max && i < l; (*p)++) {
     22 		for (j = 0; j < strlen(be); j++) {
     23 			if (str[*p] == be[j]) {
     24 				buf[i++] = str[*p];
     25 				break;
     26 			}
     27 		}
     28 	}
     29 
     30 	if (i < l)
     31 		return 1;
     32 	return 0;
     33 }
     34 
     35 char *
     36 b64enc(char *str, int l)
     37 {
     38 	char *ret;
     39 	int p, po, left;
     40 
     41 	po = 0;
     42 	p = 0;
     43 
     44 	ret = mallocz(5, 0);
     45 	for (; p < l; p += 3, po += 4) {
     46 		ret = reallocz(ret, po + 5, 0);
     47 
     48 		ret[po] = be[(str[p] & 0xFC) >> 2];
     49 		ret[po+1] = be[(str[p] & 0x03) << 4 \
     50 			    | (str[p+1] & 0xF0) >> 4];
     51 		ret[po+2] = be[(str[p+1] & 0x0F) << 2 \
     52 			    | (str[p+2] & 0xC0) >> 6];
     53 		ret[po+3] = be[str[p+2] & 0x3F];
     54 	}
     55 	left = l - p + 3;
     56 	po -= 4;
     57 	switch (left) {
     58 	case 1:
     59 		ret[po+2] = '=';
     60 	case 2:
     61 		ret[po+3] = '=';
     62 	default:
     63 		break;
     64 	}
     65 	ret[po+4] = '\0';
     66 
     67 	return ret;
     68 }
     69 
     70 char *
     71 b64dec(char *istr, int *len)
     72 {
     73 	char *ret, str[5];
     74 	int p, po, l, uglyline;
     75 	char bd[256];
     76 
     77 	memset(bd, 0x80, 256);
     78 	/* Without »=«. */
     79 	for (p = 0; p < strlen(be)-1; p++)
     80 		bd[(int)be[p]] = p;
     81 	bd['='] = 0;
     82 
     83 	p = 0;
     84 	po = 0;
     85 	ret = NULL;
     86 
     87 	/*
     88 	 * If there is something prepended to the base64 block, take it as-is.
     89 	 */
     90 	for (uglyline = 1, l = 0; uglyline == 1; l = p) {
     91 		uglyline = 0;
     92 		for (; istr[l] != '\n' && istr[l]; l++) {
     93 			if (istr[l] == ' ')
     94 				uglyline = 1;
     95 		}
     96 		/* Take care of empty lines. */
     97 		if ((l - p) == 1 && istr[l-1] == '\r')
     98 			uglyline = 1;
     99 		if ((l - p) == 0)
    100 			uglyline = 1;
    101 		if (uglyline)
    102 			po = p = l + 1;
    103 	}
    104 	if (p > 0) {
    105 		ret = reallocz(ret, l, 0);
    106 		memmove(ret, istr, p+1);
    107 	}
    108 
    109 
    110 	for (; !readnwstr(str, istr, &p, *len, 4); po += 3) {
    111 		ret = reallocz(ret, po + 4, 0);
    112 
    113 		ret[po] = bd[(int)str[0]] << 2 | bd[(int)str[1]] >> 4;
    114 		ret[po+1] = bd[(int)str[1]] << 4 | bd[(int)str[2]] >> 2;
    115 		ret[po+2] = bd[(int)str[2]] << 6 | bd[(int)str[3]];
    116 	}
    117 	if (str[3] == '=')
    118 		po--;
    119 	if (str[2] == '=')
    120 		po--;
    121 	ret[po] = '\0';
    122 	*len = po;
    123 
    124 	return ret;
    125 }
    126 
    127 int
    128 b64len(int len)
    129 {
    130 	return (len / 3) * 4 + (len % 3 > 0)? 4 : 0;
    131 }
    132