1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
4 * (GLABELS) Label and Business Card Creation program for GNOME
6 * base64.c: GLabels base64 encode/decode module
8 * Copyright (C) 2003 Jim Evins <evins@snaught.com>
10 * This module is based on base64.c from fetchmail:
12 * Copyright (C)2002 by Eric S. Raymond.
13 * Portions are copyrighted by Carl E. Harris and George M. Sipe.
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 * This base 64 encoding is defined in RFC2045 section 6.8.
37 #include <glib/gmem.h>
41 /*========================================================*/
42 /* Private macros and constants. */
43 /*========================================================*/
45 #define LINE_LENGTH 76 /* Must be <= 76 and must be a multiple of 4 */
48 #define DECODE64(c) (isascii(c) ? base64val[c] : BAD)
50 /*========================================================*/
52 /*========================================================*/
54 /*========================================================*/
55 /* Private globals. */
56 /*========================================================*/
58 static const gchar base64digits[] =
59 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
61 static const gchar base64val[] = {
62 BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
63 BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
64 BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD, 62, BAD,BAD,BAD, 63,
65 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,BAD,BAD, BAD,BAD,BAD,BAD,
66 BAD, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
67 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,BAD, BAD,BAD,BAD,BAD,
68 BAD, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
69 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,BAD, BAD,BAD,BAD,BAD
72 /*========================================================*/
73 /* Private function prototypes. */
74 /*========================================================*/
77 /*****************************************************************************/
78 /* Encode to Base64 string. */
79 /*****************************************************************************/
81 gl_base64_encode (const guchar *in, guint inlen)
87 /* Calculate output buffer size */
88 buf_size = 4*((inlen+2)/3); /* Encoded characters */
89 buf_size += buf_size / LINE_LENGTH + 2; /* Line breaks */
90 buf_size += 1; /* null termination */
92 /* Allocate output buffer */
93 out = g_new0 (gchar, buf_size);
96 /* Now do the encoding */
98 for ( i=0; inlen >= 3; inlen-=3 ) {
100 *p_out++ = base64digits[in[0] >> 2];
101 *p_out++ = base64digits[((in[0] << 4) & 0x30) | (in[1] >> 4)];
102 *p_out++ = base64digits[((in[1] << 2) & 0x3c) | (in[2] >> 6)];
103 *p_out++ = base64digits[in[2] & 0x3f];
107 if ( (i % LINE_LENGTH) == 0 ) {
115 *p_out++ = base64digits[in[0] >> 2];
116 fragment = (in[0] << 4) & 0x30;
118 fragment |= in[1] >> 4;
119 *p_out++ = base64digits[fragment];
120 *p_out++ = (inlen < 2) ? '=' : base64digits[(in[1] << 2) & 0x3c];
130 /*****************************************************************************/
131 /* Decode from a Base64 string. */
132 /*****************************************************************************/
134 gl_base64_decode (const gchar *in, guint *outlen)
138 register guchar digit1, digit2, digit3, digit4;
140 /* Calculate output buffer size */
141 buf_size = strlen (in) * 3 / 4;
143 /* Allocate output buffer */
144 out = g_new0 (gchar, buf_size);
149 /* Skip non-printable characters */
150 while ( (*in == '\n') || (*in == '\r') || (*in == ' ') ) {
158 /* Now do the decoding */
161 if (DECODE64(digit1) == BAD) {
166 if (DECODE64(digit2) == BAD) {
171 if (digit3 != '=' && DECODE64(digit3) == BAD) {
176 if (digit4 != '=' && DECODE64(digit4) == BAD) {
182 *p_out++ = (DECODE64(digit1)<<2) | (DECODE64(digit2) >> 4);
186 *p_out++ = ((DECODE64(digit2)<<4)&0xf0) | (DECODE64(digit3)>>2);
190 *p_out++ = ((DECODE64(digit3)<<6)&0xc0) | DECODE64(digit4);
195 /* Skip non-printable characters */
196 while ( (*in == '\n') || (*in == '\r') || (*in == ' ') ) {
200 } while (*in && digit4 != '=');
202 return (guchar *)out;