Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backport Feature: 5 -> 2.x internationalization support 2023-12-16 #418

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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