source: src/base64.c @ eed52b

Revision eed52b, 4.3 KB checked in by Erik Ekman <yarrick@…>, 4 years ago (diff)

#51 handle one block encode/decode for base64

  • Property mode set to 100644
Line 
1/*
2 * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
3 *
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.
7 *
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.
15 */
16
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20
21#include "encoding.h"
22#include "common.h"
23#include "base64.h"
24
25#define BLKSIZE_RAW 3
26#define BLKSIZE_ENC 4
27
28static const char cb64[] =
29        "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789+";
30static unsigned char rev64[128];
31static int reverse_init = 0;
32
33static int base64_encode(char *, size_t *, const void *, size_t);
34static int base64_decode(void *, size_t *, const char *, size_t);
35static int base64_handles_dots();
36static int base64_blksize_raw();
37static int base64_blksize_enc();
38
39#define REV64(x) rev64[(int) (x)]
40
41static struct encoder base64_encoder =
42{
43        "Base64",
44        base64_encode,
45        base64_decode,
46        base64_handles_dots,
47        base64_handles_dots,
48        base64_blksize_raw,
49        base64_blksize_enc
50};
51
52struct encoder
53*get_base64_encoder()
54{
55        return &base64_encoder;
56}
57
58static int
59base64_handles_dots()
60{
61        return 0;
62}
63
64static int
65base64_blksize_raw()
66{
67        return BLKSIZE_RAW;
68}
69
70static int
71base64_blksize_enc()
72{
73        return BLKSIZE_ENC;
74}
75
76static int
77base64_encode(char *buf, size_t *buflen, const void *data, size_t size)
78{
79        size_t newsize;
80        size_t maxsize;
81        unsigned char c;
82        unsigned char *s;
83        unsigned char *p;
84        unsigned char *q;
85        int i;
86
87        memset(buf, 0, *buflen);
88       
89        if (!reverse_init) {
90                for (i = 0; i < 64; i++) {
91                        c = cb64[i];
92                        rev64[(int) c] = i;
93                }
94                reverse_init = 1;
95        }
96
97        /* how many chars can we encode within the buf */
98        maxsize = BLKSIZE_RAW * (*buflen / BLKSIZE_ENC);
99        /* how big will the encoded data be */
100        newsize = BLKSIZE_ENC * (size / BLKSIZE_RAW);
101        if (size % BLKSIZE_RAW) {
102                newsize += BLKSIZE_ENC;
103        }
104
105        /* if the buffer is too small, eat some of the data */
106        if (*buflen < newsize) {
107                size = maxsize;
108        }
109
110        p = s = (unsigned char *) buf;
111        q = (unsigned char *)data;
112
113        for(i=0;i<size;i+=BLKSIZE_RAW) {
114                p[0] = cb64[((q[0] & 0xfc) >> 2)];
115                p[1] = cb64[(((q[0] & 0x03) << 4) | ((q[1] & 0xf0) >> 4))];
116                p[2] = (i+1 < size) ? cb64[((q[1] & 0x0f) << 2 ) | ((q[2] & 0xc0) >> 6)] : '\0';
117                p[3] = (i+2 < size) ? cb64[(q[2] & 0x3f)] : '\0';
118               
119                q += BLKSIZE_RAW;
120                p += BLKSIZE_ENC;
121        }       
122        *p = 0;
123
124        /* store number of bytes from data that was used */
125        *buflen = size;
126
127        return strlen(buf);
128}
129
130#define DECODE_ERROR 0xffffffff
131
132static int
133decode_token(const unsigned char *t, unsigned char *data, size_t len)
134{
135        if (len < 2)
136                return 0;
137
138        data[0] = ((REV64(t[0]) & 0x3f) << 2) |
139                          ((REV64(t[1]) & 0x30) >> 4);
140
141        if (len < 3)
142                return 1;
143
144        data[1] = ((REV64(t[1]) & 0x0f) << 4) |
145                          ((REV64(t[2]) & 0x3c) >> 2);
146
147        if (len < 4)
148                return 2;
149
150        data[2] = ((REV64(t[2]) & 0x03) << 6) |
151                          (REV64(t[3]) & 0x3f);
152
153        return 3;
154}
155
156static int
157base64_decode(void *buf, size_t *buflen, const char *str, size_t slen)
158{
159        unsigned char *q;
160        size_t newsize;
161        size_t maxsize;
162        const char *p;
163        unsigned char c;
164        unsigned char block[BLKSIZE_ENC];
165        int len;
166        int i;
167
168        if (!reverse_init) {
169                for (i = 0; i < 64; i++) {
170                        c = cb64[i];
171                        rev64[(int) c] = i;
172                }
173                reverse_init = 1;
174        }
175       
176        /* chars needed to decode slen */
177        newsize = BLKSIZE_RAW * (slen / BLKSIZE_ENC + 1) + 1;
178        /* encoded chars that fit in buf */
179        maxsize = BLKSIZE_ENC * (*buflen / BLKSIZE_RAW + 1) + 1;
180        /* if the buffer is too small, eat some of the data */
181        if (*buflen < newsize) {
182                slen = maxsize;
183        }
184       
185
186        q = buf;
187        for (p = str; *p; p += BLKSIZE_ENC) {
188                /* since the str is const, we unescape in another buf */
189                for (i = 0; i < BLKSIZE_ENC; i++) {
190                        block[i] = p[i];
191                }
192                len = decode_token(block, (unsigned char *) q, slen);   
193                q += len;
194                slen -= BLKSIZE_ENC;
195               
196                if (len < BLKSIZE_RAW)
197                        break;
198        }
199        *q = '\0';
200       
201        return q - (unsigned char *) buf;
202}
203
Note: See TracBrowser for help on using the repository browser.