Bug 1906077 - ICS calendar subscriptions should use the original URI for temporary redirects. r=aleca
To test, subscribe to https://github.com/othyn/go-calendar/releases/latest/download/gocal__community_day.ics Also * don't fail for cases there content-type is null * accept for content-type=application/octet-stream where the Content-Disposition says it's an .ics Differential Revision: https://phabricator.services.mozilla.com/D220872 --HG-- extra : rebase_source : a3e7e2cc8f56bdf7e7968b1a2863bbfa8002b9a2 extra : absorb_source : 3e9d607dfd459e5ad8f87348838f9667711f8cd8
This commit is contained in:
Родитель
885e42ebd1
Коммит
03004531ab
|
@ -98,7 +98,7 @@ export var detection = {
|
||||||
* @param {ProviderFilter[]} aPreDetectFilters - Functions for filtering out providers.
|
* @param {ProviderFilter[]} aPreDetectFilters - Functions for filtering out providers.
|
||||||
* @param {object} aExtraProperties - Extra properties to pass on to the
|
* @param {object} aExtraProperties - Extra properties to pass on to the
|
||||||
* providers.
|
* providers.
|
||||||
* @returns {Promise<Map<string,calICalendar[]>>} a Map of provider type to calendars found.
|
* @returns {Promise<Map<calICalendarProvider,calICalendar[]>>} a Map of provider type to calendars found.
|
||||||
*/
|
*/
|
||||||
async detect(
|
async detect(
|
||||||
aUsername,
|
aUsername,
|
||||||
|
|
|
@ -99,8 +99,6 @@ CalDavCalendar.prototype = {
|
||||||
return this != this.superCalendar;
|
return this != this.superCalendar;
|
||||||
},
|
},
|
||||||
|
|
||||||
mLastRedirectStatus: null,
|
|
||||||
|
|
||||||
ensureTargetCalendar() {
|
ensureTargetCalendar() {
|
||||||
if (!this.isCached && !this.mOfflineStorage) {
|
if (!this.isCached && !this.mOfflineStorage) {
|
||||||
// If this is a cached calendar, the actual cache is taken care of
|
// If this is a cached calendar, the actual cache is taken care of
|
||||||
|
|
|
@ -307,7 +307,7 @@ class CalDavDetector {
|
||||||
|
|
||||||
// `request.commit()` can throw; errors should be caught by calling functions.
|
// `request.commit()` can throw; errors should be caught by calling functions.
|
||||||
const response = await request.commit();
|
const response = await request.commit();
|
||||||
const homeSets = response.firstProps["C:calendar-home-set"];
|
const homeSets = response.firstProps ? response.firstProps["C:calendar-home-set"] : null;
|
||||||
const target = response.uri;
|
const target = response.uri;
|
||||||
|
|
||||||
if (response.authError) {
|
if (response.authError) {
|
||||||
|
|
|
@ -277,14 +277,19 @@ class ICSDetector {
|
||||||
|
|
||||||
// The content type header may include a charset, so use 'string.includes'.
|
// The content type header may include a charset, so use 'string.includes'.
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
const header = response.getHeader("Content-Type");
|
const contentType = response.getHeader("Content-Type");
|
||||||
|
const contentDisposition = response.getHeader("Content-Disposition");
|
||||||
if (
|
if (
|
||||||
header.includes("text/calendar") ||
|
contentType?.includes("text/calendar") ||
|
||||||
header.includes("application/ics") ||
|
contentType?.includes("application/ics") ||
|
||||||
|
/\.ics\b/i.test(contentDisposition) ||
|
||||||
(response.text && response.text.includes("BEGIN:VCALENDAR"))
|
(response.text && response.text.includes("BEGIN:VCALENDAR"))
|
||||||
) {
|
) {
|
||||||
const target = response.uri;
|
let target = response.uri;
|
||||||
|
// Set up calendar for original URI for temporal redirects.
|
||||||
|
if (response.lastRedirectStatus == 302 || response.lastRedirectStatus == 307) {
|
||||||
|
target = response.nsirequest.originalURI;
|
||||||
|
}
|
||||||
cal.LOG(`[calICSProvider] ${target.spec} has valid content type (via ${method} request)`);
|
cal.LOG(`[calICSProvider] ${target.spec} has valid content type (via ${method} request)`);
|
||||||
return [this.handleCalendar(target)];
|
return [this.handleCalendar(target)];
|
||||||
}
|
}
|
||||||
|
@ -410,8 +415,8 @@ class ICSDetector {
|
||||||
* Set up and return a new ICS calendar object.
|
* Set up and return a new ICS calendar object.
|
||||||
*
|
*
|
||||||
* @param {nsIURI} uri - The location of the calendar.
|
* @param {nsIURI} uri - The location of the calendar.
|
||||||
* @param {Set} [props] - For CalDav calendars, these are the props
|
* @param {Set} [props] - For CalDav calendars, these are the props parsed
|
||||||
* parsed from the response.
|
* from the response.
|
||||||
* @returns {calICalendar} A new calendar.
|
* @returns {calICalendar} A new calendar.
|
||||||
*/
|
*/
|
||||||
handleCalendar(uri, props = new Set()) {
|
handleCalendar(uri, props = new Set()) {
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, you can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
import { Assert } from "resource://testing-common/Assert.sys.mjs";
|
|
||||||
|
|
||||||
import { CommonUtils } from "resource://services-common/utils.sys.mjs";
|
import { CommonUtils } from "resource://services-common/utils.sys.mjs";
|
||||||
import { HttpServer } from "resource://testing-common/httpd.sys.mjs";
|
import { HttpServer } from "resource://testing-common/httpd.sys.mjs";
|
||||||
|
|
||||||
|
@ -21,6 +19,7 @@ export var ICSServer = {
|
||||||
this.username = username;
|
this.username = username;
|
||||||
this.password = password;
|
this.password = password;
|
||||||
this.server.registerPathHandler("/ping", this.ping);
|
this.server.registerPathHandler("/ping", this.ping);
|
||||||
|
this.server.registerPathHandler("/http302", this.http302);
|
||||||
this.server.registerPathHandler(this.path, this.handleICS.bind(this));
|
this.server.registerPathHandler(this.path, this.handleICS.bind(this));
|
||||||
|
|
||||||
this.reset();
|
this.reset();
|
||||||
|
@ -98,6 +97,15 @@ export var ICSServer = {
|
||||||
response.write("pong");
|
response.write("pong");
|
||||||
},
|
},
|
||||||
|
|
||||||
|
http302(request, response) {
|
||||||
|
const params = new URLSearchParams(request.queryString);
|
||||||
|
const path = params.get("path");
|
||||||
|
response.setStatusLine("1.1", 302, "Found");
|
||||||
|
response.setHeader("Location", `${ICSServer.origin}/${path}`);
|
||||||
|
response.setHeader("Content-Type", "text/plain; charset=UTF-8");
|
||||||
|
response.setHeader("Content-Length", "0");
|
||||||
|
},
|
||||||
|
|
||||||
handleICS(request, response) {
|
handleICS(request, response) {
|
||||||
if (!this.checkAuth(request, response)) {
|
if (!this.checkAuth(request, response)) {
|
||||||
return;
|
return;
|
||||||
|
@ -115,7 +123,6 @@ export var ICSServer = {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert.report(true, undefined, undefined, "Should not have reached here");
|
|
||||||
response.setStatusLine("1.1", 405, "Method Not Allowed");
|
response.setStatusLine("1.1", 405, "Method Not Allowed");
|
||||||
response.setHeader("Content-Type", "text/plain");
|
response.setHeader("Content-Type", "text/plain");
|
||||||
response.write(`Method not allowed: ${request.method}`);
|
response.write(`Method not allowed: ${request.method}`);
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* 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/. */
|
||||||
|
|
||||||
|
var { ICSServer } = ChromeUtils.importESModule(
|
||||||
|
"resource://testing-common/calendar/ICSServer.sys.mjs"
|
||||||
|
);
|
||||||
|
|
||||||
|
var { detection } = ChromeUtils.importESModule(
|
||||||
|
"resource:///modules/calendar/utils/calProviderDetectionUtils.sys.mjs"
|
||||||
|
);
|
||||||
|
|
||||||
|
add_setup(async () => {
|
||||||
|
ICSServer.open();
|
||||||
|
ICSServer.putICSInternal(
|
||||||
|
CalendarTestUtils.dedent`
|
||||||
|
BEGIN:VCALENDAR
|
||||||
|
BEGIN:VEVENT
|
||||||
|
UID:6714b781-920f-46f8-80ec-3d3995e2e9ce
|
||||||
|
SUMMARY:some event
|
||||||
|
DTSTART:20210401T120000Z
|
||||||
|
DTEND:20210401T130000Z
|
||||||
|
END:VEVENT
|
||||||
|
END:VCALENDAR
|
||||||
|
`
|
||||||
|
);
|
||||||
|
registerCleanupFunction(() => ICSServer.close());
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function testIcsDetection() {
|
||||||
|
const url = `${ICSServer.origin}/test.ics`;
|
||||||
|
const detectedCals = await detection.detect("", "", url, false, [], {});
|
||||||
|
Assert.ok(detectedCals, "should find calendars");
|
||||||
|
Assert.equal(detectedCals.size, 1, "should find one calendar");
|
||||||
|
const icsCal = detectedCals.values().next().value[0];
|
||||||
|
Assert.equal(icsCal.uri.spec, url, "should have expected uri");
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function testIcsDetection302() {
|
||||||
|
// This url will redirect to test.ics for the actual content.
|
||||||
|
// We still want to subscribe to the original url.
|
||||||
|
const url = `${ICSServer.origin}/http302?path=test.ics`;
|
||||||
|
const detectedCals = await detection.detect("", "", url, false, [], {});
|
||||||
|
Assert.ok(detectedCals, "should find calendars");
|
||||||
|
Assert.equal(detectedCals.size, 1, "should find one calendar");
|
||||||
|
const icsCal = detectedCals.values().next().value[0];
|
||||||
|
Assert.equal(icsCal.uri.spec, url, "should have expected uri");
|
||||||
|
});
|
|
@ -4,6 +4,7 @@ prefs =
|
||||||
calendar.timezone.local=UTC
|
calendar.timezone.local=UTC
|
||||||
calendar.timezone.useSystemTimezone=false
|
calendar.timezone.useSystemTimezone=false
|
||||||
|
|
||||||
|
[test_cal_detection.js]
|
||||||
[test_caldavCalendar_cached.js]
|
[test_caldavCalendar_cached.js]
|
||||||
[test_caldavCalendar_uncached.js]
|
[test_caldavCalendar_uncached.js]
|
||||||
[test_icsCalendar_cached.js]
|
[test_icsCalendar_cached.js]
|
||||||
|
|
Загрузка…
Ссылка в новой задаче