dkim-verifier
Version:
DKIM Signature Verifier in TypeScript
134 lines • 4.69 kB
JavaScript
;
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