Bug 1793415 - Catch and report errors parsing dates from vCards. r=mkmelin
The parsing may fail but that shouldn't break things. Changes to test_vCard.js are mostly reinstating a test I should not have removed (in https://hg.mozilla.org/comm-central/diff/7b22f4a4287431034851651aa94fa6c88717e235/mailnews/addrbook/test/unit/test_vCard.js) with some additional cases in the birthday section. Differential Revision: https://phabricator.services.mozilla.com/D158539 --HG-- extra : rebase_source : d2e00b8653b33e23a7bc4803935bc9a14ffca26b extra : amend_source : 3df743fc84663fc60d8e267169e044b9bbbd8591
This commit is contained in:
Родитель
cc353b7222
Коммит
a3a6fc5d5d
|
@ -3032,7 +3032,12 @@ var detailsPane = {
|
|||
list.replaceChildren();
|
||||
|
||||
let formatDate = function(date) {
|
||||
date = ICAL.VCardTime.fromDateAndOrTimeString(date);
|
||||
try {
|
||||
date = ICAL.VCardTime.fromDateAndOrTimeString(date);
|
||||
} catch (ex) {
|
||||
Cu.reportError(ex);
|
||||
return "";
|
||||
}
|
||||
if (date.year && date.month && date.day) {
|
||||
return new Services.intl.DateTimeFormat(
|
||||
Services.locale.appLocalesAsBCP47,
|
||||
|
|
|
@ -135,15 +135,20 @@ class VCardSpecialDateComponent extends HTMLElement {
|
|||
return;
|
||||
}
|
||||
// Default value is date-and-or-time.
|
||||
let dateValue = ICAL.VCardTime.fromDateAndOrTimeString(
|
||||
this.vCardPropertyEntry.value || "",
|
||||
"date-and-or-time"
|
||||
);
|
||||
let dateValue;
|
||||
try {
|
||||
dateValue = ICAL.VCardTime.fromDateAndOrTimeString(
|
||||
this.vCardPropertyEntry.value || "",
|
||||
"date-and-or-time"
|
||||
);
|
||||
} catch (ex) {
|
||||
Cu.reportError(ex);
|
||||
}
|
||||
// Always set the month first since that controls the available days.
|
||||
this.month.value = dateValue.month || "";
|
||||
this.month.value = dateValue?.month || "";
|
||||
this.fillDayOptions();
|
||||
this.day.value = dateValue.day || "";
|
||||
this.year.value = dateValue.year || "";
|
||||
this.day.value = dateValue?.day || "";
|
||||
this.year.value = dateValue?.year || "";
|
||||
}
|
||||
|
||||
fromUIToVCardPropertyEntry() {
|
||||
|
|
|
@ -403,10 +403,14 @@ function dateProperty(abCardPrefix, vPropName) {
|
|||
yield [vPropName, {}, "date", dateValue.toString()];
|
||||
},
|
||||
*toAbCard(value) {
|
||||
let dateValue = ICAL.VCardTime.fromDateAndOrTimeString(value);
|
||||
yield [`${abCardPrefix}Year`, String(dateValue.year)];
|
||||
yield [`${abCardPrefix}Month`, String(dateValue.month)];
|
||||
yield [`${abCardPrefix}Day`, String(dateValue.day)];
|
||||
try {
|
||||
let dateValue = ICAL.VCardTime.fromDateAndOrTimeString(value);
|
||||
yield [`${abCardPrefix}Year`, String(dateValue.year ?? "")];
|
||||
yield [`${abCardPrefix}Month`, String(dateValue.month ?? "")];
|
||||
yield [`${abCardPrefix}Day`, String(dateValue.day ?? "")];
|
||||
} catch (ex) {
|
||||
Cu.reportError(ex);
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
@ -2,10 +2,294 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
let { VCardUtils } = ChromeUtils.import("resource:///modules/VCardUtils.jsm");
|
||||
let { VCardProperties, VCardUtils } = ChromeUtils.import(
|
||||
"resource:///modules/VCardUtils.jsm"
|
||||
);
|
||||
|
||||
const ANY_UID = "UID:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
|
||||
|
||||
add_task(function testVCardToPropertyMap() {
|
||||
function check(vCardLine, expectedProps) {
|
||||
let vCard = `BEGIN:VCARD\r\n${vCardLine}\r\nEND:VCARD\r\n`;
|
||||
info(vCard);
|
||||
let properties = VCardProperties.fromVCard(vCard).toPropertyMap();
|
||||
// Check that every property in expectedProps is present in `properties`.
|
||||
// No other property can be present unless it is in `propWhitelist`.
|
||||
for (let [name, value] of properties) {
|
||||
if (name in expectedProps) {
|
||||
Assert.equal(value, expectedProps[name], `expected ${name}`);
|
||||
delete expectedProps[name];
|
||||
} else {
|
||||
Assert.ok(false, `card should not have property '${name}'`);
|
||||
}
|
||||
}
|
||||
|
||||
for (let name of Object.keys(expectedProps)) {
|
||||
Assert.ok(false, `expected ${name} not found`);
|
||||
}
|
||||
}
|
||||
|
||||
// Name
|
||||
check("N:Last;First", { FirstName: "First", LastName: "Last" });
|
||||
check("N:Last;First;;;", { FirstName: "First", LastName: "Last" });
|
||||
check("N:Last;First;Middle;Prefix;Suffix", {
|
||||
FirstName: "First",
|
||||
LastName: "Last",
|
||||
AdditionalNames: "Middle",
|
||||
NamePrefix: "Prefix",
|
||||
NameSuffix: "Suffix",
|
||||
});
|
||||
check("N:Stevenson;John;Philip,Paul;Dr.;Jr.,M.D.,A.C.P.", {
|
||||
FirstName: "John",
|
||||
LastName: "Stevenson",
|
||||
AdditionalNames: "Philip Paul",
|
||||
NamePrefix: "Dr.",
|
||||
NameSuffix: "Jr. M.D. A.C.P.",
|
||||
});
|
||||
|
||||
// Address
|
||||
check(
|
||||
"ADR:PO Box 3.14;Apartment 4;123 Main Street;Any Town;CA;91921-1234;U.S.A.",
|
||||
{
|
||||
WorkPOBox: "PO Box 3.14",
|
||||
WorkAddress2: "Apartment 4",
|
||||
WorkAddress: "123 Main Street",
|
||||
WorkCity: "Any Town",
|
||||
WorkState: "CA",
|
||||
WorkZipCode: "91921-1234",
|
||||
WorkCountry: "U.S.A.",
|
||||
}
|
||||
);
|
||||
check(
|
||||
"ADR;TYPE=work:PO Box 3.14;Apartment 4;123 Main Street;Any Town;CA;91921-1234;U.S.A.",
|
||||
{
|
||||
WorkPOBox: "PO Box 3.14",
|
||||
WorkAddress2: "Apartment 4",
|
||||
WorkAddress: "123 Main Street",
|
||||
WorkCity: "Any Town",
|
||||
WorkState: "CA",
|
||||
WorkZipCode: "91921-1234",
|
||||
WorkCountry: "U.S.A.",
|
||||
}
|
||||
);
|
||||
check(
|
||||
"ADR;TYPE=home:PO Box 3.14;Apartment 4;123 Main Street;Any Town;CA;91921-1234;U.S.A.",
|
||||
{
|
||||
HomePOBox: "PO Box 3.14",
|
||||
HomeAddress2: "Apartment 4",
|
||||
HomeAddress: "123 Main Street",
|
||||
HomeCity: "Any Town",
|
||||
HomeState: "CA",
|
||||
HomeZipCode: "91921-1234",
|
||||
HomeCountry: "U.S.A.",
|
||||
}
|
||||
);
|
||||
|
||||
// Phone
|
||||
check("TEL:11-2358-13-21", { WorkPhone: "11-2358-13-21" });
|
||||
check("TEL;TYPE=work:11-2358-13-21", { WorkPhone: "11-2358-13-21" });
|
||||
check("TEL;TYPE=home:11-2358-13-21", { HomePhone: "11-2358-13-21" });
|
||||
check("TEL;TYPE=cell:11-2358-13-21", { CellularNumber: "11-2358-13-21" });
|
||||
check("TEL;TYPE=pager:11-2358-13-21", { PagerNumber: "11-2358-13-21" });
|
||||
check("TEL;TYPE=fax:11-2358-13-21", { FaxNumber: "11-2358-13-21" });
|
||||
|
||||
check("TEL;TYPE=work;PREF:11-2358-13-21", { WorkPhone: "11-2358-13-21" });
|
||||
check("TEL;TYPE=work,cell:11-2358-13-21", { WorkPhone: "11-2358-13-21" });
|
||||
check("TEL;TYPE=work;TYPE=cell:11-2358-13-21", {
|
||||
WorkPhone: "11-2358-13-21",
|
||||
});
|
||||
check("TEL;TYPE=work;VALUE=TEXT:11-2358-13-21", {
|
||||
WorkPhone: "11-2358-13-21",
|
||||
});
|
||||
check("TEL;TYPE=home;VALUE=TEXT:011-2358-13-21", {
|
||||
HomePhone: "011-2358-13-21",
|
||||
});
|
||||
check(
|
||||
"TEL;TYPE=work;VALUE=TEXT:11-2358-13-21\r\nTEL;TYPE=home;VALUE=TEXT:011-2358-13-21",
|
||||
{
|
||||
WorkPhone: "11-2358-13-21",
|
||||
HomePhone: "011-2358-13-21",
|
||||
}
|
||||
);
|
||||
check("TEL;TYPE=cell:11-2358-13-21\r\nTEL;TYPE=cell:011-2358-13-21", {
|
||||
CellularNumber: "11-2358-13-21",
|
||||
});
|
||||
check("TEL;TYPE=cell;PREF=1:11-2358-13-21\r\nTEL;TYPE=cell:011-2358-13-21", {
|
||||
CellularNumber: "11-2358-13-21",
|
||||
});
|
||||
check("TEL;TYPE=cell:11-2358-13-21\r\nTEL;TYPE=cell;PREF=1:011-2358-13-21", {
|
||||
CellularNumber: "011-2358-13-21",
|
||||
});
|
||||
|
||||
// Birthday
|
||||
check("BDAY;VALUE=DATE:19830403", {
|
||||
BirthDay: "3",
|
||||
BirthMonth: "4",
|
||||
BirthYear: "1983",
|
||||
});
|
||||
check("BDAY:--0415", { BirthDay: "15", BirthMonth: "4" });
|
||||
check("BDAY:2001", { BirthYear: "2001" });
|
||||
check("BDAY:2006-06", { BirthYear: "2006", BirthMonth: "6" });
|
||||
check("BDAY:--12", { BirthMonth: "12" });
|
||||
check("BDAY:---30", { BirthDay: "30" });
|
||||
// These are error cases, testing that it doesn't throw.
|
||||
check("BDAY;VALUE=DATE:NaN-NaN-NaN", {});
|
||||
check("BDAY;VALUE=TEXT:07/07/1949", {});
|
||||
|
||||
// Anniversary
|
||||
check("ANNIVERSARY;VALUE=DATE:20041207", {
|
||||
AnniversaryDay: "7",
|
||||
AnniversaryMonth: "12",
|
||||
AnniversaryYear: "2004",
|
||||
});
|
||||
|
||||
// Organization: any number of values is valid here.
|
||||
check("ORG:Acme Widgets, Inc.", {
|
||||
Company: "Acme Widgets, Inc.",
|
||||
});
|
||||
check("ORG:Acme Widgets, Inc.;Manufacturing", {
|
||||
Company: "Acme Widgets, Inc.",
|
||||
Department: "Manufacturing",
|
||||
});
|
||||
check("ORG:Acme Widgets, Inc.;Manufacturing;Thingamies", {
|
||||
Company: "Acme Widgets, Inc.",
|
||||
Department: "Manufacturing",
|
||||
});
|
||||
|
||||
// URL
|
||||
// If no type is given assume its WebPage1 (work).
|
||||
check("URL:https://www.thunderbird.net/", {
|
||||
WebPage1: "https://www.thunderbird.net/",
|
||||
});
|
||||
|
||||
check("URL;TYPE=work:https://developer.thunderbird.net/", {
|
||||
WebPage1: "https://developer.thunderbird.net/",
|
||||
});
|
||||
|
||||
check("URL;TYPE=home:https://addons.thunderbird.net/", {
|
||||
WebPage2: "https://addons.thunderbird.net/",
|
||||
});
|
||||
|
||||
check(
|
||||
formatVCard`
|
||||
URL;TYPE=home:https://addons.thunderbird.net/
|
||||
URL;TYPE=work:https://developer.thunderbird.net/`,
|
||||
{
|
||||
WebPage1: "https://developer.thunderbird.net/",
|
||||
WebPage2: "https://addons.thunderbird.net/",
|
||||
}
|
||||
);
|
||||
|
||||
// If a URL without a type is given and a Work Web Page do not import the URL without type.
|
||||
check(
|
||||
formatVCard`
|
||||
URL:https://www.thunderbird.net/
|
||||
URL;TYPE=home:https://addons.thunderbird.net/
|
||||
URL;TYPE=work:https://developer.thunderbird.net/`,
|
||||
{
|
||||
WebPage1: "https://developer.thunderbird.net/",
|
||||
WebPage2: "https://addons.thunderbird.net/",
|
||||
}
|
||||
);
|
||||
// Email: just to be difficult, email is stored by priority, not type.
|
||||
check("EMAIL:first@invalid", { PrimaryEmail: "first@invalid" });
|
||||
check("EMAIL;PREF=1:first@invalid", { PrimaryEmail: "first@invalid" });
|
||||
|
||||
check("EMAIL;PREF=1:first@invalid\r\nEMAIL:second@invalid", {
|
||||
PrimaryEmail: "first@invalid",
|
||||
SecondEmail: "second@invalid",
|
||||
});
|
||||
check("EMAIL:second@invalid\r\nEMAIL;PREF=1:first@invalid", {
|
||||
PrimaryEmail: "first@invalid",
|
||||
SecondEmail: "second@invalid",
|
||||
});
|
||||
|
||||
check("EMAIL;PREF=1:first@invalid\r\nEMAIL;PREF=2:second@invalid", {
|
||||
PrimaryEmail: "first@invalid",
|
||||
SecondEmail: "second@invalid",
|
||||
});
|
||||
check("EMAIL;PREF=2:second@invalid\r\nEMAIL;PREF=1:first@invalid", {
|
||||
PrimaryEmail: "first@invalid",
|
||||
SecondEmail: "second@invalid",
|
||||
});
|
||||
|
||||
check(
|
||||
"EMAIL;PREF=1:first@invalid\r\nEMAIL;PREF=2:second@invalid\r\nEMAIL;PREF=3:third@invalid",
|
||||
{
|
||||
PrimaryEmail: "first@invalid",
|
||||
SecondEmail: "second@invalid",
|
||||
}
|
||||
);
|
||||
check(
|
||||
"EMAIL;PREF=2:second@invalid\r\nEMAIL;PREF=3:third@invalid\r\nEMAIL;PREF=1:first@invalid",
|
||||
{
|
||||
PrimaryEmail: "first@invalid",
|
||||
SecondEmail: "second@invalid",
|
||||
}
|
||||
);
|
||||
check(
|
||||
"EMAIL;PREF=3:third@invalid\r\nEMAIL;PREF=1:first@invalid\r\nEMAIL;PREF=2:second@invalid",
|
||||
{
|
||||
PrimaryEmail: "first@invalid",
|
||||
SecondEmail: "second@invalid",
|
||||
}
|
||||
);
|
||||
check(
|
||||
"EMAIL;PREF=3:third@invalid\r\nEMAIL;PREF=2:second@invalid\r\nEMAIL;PREF=1:first@invalid",
|
||||
{
|
||||
PrimaryEmail: "first@invalid",
|
||||
SecondEmail: "second@invalid",
|
||||
}
|
||||
);
|
||||
check(
|
||||
"EMAIL;PREF=2:second@invalid\r\nEMAIL;PREF=1:first@invalid\r\nEMAIL;PREF=3:third@invalid",
|
||||
{
|
||||
PrimaryEmail: "first@invalid",
|
||||
SecondEmail: "second@invalid",
|
||||
}
|
||||
);
|
||||
check(
|
||||
"EMAIL;PREF=1:first@invalid\r\nEMAIL;PREF=3:third@invalid\r\nEMAIL;PREF=2:second@invalid",
|
||||
{
|
||||
PrimaryEmail: "first@invalid",
|
||||
SecondEmail: "second@invalid",
|
||||
}
|
||||
);
|
||||
|
||||
// Group-prefixed properties.
|
||||
check(
|
||||
formatVCard`
|
||||
item1.EMAIL:first@invalid
|
||||
item1.X-ABLabel:First`,
|
||||
{
|
||||
PrimaryEmail: "first@invalid",
|
||||
}
|
||||
);
|
||||
check(
|
||||
formatVCard`
|
||||
item1.EMAIL:first@invalid
|
||||
item1.X-ABLabel:First
|
||||
item2.EMAIL:second@invalid
|
||||
item2.X-ABLabel:Second`,
|
||||
{ PrimaryEmail: "first@invalid", SecondEmail: "second@invalid" }
|
||||
);
|
||||
check(
|
||||
formatVCard`
|
||||
foo-bar.EMAIL:first@invalid
|
||||
foo-bar.X-ABLabel:First
|
||||
EMAIL:second@invalid`,
|
||||
{ PrimaryEmail: "first@invalid", SecondEmail: "second@invalid" }
|
||||
);
|
||||
check(
|
||||
formatVCard`
|
||||
EMAIL:first@invalid
|
||||
abc.EMAIL:second@invalid
|
||||
abc.X-ABLabel:Second`,
|
||||
{ PrimaryEmail: "first@invalid", SecondEmail: "second@invalid" }
|
||||
);
|
||||
check("xyz.TEL:11-2358-13-21", { WorkPhone: "11-2358-13-21" });
|
||||
});
|
||||
|
||||
add_task(function testAbCardToVCard() {
|
||||
function check(abCardProps, ...expectedLines) {
|
||||
let abCard = Cc["@mozilla.org/addressbook/cardproperty;1"].createInstance(
|
||||
|
|
Загрузка…
Ссылка в новой задаче