Skip to content

Commit

Permalink
Backport Feature: 5 -> 2.x internationalization support 2023-12-16 (#418
Browse files Browse the repository at this point in the history
)
  • Loading branch information
dodmi authored Jan 7, 2024
1 parent 9c939f1 commit a010e90
Show file tree
Hide file tree
Showing 6 changed files with 371 additions and 277 deletions.
2 changes: 2 additions & 0 deletions defaults/preferences/prefs.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ pref("extensions.dkim_verifier.key.storing", 0);
pref("extensions.dkim_verifier.saveResult", false);
pref("extensions.dkim_verifier.arh.read", false);

pref("extensions.dkim_verifier.internationalized.enable", false);

////////////////////////////////////////////////////////////////////////////////
// general preferences - DNS
////////////////////////////////////////////////////////////////////////////////
Expand Down
85 changes: 14 additions & 71 deletions modules/ARHParser.jsm.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

// options for ESLint
/* global Components, Services */
/* global Logging, DKIM_Error */
/* global Logging, rfcParser, DKIM_Error */
/* exported EXPORTED_SYMBOLS, ARHParser */

"use strict";
Expand All @@ -37,70 +37,13 @@ Cu.import("resource://gre/modules/Services.jsm");

Cu.import("resource://dkim_verifier/logging.jsm.js");
Cu.import("resource://dkim_verifier/helper.jsm.js");

Cu.import("resource://dkim_verifier/rfcParser.jsm.js");

// @ts-ignore
var prefs = Services.prefs.getBranch(PREF_BRANCH);
// @ts-ignore
const log = Logging.getLogger("ARHParser");


// WSP as specified in Appendix B.1 of RFC 5234
const WSP_p = "[ \t]";
// VCHAR as specified in Appendix B.1 of RFC 5234
const VCHAR_p = "[!-~]";
// Let-dig as specified in Section 4.1.2 of RFC 5321 [SMTP].
const Let_dig_p = "[A-Za-z0-9]";
// Ldh-str as specified in Section 4.1.2 of RFC 5321 [SMTP].
const Ldh_str_p = `(?:[A-Za-z0-9-]*${Let_dig_p})`;
// "Keyword" as specified in Section 4.1.2 of RFC 5321 [SMTP].
const Keyword_p = Ldh_str_p;
// sub-domain as specified in Section 4.1.2 of RFC 5321 [SMTP].
const sub_domain_p = `(?:${Let_dig_p}${Ldh_str_p}?)`;
// obs-FWS as specified in Section 4.2 of RFC 5322
const obs_FWS_p = `(?:${WSP_p}+(?:\r\n${WSP_p}+)*)`;
// quoted-pair as specified in Section 3.2.1 of RFC 5322
// Note: obs-qp is not included, so this pattern matches less then specified!
const quoted_pair_p = `(?:\\\\(?:${VCHAR_p}|${WSP_p}))`;
// FWS as specified in Section 3.2.2 of RFC 5322
const FWS_p = `(?:(?:(?:${WSP_p}*\r\n)?${WSP_p}+)|${obs_FWS_p})`;
const FWS_op = `${FWS_p}?`;
// ctext as specified in Section 3.2.2 of RFC 5322
const ctext_p = "[!-'*-[\\]-~]";
// ccontent as specified in Section 3.2.2 of RFC 5322
// Note: comment is not included, so this pattern matches less then specified!
const ccontent_p = `(?:${ctext_p}|${quoted_pair_p})`;
// comment as specified in Section 3.2.2 of RFC 5322
const comment_p = `\\((?:${FWS_op}${ccontent_p})*${FWS_op}\\)`;
// CFWS as specified in Section 3.2.2 of RFC 5322 [MAIL]
const CFWS_p = `(?:(?:(?:${FWS_op}${comment_p})+${FWS_op})|${FWS_p})`;
const CFWS_op = `${CFWS_p}?`;
// atext as specified in Section 3.2.3 of RFC 5322
const atext_p = "[!#-'*-+/-9=?A-Z^-~-]";
// dot-atom-text as specified in Section 3.2.3 of RFC 5322
const dot_atom_text_p = `(?:${atext_p}+(?:\\.${atext_p}+)*)`;
// dot-atom as specified in Section 3.2.3 of RFC 5322
// dot-atom = [CFWS] dot-atom-text [CFWS]
const dot_atom_p = `(?:${CFWS_op}${dot_atom_text_p}${CFWS_op})`;
// qtext as specified in Section 3.2.4 of RFC 5322
// Note: obs-qtext is not included, so this pattern matches less then specified!
const qtext_p = "[!#-[\\]-~]";
// qcontent as specified in Section 3.2.4 of RFC 5322
const qcontent_p = `(?:${qtext_p}|${quoted_pair_p})`;
// quoted-string as specified in Section 3.2.4 of RFC 5322
const quoted_string_p = `(?:${CFWS_op}"(?:${FWS_op}${qcontent_p})*${FWS_op}"${CFWS_op})`;
const quoted_string_cp = `(?:${CFWS_op}"((?:${FWS_op}${qcontent_p})*)${FWS_op}"${CFWS_op})`;
// local-part as specified in Section 3.4.1 of RFC 5322
// Note: obs-local-part is not included, so this pattern matches less then specified!
const local_part_p = `(?:${dot_atom_p}|${quoted_string_p})`;
// token as specified in Section 5.1 of RFC 2045.
const token_p = "[^ \\x00-\\x1F\\x7F()<>@,;:\\\\\"/[\\]?=]+";
// "value" as specified in Section 5.1 of RFC 2045.
const value_cp = `(?:(${token_p})|${quoted_string_cp})`;
// domain-name as specified in Section 3.5 of RFC 6376 [DKIM].
const domain_name_p = `(?:${sub_domain_p}(?:\\.${sub_domain_p})+)`;


/**
* @typedef {Object} ARHHeader
* @property {String} authserv_id
Expand Down Expand Up @@ -137,7 +80,7 @@ let ARHParser = {
parse: function _ARHParser_parse(authresHeader) {
// remove header name
authresHeader = authresHeader.replace(
new RegExp(`^Authentication-Results:${CFWS_op}`, "i"), "");
new RegExp(`^Authentication-Results:${rfcParser.get("CFWS_op")}`, "i"), "");
let authresHeaderRef = new RefString(authresHeader);

/** @type {ARHHeader} */
Expand All @@ -146,7 +89,7 @@ let ARHParser = {
let reg_match;

// get authserv-id and authres-version
reg_match = match(authresHeaderRef, `${value_cp}(?:${CFWS_p}([0-9]+)${CFWS_op})?`);
reg_match = match(authresHeaderRef, `${rfcParser.get("value_cp")}(?:${rfcParser.get("CFWS")}([0-9]+)${rfcParser.get("CFWS_op")})?`);
const authserv_id = reg_match[1] || reg_match[2];
if (!authserv_id) {
throw new DKIM_Error("Error matching the ARH authserv-id.");
Expand All @@ -159,7 +102,7 @@ let ARHParser = {
}

// check if message authentication was performed
reg_match = match_o(authresHeaderRef, `;${CFWS_op}?none`);
reg_match = match_o(authresHeaderRef, `;${rfcParser.get("CFWS_op")}?none`);
if (reg_match !== null) {
log.debug("no-result");
return res;
Expand Down Expand Up @@ -193,10 +136,10 @@ function parseResinfo(str) {
let res = {};

// get methodspec
const method_version_p = `${CFWS_op}/${CFWS_op}([0-9]+)`;
const method_p = `(${Keyword_p})(?:${method_version_p})?`;
const result_p = `=${CFWS_op}(${Keyword_p})`;
const methodspec_p = `;${CFWS_op}${method_p}${CFWS_op}${result_p}`;
const method_version_p = `${rfcParser.get("CFWS_op")}/${rfcParser.get("CFWS_op")}([0-9]+)`;
const method_p = `(${rfcParser.get("Keyword")})(?:${method_version_p})?`;
const result_p = `=${rfcParser.get("CFWS_op")}(${rfcParser.get("Keyword")})`;
const methodspec_p = `;${rfcParser.get("CFWS_op")}${method_p}${rfcParser.get("CFWS_op")}${result_p}`;
try {
reg_match = match(str, methodspec_p);
} catch (exception) {
Expand Down Expand Up @@ -227,21 +170,21 @@ function parseResinfo(str) {
checkResultKeyword(res.method, reg_match[3]);

// get reasonspec (optional)
const reasonspec_p = `reason${CFWS_op}=${CFWS_op}${value_cp}`;
const reasonspec_p = `reason${rfcParser.get("CFWS_op")}=${rfcParser.get("CFWS_op")}${rfcParser.get("value_cp")}`;
reg_match = match_o(str, reasonspec_p);
if (reg_match !== null) {
res.reason = reg_match[1] || reg_match[2];
}

// get propspec (optional)
let pvalue_p = `${value_cp}|((?:${local_part_p}?@)?${domain_name_p})`;
let pvalue_p = `${rfcParser.get("value_cp")}|((?:${rfcParser.get("local_part")}?@)?${rfcParser.get("domain_name")})`;
if (prefs.getBoolPref("relaxedParsing")) {
// allow "/" and ":" in properties, even if it is not in a quoted-string
pvalue_p += "|([^ \\x00-\\x1F\\x7F()<>@,;\\\\\"[\\]?=]+)";
}
const special_smtp_verb_p = "mailfrom|rcptto";
const property_p = `${special_smtp_verb_p}|${Keyword_p}`;
const propspec_p = `(${Keyword_p})${CFWS_op}\\.${CFWS_op}(${property_p})${CFWS_op}=${CFWS_op}(?:${pvalue_p})`;
const property_p = `${special_smtp_verb_p}|${rfcParser.get("Keyword")}`;
const propspec_p = `(${rfcParser.get("Keyword")})${rfcParser.get("CFWS_op")}\\.${rfcParser.get("CFWS_op")}(${property_p})${rfcParser.get("CFWS_op")}=${rfcParser.get("CFWS_op")}(?:${pvalue_p})`;
res.propertys = {};
res.propertys.smtp = {};
res.propertys.header = {};
Expand Down Expand Up @@ -368,7 +311,7 @@ function match(str, pattern) {
* an Array, containing the matches
*/
function match_o(str, pattern) {
const regexp = new RegExp(`^${CFWS_op}(?:${pattern})(?:(?:${CFWS_op}\r\n$)|(?=;)|(?=${CFWS_p}))`);
const regexp = new RegExp(`^${rfcParser.get("CFWS_op")}(?:${pattern})(?:(?:${rfcParser.get("CFWS_op")}\r\n$)|(?=;)|(?=${rfcParser.get("CFWS")}))`);
const reg_match = str.match(regexp);
if (reg_match === null || !reg_match[0]) {
return null;
Expand Down
12 changes: 3 additions & 9 deletions modules/bimi.jsm.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

// options for ESLint
/* global Components */
/* global Logging */
/* global Logging, rfcParser */
/* exported EXPORTED_SYMBOLS, BIMI */

"use strict";
Expand All @@ -32,18 +32,12 @@ const Cu = Components.utils;

Cu.import("resource://dkim_verifier/logging.jsm.js");
Cu.import("resource://dkim_verifier/ARHParser.jsm.js");
Cu.import("resource://dkim_verifier/rfcParser.jsm.js");

let BIMI = (function() {

const log = Logging.getLogger("BIMI");

// WSP as specified in Appendix B.1 of RFC 5234
const WSP_p = "[ \t]";
// obs-FWS as specified in Section 4.2 of RFC 5322
const obs_FWS_p = `(?:${WSP_p}+(?:\r\n${WSP_p}+)*)`;
// FWS as specified in Section 3.2.2 of RFC 5322
const FWS_p = `(?:(?:(?:${WSP_p}*\r\n)?${WSP_p}+)|${obs_FWS_p})`;

let that = {
/**
* Try to get the BIMI Indicator if available.
Expand Down Expand Up @@ -87,7 +81,7 @@ let BIMI = (function() {
// Remove header name and new line at end
bimiIndicator = bimiIndicator.slice("bimi-indicator:".length, -"\r\n".length);
// Remove all whitespace
bimiIndicator = bimiIndicator.replace(new RegExp(`${FWS_p}`, "g"), "");
bimiIndicator = bimiIndicator.replace(new RegExp(`${rfcParser.get("FWS")}`, "g"), "");

return bimiIndicator;
}
Expand Down
28 changes: 10 additions & 18 deletions modules/dkimDMARC.jsm.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@

// options for ESLint
/* eslint strict: ["warn", "function"] */
/* global Components, Services, XPCOMUtils */
/* global Logging, Verifier, DNS */
/* global Components, Services */
/* global Logging, DNS, rfcParser */
/* global getBaseDomainFromAddr, getDomainFromAddr, toType, DKIM_TempError, DKIM_Error */
/* exported EXPORTED_SYMBOLS, DMARC */

Expand All @@ -34,19 +34,11 @@ var EXPORTED_SYMBOLS = [
const Cu = Components.utils;

Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");

Cu.import("resource://dkim_verifier/logging.jsm.js");
Cu.import("resource://dkim_verifier/helper.jsm.js");
Cu.import("resource://dkim_verifier/DNSWrapper.jsm.js");

XPCOMUtils.defineLazyModuleGetter(
this,
"Verifier",
"resource://dkim_verifier/dkimVerifier.jsm.js"
);


Cu.import("resource://dkim_verifier/rfcParser.jsm.js");

/**
* @public
Expand Down Expand Up @@ -316,14 +308,14 @@ function parseDMARCRecord(DMARCRecordStr) {
};

// parse tag-value list
let parsedTagMap = Verifier.parseTagValueList(DMARCRecordStr);
let parsedTagMap = rfcParser.parseTagValueList(DMARCRecordStr);
if (parsedTagMap === -1) {
throw new DKIM_Error("DKIM_DMARCERROR_ILLFORMED_TAGSPEC");
} else if (parsedTagMap === -2) {
throw new DKIM_Error("DKIM_DMARCERROR_DUPLICATE_TAG");
}
if (!(toType(parsedTagMap) === "Map")) {
throw new DKIM_Error(`unexpected return value from Verifier.parseTagValueList: ${parsedTagMap}`);
throw new DKIM_Error(`unexpected return value from rfcParser.parseTagValueList: ${parsedTagMap}`);
}
/** @type {Map} */
// @ts-ignore
Expand All @@ -334,7 +326,7 @@ function parseDMARCRecord(DMARCRecordStr) {
// of this tag MUST match precisely; if it does not or it is absent,
// the entire retrieved record MUST be ignored. It MUST be the first
// tag in the list.
let versionTag = Verifier.parseTagValue(tagMap, "v", "DMARC1", 3);
let versionTag = rfcParser.parseTagValue(tagMap, "v", "DMARC1", 3);
if (versionTag === null) {
throw new DKIM_Error("DKIM_DMARCERROR_MISSING_V");
} else {
Expand All @@ -344,7 +336,7 @@ function parseDMARCRecord(DMARCRecordStr) {
// adkim: (plain-text; OPTIONAL, default is "r".) Indicates whether
// strict or relaxed DKIM identifier alignment mode is required by
// the Domain Owner.
let adkimTag = Verifier.parseTagValue(tagMap, "adkim", "[rs]", 3);
let adkimTag = rfcParser.parseTagValue(tagMap, "adkim", "[rs]", 3);
if (adkimTag === null || versionTag[0] === "DMARC1") {
dmarcRecord.adkim = "r";
} else {
Expand All @@ -369,7 +361,7 @@ function parseDMARCRecord(DMARCRecordStr) {
// email that fails the DMARC mechanism check. Rejection SHOULD
// occur during the SMTP transaction. See Section 15.4 for some
// discussion of SMTP rejection methods and their implications.
let pTag = Verifier.parseTagValue(tagMap, "p", "(?:none|quarantine|reject)", 3);
let pTag = rfcParser.parseTagValue(tagMap, "p", "(?:none|quarantine|reject)", 3);
if (pTag === null) {
throw new DKIM_Error("DKIM_DMARCERROR_MISSING_P");
} else {
Expand All @@ -392,7 +384,7 @@ function parseDMARCRecord(DMARCRecordStr) {
// selected = true
// else
// selected = false
let pctTag = Verifier.parseTagValue(tagMap, "pct", "[0-9]{1,3}", 3);
let pctTag = rfcParser.parseTagValue(tagMap, "pct", "[0-9]{1,3}", 3);
if (pctTag === null) {
dmarcRecord.pct = 100;
} else {
Expand All @@ -411,7 +403,7 @@ function parseDMARCRecord(DMARCRecordStr) {
// Note that "sp" will be ignored for DMARC records published on sub-
// domains of Organizational Domains due to the effect of the DMARC
// Policy Discovery mechanism described in Section 8.
let spTag = Verifier.parseTagValue(tagMap, "sp", "(?:none|quarantine|reject)", 3);
let spTag = rfcParser.parseTagValue(tagMap, "sp", "(?:none|quarantine|reject)", 3);
if (spTag !== null) {
dmarcRecord.sp = spTag[0];
}
Expand Down
Loading

0 comments on commit a010e90

Please sign in to comment.