2 * Copyright (c) 2006-2007 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 #define MIN(a,b) ((a)<(b)?(a):(b))
30 static const char base32[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ98765-";
31 static const char padder[] = " 1234";
32 static char reverse32[128];
33 static int reverse_init = 0;
35 /* Eat 5 bytes from src, write 8 bytes to dest */
37 encode_chunk(char *dest, const char *src)
41 *dest++ = base32[(*src & 0xF8) >> 3]; /* 1111 1000 first byte */
43 c = (*src++ & 0x07) << 2; /* 0000 0111 first byte */
44 c |= ((*src & 0xC0) >> 6); /* 1100 0000 second byte */
45 *dest++ = base32[(int) c];
47 *dest++ = base32[(*src & 0x3E) >> 1]; /* 0011 1110 second byte */
49 c = (*src++ & 0x01) << 4; /* 0000 0001 second byte */
50 c |= ((*src & 0xF0) >> 4); /* 1111 0000 third byte */
51 *dest++ = base32[(int) c];
53 c = (*src++ & 0x0F) << 1; /* 0000 1111 third byte */
54 c |= ((*src & 0x80) >> 7); /* 1000 0000 fourth byte */
55 *dest++ = base32[(int) c];
57 *dest++ = base32[(*src & 0x7C) >> 2]; /* 0111 1100 fourth byte */
59 c = (*src++ & 0x03) << 3; /* 0000 0011 fourth byte */
60 c |= ((*src & 0xE0) >> 5); /* 1110 0000 fifth byte */
61 *dest++ = base32[(int) c];
63 *dest++ = base32[*src++ & 0x1F]; /* 0001 1111 fifth byte */
66 /* Eat 8 bytes from src, write 5 bytes to dest */
68 decode_chunk(char *dest, char *src)
74 for (i = 0; i < 32; i++) {
76 reverse32[(int) c] = i;
81 c = reverse32[(int) *src++] << 3; /* Take bits 11111 from byte 1 */
82 c |= (reverse32[(int) *src] & 0x1C) >> 2; /* Take bits 11100 from byte 2 */
85 c = (reverse32[(int) *src++] & 0x3) << 6; /* Take bits 00011 from byte 2 */
86 c |= reverse32[(int) *src++] << 1; /* Take bits 11111 from byte 3 */
87 c |= (reverse32[(int) *src] & 0x10) >> 4; /* Take bits 10000 from byte 4 */
90 c = (reverse32[(int) *src++] & 0xF) << 4; /* Take bits 01111 from byte 4 */
91 c |= (reverse32[(int) *src] & 0x1E) >> 1; /* Take bits 11110 from byte 5 */
94 c = reverse32[(int) *src++] << 7; /* Take bits 00001 from byte 5 */
95 c |= reverse32[(int) *src++] << 2; /* Take bits 11111 from byte 6 */
96 c |= (reverse32[(int) *src] & 0x18) >> 3; /* Take bits 11000 from byte 7 */
99 c = (reverse32[(int) *src++] & 0x7) << 5; /* Take bits 00111 from byte 7 */
100 c |= reverse32[(int) *src++]; /* Take bits 11111 from byte 8 */
105 encode_data(const char *buf, const size_t len, int space, char *dest)
119 space -= space / SPACING;
120 chunks = (space - 1) / ENC_CHUNK;
121 while ((chunks + 1) * ENC_CHUNK + 1 > space) {
124 write = RAW_CHUNK * chunks;
125 write = MIN(write, len); /* do not use more bytes than is available; */
126 final = (write == len); /* is this the last block? */
127 chunks = write / RAW_CHUNK;
128 leftovers = write % RAW_CHUNK;
130 memset(encoded, 0, sizeof(encoded));
133 for (i = 0; i < chunks; i++) {
134 encode_chunk(ep, dp);
138 realwrite = ENC_CHUNK * chunks;
139 memset(padding, 0, sizeof(padding));
142 pp += RAW_CHUNK - leftovers;
143 memcpy(pp, dp, leftovers);
146 *ep++ = padder[leftovers];
147 encode_chunk(ep, pp);
149 realwrite += ENC_CHUNK + 1; /* plus padding character */
153 for (i = 1; i <= realwrite; i++) {
154 if (i % SPACING == 0) {
165 decode_data(char *dest, int size, const char *src, char *srcend)
177 memset(encoded, 0, sizeof(encoded));
178 memset(dest, 0, size);
180 /* First byte is not encoded */
186 while(enclen < sizeof(encoded) && src < srcend) {
199 for (i = 0; i < chunks-1; i++) {
200 decode_chunk(dest, ep);
205 /* Read last chunk */
208 padded = *ep++ - '0';
209 decode_chunk(pp, ep);
210 pp += RAW_CHUNK - padded;
211 memcpy(dest, pp, padded);
214 decode_chunk(dest, ep);