Skip to content
Snippets Groups Projects
base64.c 3.93 KiB
Newer Older
deuce's avatar
deuce committed
/* Base64 encoding/decoding routines */

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
 * Copyright Rob Swindell - http://www.synchro.net/copyright.html			*
deuce's avatar
deuce committed
 *																			*
 * This library is free software; you can redistribute it and/or			*
 * modify it under the terms of the GNU Lesser General Public License		*
deuce's avatar
deuce committed
 * as published by the Free Software Foundation; either version 2			*
 * of the License, or (at your option) any later version.					*
 * See the GNU Lesser General Public License for more details: lgpl.txt or	*
 * http://www.fsf.org/copyleft/lesser.html									*
deuce's avatar
deuce committed
 *																			*
 * For Synchronet coding style and modification guidelines, see				*
 * http://www.synchro.net/source.html										*
 *																			*
 * Note: If this box doesn't appear square, then you need to fix your tabs.	*
 ****************************************************************************/

deuce's avatar
deuce committed
#include <stdlib.h>
deuce's avatar
deuce committed
#include <string.h>
#include "base64.h"
static const char * base64alphabet =
	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
deuce's avatar
deuce committed
int b64_decode(char *target, size_t tlen, const char *source, size_t slen)
	const char *inp;
	char *      outp;
	char *      outend;
	const char *inend;
	int         bits = 0;
	int         working = 0;
	char *      i;
	if (slen == 0)
		slen = strlen(source);
	outp = target;
	inp = source;
	outend = target + tlen;
	inend = source + slen;
	for (; outp < outend && inp < inend; inp++) {
		if (isspace(*inp))
		working <<= 6;
		i = strchr(base64alphabet, (char)*inp);
		if (i == NULL) {
		if (*i == '=')  { /* pad char */
			if ((working & 0xFF) != 0)
		bits += 6;
		working |= (i - base64alphabet);
		if (bits >= 8) {
			*(outp++) = (char)((working & (0xFF << (bits - 8))) >> (bits - 8));
			bits -= 8;
	if (outp == outend)  {
		*(--outp) = 0;
	return outp - target;
static int add_char(char *pos, char ch, int done, char *end)
	if (done)
		*pos = base64alphabet[64];
deuce's avatar
deuce committed
	else
		*pos = base64alphabet[(int)ch];
int b64_encode(char *target, size_t tlen, const char *source, size_t slen)  {
	const char *inp;
	char *      outp;
	char *      outend;
	const char *inend;
	char *      tmpbuf = NULL;
	int         done = 0;
	char        enc;
	int         buf;

	inp = source;
	if (source == target)  {
		tmpbuf = (char *)malloc(tlen);
		if (tmpbuf == NULL)
	outend = outp + tlen;
	inend = inp + slen;
	for (; (inp < inend) && !done;)  {
		enc = *(inp++);
		buf = (enc & 0x03) << 4;
		enc = (enc & 0xFC) >> 2;
		if (add_char(outp++, enc, done, outend)) {
		if (inp >= inend)
			enc = buf;
deuce's avatar
deuce committed
		else
			enc = buf | ((*inp & 0xF0) >> 4);
		if (add_char(outp++, enc, done, outend)) {
		if (inp == inend)
			done = 1;
			buf = (*(inp++) << 2) & 0x3C;
				enc = buf | ((*inp & 0xC0) >> 6);
		if (add_char(outp++, enc, done, outend)) {
		if (inp == inend)
			done = 1;
			enc = ((int)*(inp++)) & 0x3F;
		if (add_char(outp++, enc, done, outend)) {
		if (inp == inend)
			done = 1;
	if (outp < outend)
		*outp = 0;
	if (source == target) {
		memcpy(target, tmpbuf, tlen);
rswindell's avatar
rswindell committed

#ifdef BASE64_TEST
int main(int argc, char**argv)
{
rswindell's avatar
rswindell committed
	char buf[512];

	for (i = 1; i < argc; i++) {
		j = b64_decode(buf, sizeof(buf), argv[i], 0);
		printf("%s (%d)\n", buf, j);
rswindell's avatar
rswindell committed
	}

	return 0;
}
#endif