view f-demime/base64.c @ 2:1857d0d5a7bd

f-demime: fix parsing of Content-* headers
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 06 May 2023 06:33:26 +0000
parents 7e0d08176f32
children
line wrap: on
line source

/*
 * This module implements base64 decoding.
 */

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include "defs.h"

extern void (*dec_outf)();

static unsigned b64_accum, b64_eq_flag;
static int b64_state, last_partial;
int b64_err_flag, b64_nonempty;

void
base64_dec_init()
{
	b64_accum = 0;
	b64_eq_flag = 0;
	b64_state = 0;
	b64_err_flag = 0;
	b64_nonempty = 0;
	last_partial = 0;
}

static void
process_unit()
{
	if (last_partial)
		b64_err_flag = 1;
	switch (b64_eq_flag) {
	case 0:
		dec_outf(b64_accum >> 16);
		dec_outf((b64_accum >> 8) & 0xFF);
		dec_outf(b64_accum & 0xFF);
		last_partial = 0;
		break;
	case 1:
		dec_outf(b64_accum >> 16);
		dec_outf((b64_accum >> 8) & 0xFF);
		last_partial = 1;
		break;
	case 3:
		dec_outf(b64_accum >> 16);
		last_partial = 1;
		break;
	default:
		b64_err_flag = 1;
	}
	b64_accum = 0;
	b64_eq_flag = 0;
	b64_state = 0;
}

static void
base64_input_char(ch)
{
	int code;

	b64_nonempty = 1;
	if (ch >= 'A' && ch <= 'Z')
		code = ch - 'A';
	else if (ch >= 'a' && ch <= 'z')
		code = ch - 'a' + 26;
	else if (ch >= '0' && ch <= '9')
		code = ch - '0' + 52;
	else switch (ch) {
	case '+':
		code = 62;
		break;
	case '/':
		code = 63;
		break;
	case '=':
		code = 64;
		break;
	default:
		b64_err_flag = 1;
		return;
	}
	b64_accum <<= 6;
	b64_accum |= (code & 63);
	b64_eq_flag <<= 1;
	b64_eq_flag |= (code >> 6);
	b64_state++;
	if (b64_state >= 4)
		process_unit();
}

void
base64_input_line(line)
	char *line;
{
	char *cp;
	int c;

	for (cp = line; *cp; ) {
		c = *cp++;
		if (!isspace(c))
			base64_input_char(c);
	}
}

void
base64_dec_finish()
{
	if (b64_state)
		b64_err_flag = 1;
}