stefan.tollkuehn 2b3e96e50a Reject normalized datetime-local inputs
createFromFormat() only returns false on hard parse failures.
Impossible dates such as 2026-02-31 were silently normalized
into March, so a confirmed event could land on a different day
than the booking link supplied. Non-padded values like
2026-2-3T10:00 were also accepted and reformatted.

Parse with a leading "!" so no current-date fields leak in,
require zero warnings and errors from getLastErrors(), and
round-trip the value through the format. Impossible dates,
out-of-range components and non-padded values now throw in
both the confirmation and the creation stage.
2026-10-26 13:39:07 +01:00
2026-10-07 21:57:34 +02:00
2026-10-08 14:09:12 +02:00
2026-10-08 14:09:12 +02:00
2026-10-08 14:13:27 +02:00
2026-10-08 14:09:12 +02:00

AToCal — Add To Calendar

A Nextcloud app that lets remote applications create events in the authenticated user's Nextcloud Calendar via a simple link.

How it works

remote app                  Nextcloud (atocal)
    |                              |
    |  GET /apps/atocal/confirm    |
    |  summary, start, end, ...    |
    |----------------------------->|
    |                              |  confirm page
    |<-----------------------------|
    |                              |
    |  POST /apps/atocal/create    |  (CSRF token from form)
    |----------------------------->|
    |                              |  event in "Personal" calendar
    |<-----------------------------|  redirect to Calendar app

The remote app links the user to the confirm page. The user reviews the event and submits the form. The event lands in the user's "Personal" calendar and the browser opens the Calendar app.

Routes

Method Path Purpose
GET /apps/atocal/confirm Show confirmation page
POST /apps/atocal/create Create the event

Link parameters (GET /confirm and form POST /create)

Parameter Required Rules
summary yes max 255 chars
start yes datetime-local, e.g. 2026-10-07T14:15
end yes after start, same format
description no max 10000 chars
location no HTTPS URL
url no HTTPS URL; merged into description
organizer no email address; display info only

Dates carry no timezone and are interpreted in the user's Nextcloud timezone (server default as fallback).

Organizer

The event's ICS ORGANIZER is the Nextcloud user's own email address. Invitations to attendees are scheduled by the CalDAV backend in the calendar owner's name, which only works when the organizer matches the owner.

The organizer link parameter is shown on the confirm page as meeting information and is used as ORGANIZER fallback only when the user has no profile email — in that case no working invitations may be sent, so profile emails should be set.

Reminder

Every created event gets a display alarm 15 minutes before it starts (TRIGGER:-PT15M VALARM). The reminder is not configurable.

Example:

https://cloud.example.com/apps/atocal/confirm?summary=Kickoff&start=2026-10-12T10:00&end=2026-10-12T11:00&location=https%3A%2F%2Fmeet.example.com%2Fkickoff

Requirements

  • Nextcloud 34 or 35
  • Calendar app enabled
  • A writable calendar named "Personal" (event creation fails with a friendly error otherwise)

Install

Copy this directory to the Nextcloud server as apps/atocal, then:

occ app:enable atocal

Structure

appinfo/info.xml          app metadata
appinfo/routes.php        routes
lib/AppInfo/Application.php   container setup
lib/Controller/CalendarController.php   confirm/create logic
templates/confirm.php    confirmation page
templates/style.css       page styles
S
Description
AToCal is a Nextcloud app to create calendar events from a GET request. It emails attendees, books the slot as an event with organizer details, and lets invitees confirm or decline online
Readme AGPL-3.0
388 KiB
0 Stars 1 Watchers 0 Forks
Languages
PHP 83.6%
JavaScript 10.2%
CSS 6.2%