~sircmpwn/hare-message

bcbe6220310b9161ccc0ab3b64c5152aedbc9da4 — Drew DeVault 8 months ago 7dab49f
message: implement header_write
1 files changed, 44 insertions(+), 0 deletions(-)

M message/header.ha
M message/header.ha => message/header.ha +44 -0
@@ 340,6 340,50 @@ export fn header_set(head: *header, key: str, val: str) void = {
	assert(vals[0] == "text/x-hare");
};

// Writes a MIME [[header]] to an [[io::handle]].
export fn write_header(sink: io::handle, head: *header) (size | io::error) = {
	let z = 0z;
	for (let i = len(head.fields); i > 0; i -= 1) {
		const field = head.fields[i - 1];
		const raw = header_field_raw(field)!;
		z += io::writeall(sink, raw)?;
	};
	z += fmt::fprint(sink, "\r\n")?;
	return z;
};

@test fn write_header() void = {
	const head = new_header();
	defer header_finish(&head);

	const dkim = "DKIM-Signature: a=rsa-sha256; bh=uI/rVH7mLBSWkJVvQYKz3TbpdI2BLZWTIMKcuo0KHOI=; c=simple/simple; d=example.org; h=Subject:To:From; s=default; t=1577562184; v=1; b=;\r\n";
	header_add(&head, "DKIM-Signature", "a=rsa-sha256; bh=uI/rVH7mLBSWkJVvQYKz3TbpdI2BLZWTIMKcuo0KHOI=; c=simple/simple; d=example.org; h=Subject:To:From; s=default; t=1577562184; v=1; b=;");
	header_add_raw(&head, strings::toutf8(dkim));
	header_add(&head, "Content-Type", "text/html");
	header_add(&head, "Content-Type", "text/plain");
	header_add(&head, "FROM", "Harriet <harriet@harelang.org>");
	header_add(&head, "to", "Drew DeVault <sir@cmpwn.com>");

	const sink = strio::dynamic();
	defer io::close(&sink)!;
	write_header(&sink, &head)!;
	const result = strio::string(&sink);

	const expect =
		"To: Drew DeVault <sir@cmpwn.com>\r\n"
		"From: Harriet <harriet@harelang.org>\r\n"
		"Content-Type: text/plain\r\n"
		"Content-Type: text/html\r\n"
		// Should not fold or canonicalize
		"DKIM-Signature: a=rsa-sha256; bh=uI/rVH7mLBSWkJVvQYKz3TbpdI2BLZWTIMKcuo0KHOI=; c=simple/simple; d=example.org; h=Subject:To:From; s=default; t=1577562184; v=1; b=;\r\n"
		// Should fold & canonicalize
		"Dkim-Signature: a=rsa-sha256;\r\n"
		" bh=uI/rVH7mLBSWkJVvQYKz3TbpdI2BLZWTIMKcuo0KHOI=; c=simple/simple;\r\n"
		" d=example.org; h=Subject:To:From; s=default; t=1577562184; v=1; b=;\r\n"
		"\r\n";
	assert(result == expect);
};

def PREFERRED_HEADER_LEN = 76z;
def MAX_HEADER_LEN = 998z;