UNPKG

dkim-verifier

Version:

DKIM Signature Verifier in TypeScript

134 lines 4.69 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.parseEmailToCanonicalized = exports.parseEmail = void 0; const header_1 = require("./header"); const canonicalization_1 = require("./canonicalization"); var HeaderParseState; (function (HeaderParseState) { HeaderParseState[HeaderParseState["Initial"] = 0] = "Initial"; HeaderParseState[HeaderParseState["Key"] = 1] = "Key"; HeaderParseState[HeaderParseState["PreValue"] = 2] = "PreValue"; HeaderParseState[HeaderParseState["Value"] = 3] = "Value"; HeaderParseState[HeaderParseState["ValueNewline"] = 4] = "ValueNewline"; HeaderParseState[HeaderParseState["Complete"] = 5] = "Complete"; })(HeaderParseState || (HeaderParseState = {})); const parseEmail = (rawData) => { const emailFormatData = rawData.replace(/\r\n|\n/g, "\r\n"); const [headers, ix] = parseHeaders(emailFormatData); const dkim = (0, header_1.parseDkim)(headers); const body = emailFormatData.slice(ix, emailFormatData.length); return { headers, dkim, body }; }; exports.parseEmail = parseEmail; const parseEmailToCanonicalized = (rawData) => { const { dkim, headers, body } = (0, exports.parseEmail)(rawData); const canonicalizeInstruction = (0, canonicalization_1.newCanonicalization)(dkim.c); const [canonicalizedHeaders, canonicalizedBody] = (0, canonicalization_1.canonicalize)(canonicalizeInstruction, dkim, headers, body); return { canonicalizedHeaders, canonicalizedBody, dkim }; }; exports.parseEmailToCanonicalized = parseEmailToCanonicalized; const parseHeaders = (rawData) => { const headers = []; let i = 0; while (i < rawData.length) { if (rawData[i] === "\n") { i++; break; } else if (rawData[i] === "\r") { if (i + 1 < rawData.length && rawData[i + 1] === "\n") { i += 2; break; } else { throw new Error("Invalid header"); } } const [header, i_next] = parseHeader(rawData.slice(i, rawData.length)); headers.push(header); i += i_next; } return [headers, i]; }; const parseHeader = (rawData) => { let ix = 0; let ix_key_end = 0; let ix_value_start = 0; let ix_value_end = 0; const chars = [...rawData]; let state = HeaderParseState.Initial; for (let i = 0; i < chars.length; i++) { const c = chars[i]; switch (state) { case HeaderParseState.Initial: { if (c === " ") { throw new Error("Invalid header"); } state = HeaderParseState.Key; continue; } case HeaderParseState.Key: { if (c === ":") { ix_key_end = i; state = HeaderParseState.PreValue; continue; } else if (c === "\n") { ix_key_end = i; ix_value_start = i; ix_value_end = i; state = HeaderParseState.Complete; break; } continue; } case HeaderParseState.PreValue: { if (c !== " ") { ix_value_start = i; ix_value_end = i; state = HeaderParseState.Value; continue; } continue; } case HeaderParseState.Value: { if (c === "\n") { state = HeaderParseState.ValueNewline; continue; } else if (c !== "\r") { ix_value_end = i + 1; continue; } continue; } case HeaderParseState.ValueNewline: { if (c === " " || c === "\t") { state = HeaderParseState.Value; continue; } else { state = HeaderParseState.Complete; break; } } } if (state === HeaderParseState.Complete) { ix = i; break; } } return [ ix_key_end !== 0 ? { key: rawData.slice(0, ix_key_end), value: rawData.slice(ix_value_start, ix_value_end), } : { key: rawData.slice(0, ix), value: rawData.slice(ix, ix), }, ix, ]; }; //# sourceMappingURL=parser.js.map