Statistics
| Revision:

root / libsylph / base64.c @ 3052

History | View | Annotate | Download (4.2 kB)

1 528 hiro
/*
2 578 hiro
 * LibSylph -- E-Mail client library
3 578 hiro
 * Copyright (C) 1999-2005 Hiroyuki Yamamoto
4 528 hiro
 *
5 578 hiro
 * This library is free software; you can redistribute it and/or
6 578 hiro
 * modify it under the terms of the GNU Lesser General Public
7 578 hiro
 * License as published by the Free Software Foundation; either
8 578 hiro
 * version 2.1 of the License, or (at your option) any later version.
9 528 hiro
 *
10 578 hiro
 * This library is distributed in the hope that it will be useful,
11 528 hiro
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 578 hiro
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 578 hiro
 * Lesser General Public License for more details.
14 528 hiro
 *
15 578 hiro
 * You should have received a copy of the GNU Lesser General Public
16 578 hiro
 * License along with this library; if not, write to the Free Software
17 578 hiro
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18 528 hiro
 */
19 528 hiro
20 528 hiro
#include <glib.h>
21 528 hiro
#include <ctype.h>
22 528 hiro
#include <string.h>
23 528 hiro
24 528 hiro
#include "base64.h"
25 528 hiro
26 528 hiro
static const gchar base64char[64] =
27 528 hiro
        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
28 528 hiro
29 528 hiro
static const gchar base64val[128] = {
30 528 hiro
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
31 528 hiro
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
32 528 hiro
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
33 528 hiro
        52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
34 528 hiro
        -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
35 528 hiro
        15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
36 528 hiro
        -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
37 528 hiro
        41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1
38 528 hiro
};
39 528 hiro
40 528 hiro
#define BASE64VAL(c)        (isascii((guchar)c) ? base64val[(gint)(c)] : -1)
41 528 hiro
42 528 hiro
void base64_encode(gchar *out, const guchar *in, gint inlen)
43 528 hiro
{
44 528 hiro
        const guchar *inp = in;
45 528 hiro
        gchar *outp = out;
46 528 hiro
47 528 hiro
        while (inlen >= 3) {
48 528 hiro
                *outp++ = base64char[(inp[0] >> 2) & 0x3f];
49 528 hiro
                *outp++ = base64char[((inp[0] & 0x03) << 4) |
50 528 hiro
                                     ((inp[1] >> 4) & 0x0f)];
51 528 hiro
                *outp++ = base64char[((inp[1] & 0x0f) << 2) |
52 528 hiro
                                     ((inp[2] >> 6) & 0x03)];
53 528 hiro
                *outp++ = base64char[inp[2] & 0x3f];
54 528 hiro
55 528 hiro
                inp += 3;
56 528 hiro
                inlen -= 3;
57 528 hiro
        }
58 528 hiro
59 528 hiro
        if (inlen > 0) {
60 528 hiro
                *outp++ = base64char[(inp[0] >> 2) & 0x3f];
61 528 hiro
                if (inlen == 1) {
62 528 hiro
                        *outp++ = base64char[(inp[0] & 0x03) << 4];
63 528 hiro
                        *outp++ = '=';
64 528 hiro
                } else {
65 528 hiro
                        *outp++ = base64char[((inp[0] & 0x03) << 4) |
66 528 hiro
                                             ((inp[1] >> 4) & 0x0f)];
67 528 hiro
                        *outp++ = base64char[((inp[1] & 0x0f) << 2)];
68 528 hiro
                }
69 528 hiro
                *outp++ = '=';
70 528 hiro
        }
71 528 hiro
72 528 hiro
        *outp = '\0';
73 528 hiro
}
74 528 hiro
75 528 hiro
gint base64_decode(guchar *out, const gchar *in, gint inlen)
76 528 hiro
{
77 528 hiro
        const gchar *inp = in;
78 528 hiro
        guchar *outp = out;
79 528 hiro
        gchar buf[4];
80 528 hiro
81 528 hiro
        if (inlen < 0)
82 528 hiro
                inlen = G_MAXINT;
83 528 hiro
84 528 hiro
        while (inlen >= 4 && *inp != '\0') {
85 528 hiro
                buf[0] = *inp++;
86 528 hiro
                inlen--;
87 528 hiro
                if (BASE64VAL(buf[0]) == -1) break;
88 528 hiro
89 528 hiro
                buf[1] = *inp++;
90 528 hiro
                inlen--;
91 528 hiro
                if (BASE64VAL(buf[1]) == -1) break;
92 528 hiro
93 528 hiro
                buf[2] = *inp++;
94 528 hiro
                inlen--;
95 528 hiro
                if (buf[2] != '=' && BASE64VAL(buf[2]) == -1) break;
96 528 hiro
97 528 hiro
                buf[3] = *inp++;
98 528 hiro
                inlen--;
99 528 hiro
                if (buf[3] != '=' && BASE64VAL(buf[3]) == -1) break;
100 528 hiro
101 528 hiro
                *outp++ = ((BASE64VAL(buf[0]) << 2) & 0xfc) |
102 528 hiro
                          ((BASE64VAL(buf[1]) >> 4) & 0x03);
103 528 hiro
                if (buf[2] != '=') {
104 528 hiro
                        *outp++ = ((BASE64VAL(buf[1]) & 0x0f) << 4) |
105 528 hiro
                                  ((BASE64VAL(buf[2]) >> 2) & 0x0f);
106 528 hiro
                        if (buf[3] != '=') {
107 528 hiro
                                *outp++ = ((BASE64VAL(buf[2]) & 0x03) << 6) |
108 528 hiro
                                           (BASE64VAL(buf[3]) & 0x3f);
109 528 hiro
                        }
110 528 hiro
                }
111 528 hiro
        }
112 528 hiro
113 528 hiro
        return outp - out;
114 528 hiro
}
115 528 hiro
116 528 hiro
Base64Decoder *base64_decoder_new(void)
117 528 hiro
{
118 528 hiro
        Base64Decoder *decoder;
119 528 hiro
120 528 hiro
        decoder = g_new0(Base64Decoder, 1);
121 528 hiro
        return decoder;
122 528 hiro
}
123 528 hiro
124 528 hiro
void base64_decoder_free(Base64Decoder *decoder)
125 528 hiro
{
126 528 hiro
        g_free(decoder);
127 528 hiro
}
128 528 hiro
129 528 hiro
gint base64_decoder_decode(Base64Decoder *decoder,
130 528 hiro
                           const gchar *in, guchar *out)
131 528 hiro
{
132 528 hiro
        gint len, total_len = 0;
133 528 hiro
        gint buf_len;
134 528 hiro
        gchar buf[4];
135 528 hiro
136 528 hiro
        g_return_val_if_fail(decoder != NULL, -1);
137 528 hiro
        g_return_val_if_fail(in != NULL, -1);
138 528 hiro
        g_return_val_if_fail(out != NULL, -1);
139 528 hiro
140 528 hiro
        buf_len = decoder->buf_len;
141 528 hiro
        memcpy(buf, decoder->buf, sizeof(buf));
142 528 hiro
143 528 hiro
        for (;;) {
144 528 hiro
                while (buf_len < 4) {
145 528 hiro
                        gchar c = *in;
146 528 hiro
147 528 hiro
                        in++;
148 528 hiro
                        if (c == '\0') break;
149 528 hiro
                        if (c == '\r' || c == '\n') continue;
150 528 hiro
                        if (c != '=' && BASE64VAL(c) == -1)
151 528 hiro
                                return -1;
152 528 hiro
                        buf[buf_len++] = c;
153 528 hiro
                }
154 528 hiro
                if (buf_len < 4 || buf[0] == '=' || buf[1] == '=') {
155 528 hiro
                        decoder->buf_len = buf_len;
156 528 hiro
                        memcpy(decoder->buf, buf, sizeof(buf));
157 528 hiro
                        return total_len;
158 528 hiro
                }
159 528 hiro
                len = base64_decode(out, buf, 4);
160 528 hiro
                out += len;
161 528 hiro
                total_len += len;
162 528 hiro
                buf_len = 0;
163 528 hiro
                if (len < 3) {
164 528 hiro
                        decoder->buf_len = 0;
165 528 hiro
                        return total_len;
166 528 hiro
                }
167 528 hiro
        }
168 528 hiro
}