WP Manifestindependent plugin directory
manifest / events / calendar-plus

Calendar+ (An Accessible Events Calendar) WP Registry grade D+. High-severity findings · 3 findingsWP RegistryHigh-severity findings · 3 findingsOpen the reportD+

Create, manage, and share your calendar and upcoming events.

★ 12stars
v2.2.15latest · 6mo ago

Install

Download source zip No release zip yet

This is the repository archive. It installs, but the folder name will carry the branch suffix and updates will not flow.

Install straight from GitHub with WP-CLI:

wp plugin install https://github.com/campuspress/calendar-plus/archive/refs/heads/master.zip
Updates itself. It ships its own updater (Plugin Update Checker), so new versions appear under Dashboard → Updates.

Calendar+ is a WordPress calendar and events plugin developed by the team at CampusPress.

Calendar+ is specifically developed to be friendly for visitors using screen-readers and other assistive technologies. Calendar owners can import events from iCal and Google Calendar feeds and choose from multiple display options.

Site visitors can easily add events to their own Google Calendar, Outlook, or download an ical file.

More info

Calendar Plus uses several technologies to generate the CSS/JS bundles:

  • React for the Calendar shortcode
  • Sass for styling
  • Webpack to minimize and generate JS
  • npm to run tasks

Calendar Plus is built on Webpack. It generates 4 bundles:

  • admin.js
  • settings.js
  • editor-shortcode.js
  • calendar-plus.css with Foundation styles

Getting started

  1. Install Node.js
  2. Run npm install in plugin root folder. All node dependencies will be downloaded to node_modules
  3. Run composer install to install Composer packages in vendor
  4. Run npm run build to generate the production CSS and JavaScript
  5. Run npm run gulp to update translation files

React Calendar

The front-end calendar is a combination of React + ES6 JS structure. Everything begins with _src/calendar/react-calendar/index.js

React Calendar will get a calendarPlusi18n object that is generated in includes/shortcodes/class-calendar-plus-calendar-shortcode.php which contains everything needed to render the calendar.

React Calendar uses the React Big Calendar component.

Watching files

You can run npm run watch:front to begin watching Calendar files.

The bundle

All React/ES6 scripts are bundled into public/js/calendar-plus.js

Admin Scripts

Watching files

Run npm run watch:admin to watch JS files. These are:

_src/admin/admin/admin.js

wp-admin scripts are written Backbone

admin.js will require every js file the collections, misc, models and views directories.

_src/admin/settings/settings.js

Scripts for the admin Events > Settings screen.

_src/admin/editor-shortcode/editor-shortcode.js

Scripts for the Calendar Plus button in the WordPress visual editor.

The bundle

Every script is minified and bundled in:

admin/js/admin.js admin/js/editor-shortcode.js admin/js/settings.js

Webpack will do everything for you.

Styles

Webpack will also transform Sass to CSS and will bundle them in .css files.

Watching files

Run npm run watch:public to watch Sass files. These are:

_src/public/calendar-plus.scss

The main styles for React Calendar

_src/public/calendar-plus-events-by-cat-shortcode.scss

Styles for the Events By Category Shortcode

The bundle

Every stylesheet is minified and bundled in:

public/css/calendar-plus.css public/css/calendar-plus-events-by-cat-shortcode.css

Webpack will do everything for you.

Some notes about the bundles

Webpack just understands JS but webpack.calendar-plus.js uses a plugin that will allow Webpack understand Sass too. The process is the following one:

  • Process Sass and transform to CSS
  • Get that CSS and add it to a .js file and use eval() to add those styles to your website
  • Thanks to extract-text-webpack-plugin in Webpack, the plugin will get the eval() contents and will place them in a .css file which is loaded by Calendar Plus.
  • The .js file will be still there but is useless. These files are:

public/css/calendar-plus.js public/css/calendar-plus-events-by-cat-shortcode.js

Right now, they are included in the commits but do not worry about them.

Watch all bundles

Just run npm run watch and all bundles will be watched at the same time.

Troubleshooting

On Windows platforms it may be necessary to run npm install --global --production windows-build-tools before installing node modules.

Releases

4 releases.

Tag
Published
v2.2.15 latest
Apr 1, 2026 6mo ago
Mar 13, 2025 1 year ago
Feb 28, 2023 3 years ago
May 13, 2020 6 years ago

These releases are tags only. The author does not attach a packaged zip, so there are no download counts to report.

D+ grade

Security

Calendar+ (An Accessible Events Calendar) 2.2.15 · audited by WP Registry

High-severity findings.

1 high 2 medium
Audited release
2.2.15
Findings
3
Worst severity
high
Content hash
2eb5980af1dd4d0c2eba5eae…

Findings

  • high Unauthenticated REST deletion of arbitrary event dates via inverted permission check

    auth_bypass

    DELETE /wp-json/calendar-plus/v1/events/{id}/dates/{date_id} is gated by edit_item_permissions_check. That helper only returns WP_Error when get_post($id) is truthy AND the user lacks edit_calendar_events or manage_calendar_plus. If the event ID does not exist (0, 999999999, a purged post), the if-body is skipped and the callback returns true for unauthenticated and Subscriber users. delete_item_date then calls calendarp_delete_event_cell(date_id) with no check that the cell belongs to {id}, so any wp_calendarp_calendar row can be removed. Date IDs are sequential integers; an unauth client can wipe the entire occurrence table (public calendar, widgets, iCal, archives) without a nonce. Cookie-authenticated low-priv users can do the same using the wp_rest nonce localized on the public calendar shortcode. PATCH uses a non-existent edit_item_date_permissions_check method (fatal/deny, not an additional bypass).

    includes/rest-api/endpoints/class-calendar-plus-rest-endpoints-event.php:109-205

    Recommendation

    Deny by default: if the event post is missing, return 404/forbidden. Require current_user_can('manage_calendar_plus') (and edit_post on that event) before any mutation. Bind date_id to the route event id inside delete_item_date and reject mismatches. Implement the missing edit_item_date_permissions_check with the same deny-by-default logic.

  • medium Unauthenticated REST disclosure of unpublished event occurrence rows

    information_disclosure

    GET /wp-json/calendar-plus/v1/events/{id}/dates uses get_items_permissions_check, which returns true for everyone unless context=edit. get_item_dates then returns calendar_plus()->generator->get_all_event_dates($id) with no current_user_can_read() / post_status check (unlike GET /events, which skips unreadable events). Guessable numeric IDs therefore leak from_date/until_date/from_time/until_time/series_number for draft, private, and password-protected calendar_event posts. Those date_id values are also the identifiers needed for the unauthenticated DELETE bypass on the sibling route.

    includes/rest-api/endpoints/class-calendar-plus-rest-endpoints-event.php:89-193

    Recommendation

    Load the event with calendarp_get_event() and return 404 unless current_user_can_read() (published/public) or the requester can edit that event. Do not return calendar rows for missing or non-event IDs.

  • medium CSRF on AJAX calendar-cell time updates (missing nonce)

    csrf

    wp_ajax_calendarp_edit_calendar_cell is reachable by any logged-in user who holds manage_calendar_plus (Administrator and the plugin's calendarp_events_manager role). The handler never calls check_ajax_referer/wp_verify_nonce. A forged POST to admin-ajax.php with action=calendarp_edit_calendar_cell, cell_id, from_time, until_time (and optional edit_all) updates wp_calendarp_calendar times for one occurrence or every row for that event, then sets _has_custom_dates. The admin calendar UI (admin.js) posts exactly those fields with no nonce. The public React calendar then displays the attacker-chosen times. Subscriber cannot invoke this directly; exploitation is CSRF of a Calendar Plus manager.

    includes/ajax.php:3-84

    Recommendation

    Call check_ajax_referer() with a dedicated action before mutating rows, localize that nonce only on the admin calendar screen, and keep the manage_calendar_plus capability check.

WP Registry hashes the installable build and reports on that exact bytes-for-bytes copy. Embargoed findings are withheld until they are disclosed, so a clean verdict means nothing public is outstanding. WP Manifest does not audit code itself.