view f-demime/msgstate.c @ 8:a92d0d59b669 default tip

f-demime: indicate X-backslash-escapes encoding in output
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 06 May 2023 17:00:23 +0000
parents 612c4d0df768
children
line wrap: on
line source

/*
 * This module implements the message state machine, receiving input lines
 * and message start/end markers from the input processing main loop.
 */

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

enum msg_state msg_state;
enum msg_hdr_state hdr_state;
unsigned mp_nest_level;
char mp_boundaries[MAX_MP_NESTING][MAX_MP_BOUNDARY+1];
int mp_is_digest[MAX_MP_NESTING];
char cont_type_buf[HDR_BUF_SIZE], cont_te_buf[HDR_BUF_SIZE];
int got_cont_type, got_cont_te;

void
start_entity_hdr()
{
	msg_state = MSG_STATE_HEADER;
	hdr_state = HDR_STATE_BEGIN;
	got_cont_type = 0;
	got_cont_te = 0;
}

void
begin_new_message()
{
	mp_nest_level = 0;
	start_entity_hdr();
}

static void
emit_prefrom_warning()
{
	static int done;

	if (done)
		return;
	fprintf(stderr,
		"f-demime warning: data present before the first From\n");
	done = 1;
}

static int
check_mp_terminator(line, unterm)
	char *line;
{
	unsigned lev, bndlen;
	char *bnd, *cp;

	if (line[0] != '-' || line[1] != '-')
		return(0);
	for (lev = 0; lev < mp_nest_level; lev++) {
		bnd = mp_boundaries[lev];
		bndlen = strlen(bnd);
		if (strncmp(line+2, bnd, bndlen))
			continue;
		finish_msg_body();
		fputs(line, stdout);
		cp = line + 2 + bndlen;
		if (!*cp || isspace(*cp)) {
			mp_nest_level = lev + 1;
			start_entity_hdr();
			if (unterm)
				msg_state = MSG_STATE_DELIM_UNTERM;
			return(1);
		}
		if (cp[0] != '-' || cp[1] != '-') {
			if (!unterm)
				puts("X-Fdemime-Error: invalid delimiter line");
		}
		mp_nest_level = lev;
		msg_state = MSG_STATE_BODY_PASS;
		return(1);
	}
	return(0);
}

void
message_input_line(line, unterm, prev_unterm)
	char *line;
{
	if (!prev_unterm && check_mp_terminator(line, unterm))
		return;
	switch (msg_state) {
	case MSG_STATE_UNDEF:
		emit_prefrom_warning();
		fputs(line, stdout);
		return;
	case MSG_STATE_DELIM_UNTERM:
		fputs(line, stdout);
		if (!unterm)
			msg_state = MSG_STATE_HEADER;
		return;
	case MSG_STATE_HEADER:
		header_input_line(line, unterm, prev_unterm);
		return;
	case MSG_STATE_BODY_PASS:
		fputs(line, stdout);
		return;
	case MSG_STATE_PTEXT_B64:
	case MSG_STATE_BLOB_B64:
	case MSG_STATE_B64_TO_QP:
		base64_input_line(line);
		return;
	case MSG_STATE_PTEXT_QP:
		qpdec_input_line(line, unterm);
		return;
	default:
		fprintf(stderr,
		"f-demime internal error: bad state in message_input_line()\n");
		abort();
	}
}