WebCalendar

About WebCalendar

WebCalendar is a PHP-based calendar application that can be configured as a single-user calendar, a multi-user calendar for groups of users, or as an event calendar viewable by visitors. MySQL/MariaDB, SQLite3, PostgreSQL, Oracle, DB2, Interbase, MS SQL Server, or ODBC is required. The version 1.9.X releases are still a little rough around the edges since these include an overhaul of the UI to use Bootstrap and jQuery and a complete rewrite of the web-based installer.

WebCalendar can be setup in a variety of ways, such as…

  • A schedule management system for a single person
  • A schedule management system for a group of people, allowing one or more assistants to manage the calendar of another user
  • An events schedule that anyone can view, allowing visitors to submit new events
  • A calendar server that can be viewed with iCalendar-compliant calendar applications like Mozilla Sunbird, Apple iCal or GNOME Evolution or RSS-enabled applications like Firefox, Thunderbird, RSSOwl, FeedDemon, or BlogExpress.

Overview of Features

  • Multi-user support
  • 30 supported languages: Basque, Bulgarian, Chinese-Big5, Chinese-GB2312, Czech, Danish, Dutch, English-US, Estonian, Finnish, French, Galician, German, Greek, Holo-Big5, Hungarian, Icelandic, Italian, Japanese, Korean, Norwegian, Polish, Portuguese_BR, Portuguese, Romanian, Russian, Spanish, Swedish, Turkish, Welsh (see current list of translations here)
  • Web-based installer
  • Auto-detect user’s language preference from browser settings
  • View calendars by day, week, month or year
  • View another user’s calendar
  • View one or more users’ calendar via layers on top of your own calendar
  • Add/Edit/Delete users
  • Add/Edit/Delete events
  • Repeating events including support for overriding or deleting (exceptions)
  • Configurable custom event fields
  • User-configurable preferences for colors, 12/24 time format, Sun/Mon week start
  • Checks for scheduling conflicts
  • Email reminders for upcoming events
  • Email notifications for new/updated/deleted events
  • Export events to iCalendar
  • Import from iCalendar/ics format
  • Optional general access (no login required) to allow calendar to be viewed by people without a login (useful for event calendars)
  • Users can make their calendar available publicly to anyone with an iCalendar-compliant calendar program (such as Apple’s iCal, Mozilla Calendar or Sunbird)
  • Publishing of free/busy schedules (part of the iCalendar standard)
  • RSS support that puts a user’s calendar into RSS
  • Subscribe to “remote” calendars (hosted elsewhere on the net) in either iCalendar or hCalendar formats (WebCalendar 1.1+)
  • User authentication: Web-based, HTTP, LDAP or NIS

System Requirements

  • PHP 8 or later
  • PHP support and access to one of the following databases:
    • SQLite
    • MySQL/MariaDB
    • Oracle
    • Postgres
    • IBM DB2
  • Access to cron for Linux/Unix systems (to send out reminders)

Development Cost

The following metrics from Ohloh show how much it would have cost to commercially develop WebCalendar.

  • Codebase Size: 138,588 lines
  • Estimated Effort: 34 person-years
  • Estimated Cost: $1,884,469
  • (As of 11 August 2024)

Donations

If you’d like to help support the costs of developing, maintaining and supporting WebCalendar, please consider donating.

Developer Resources

License

WebCalendar is available under the GNU General Public License, version 2.

For more information on this license:

Documentation

Most Recent Changes

Below are the most recent source code commits to github on the master branch.

  • Merge pull request #652 from craigk5n/fix/issue-642-wizard-missing-me…
    by craigk5n on June 21, 2026 at 2:03 am

    Merge pull request #652 from craigk5n/fix/issue-642-wizard-missing-methods fix(wizard): restore missing createAdminUser() and getUpgradeSqlCommands()

  • fix(wizard): restore createAdminUser() and getUpgradeSqlCommands()
    by craigk5n on June 21, 2026 at 1:54 am

    fix(wizard): restore createAdminUser() and getUpgradeSqlCommands() Commit 95c4e08 (“clean up wizard installer”) removed two WizardDatabase methods but left their callers in place, so the wizard fatals with “Call to undefined method” on PHP 8.x: – WizardDatabase::createAdminUser() — called by index.php (create-admin-user action) and headless.php. Hitting the admin-user step (e.g. a fresh env-var/Docker install adding an admin) returned HTTP 500 with an empty body, which the wizard JS reports as “Unexpected end of JSON input” (issue #642, reported by @sonntam). – WizardDatabase::getUpgradeSqlCommands() — called by index.php (get-upgrade-sql action) during the upgrade flow. Restore both. createAdminUser() is improved over the deleted version: – Stores the password with password_hash(PASSWORD_DEFAULT) to match the main app (includes/user.php) instead of md5(). – Selects the target database for mysqli, since the create-admin-user action only calls testConnection() (which does not select a DB) before this, so the INSERT would otherwise fail with “No database selected”. – Reports a specific error per backend instead of swallowing failures. Verified in a PHP 8.1 + MySQL 8.0 container: connect (no select_db) -> createAdminUser() creates an enabled admin row whose bcrypt hash passes password_verify().

  • Merge pull request #651 from craigk5n/fix/issue-642-wizard-mysqli-json
    by craigk5n on June 20, 2026 at 3:09 pm

    Merge pull request #651 from craigk5n/fix/issue-642-wizard-mysqli-json fix(wizard): prevent “Unexpected end of JSON input” on PHP 8.1+ installs

  • fix(wizard): prevent “Unexpected end of JSON input” on PHP 8.1+ installs
    by craigk5n on June 20, 2026 at 2:57 pm

    fix(wizard): prevent “Unexpected end of JSON input” on PHP 8.1+ installs The install wizard’s WizardDatabase class is written against legacy mysqli semantics: @-suppressed calls that check ->error/->connect_error and false returns. PHP 8.1+ defaults mysqli to MYSQLI_REPORT_ERROR|MYSQLI_REPORT_STRICT, making those calls throw mysqli_sql_exception instead. The @ operator does not suppress thrown exceptions, so an uncaught exception (e.g. select_db on a not-yet-created database) becomes a fatal error. With display_errors off and the output buffer cleaned, the AJAX response body is empty, which the wizard JS surfaces as “Unexpected end of JSON input” (issue #642). – WizardDatabase: disable mysqli exception throwing in the constructor (mysqli_report(MYSQLI_REPORT_OFF)), restoring the return-false contract the class assumes across all connect/select_db/query calls at once. – index.php: add a register_shutdown_function in the API POST handler that emits a valid JSON error if any future fatal escapes, so the user sees the real problem instead of an empty body. Reproduced and verified in a PHP 8.1.21 + MySQL 8.0 container: pre-fix the select_db-on-missing-db path threw an uncaught exception (empty body); with the fix it returns clean JSON and the wizard advances to the create-db step.

  • fix(tools): handle mixed latin1/UTF-8 data in charset converter
    by craigk5n on June 16, 2026 at 2:43 am

    fix(tools): handle mixed latin1/UTF-8 data in charset converter The latin1->utf8 converter (issue #626) assumed all non-ASCII bytes were UTF-8 wrongly stored in a latin1 column, and used a column-wide binary->utf8mb4 reinterpret. Databases upgraded over many years often hold a MIX: genuine latin1 bytes (e.g. “a-umlaut”=0xE4, “sharp-s”=0xDF) alongside double-encoded UTF-8 (0xC3A4) in the same column. Genuine latin1 bytes are not valid UTF-8, so the reinterpret step threw “Incorrect string value: \xE4…” and aborted (issue #649). Decide per value instead of per column (“fix-then-reinterpret”): 1. MODIFY column to a binary type (lossless) 2. per distinct value: keep if already valid UTF-8, else transcode latin1->UTF-8 3. MODIFY to utf8mb4 (all bytes now valid, never errors) 4. set table default charset Also: – mysqli_report(OFF) + per-column error handling so one bad column no longer aborts the run; failed columns keep raw bytes and are re-runnable – optional WEBCALENDAR_DB_* env overrides for container/test use – detection summary now counts ASCII / valid-UTF-8 / genuine-latin1 Add tests/test-latin1-conversion.sh: seeds MariaDB 10.5 with the exact failing values from #649 (plus double-encoded, ASCII, and a TEXT column), runs dry-run then conversion, and asserts the resulting bytes and charset.

Download Metrics

  • Downloads via Github: 20323
  • Downloads via SourceForge:

Related Links

  • Standards
    • RFC 2445: Internet Calendaring and Scheduling Core Object Specification (iCalendar)
    • CalDAV: Calendaring and Scheduling Extensions to WebDAV (DRAFT) 
      [Note: WebCalendar does not yet support CalDAV.)
  • Calendar client applications – You can use the applications to view events stored in WebCalendar if you enable its publishing settings.
  • iCalendar/ics download sites – These sites contain calendars for holidays, sports teams schedules, music converts, etc. You can import these files into WebCalendar.