Skip to content

Conversation

@Olen
Copy link

@Olen Olen commented Feb 9, 2026

Summary

  • Exclude DTSTAMP from etag computation in RefreshWebcalService to prevent false change detection
  • DTSTAMP is preserved in stored calendar data (required property per RFC 5545)

Problem

Many iCal providers (Google Calendar, Outlook 365, itslearning) set DTSTAMP to the current UTC time on every feed request per RFC 5545. Since Nextcloud computes the etag as md5(serialized_data) and DTSTAMP changes every time, every event appears modified on every refresh — even if nothing actually changed.

For a Google Calendar subscription with 2,621 events refreshed every ~15 minutes, this generates ~189K false change rows per day in oc_calendarchanges.

Reported at: #51120 (comment)

Approach

Instead of stripping DTSTAMP from the VObject (which would remove a required property from stored data), the fix strips DTSTAMP lines from a copy of the serialized string used only for etag computation:

$sObjectForEtag = preg_replace('/^DTSTAMP:.*\r?\n/m', '', $sObject);
$etag = md5($sObjectForEtag);

The stored calendar data ($sObject) is completely unchanged.

Test plan

  • New test testDtstampChangeDoesNotTriggerUpdate verifies a DTSTAMP-only change does not trigger updateCalendarObject
  • Updated identicalDataProvider etag computation to match the new DTSTAMP-stripped hashing
  • Run RefreshWebcalServiceTest unit tests

Fixes: #51120

🤖 Generated with Claude Code

@Olen Olen force-pushed the fix/strip-dtstamp-webcal-refresh branch 2 times, most recently from 7df84bc to 4c5b46f Compare February 9, 2026 11:38
@tcitworld
Copy link
Member

As the DTSTAMP is a required property, we shouldn't remove it from the saved payload, but just do the md5 hash without it.

@Olen Olen force-pushed the fix/strip-dtstamp-webcal-refresh branch from 4c5b46f to 36fdb9a Compare February 9, 2026 17:25
@Olen
Copy link
Author

Olen commented Feb 9, 2026

Thanks for the review @tcitworld — you're absolutely right. DTSTAMP is a required property per RFC 5545 and shouldn't be removed from the stored data.

Apologies for being too quick with the initial approach. I've reworked the fix to be much more minimal: instead of stripping DTSTAMP from the VObject before serialization, it now only strips the DTSTAMP lines from a copy of the serialized string used for the etag/md5 computation. The stored calendar data is completely unchanged — DTSTAMP is preserved.

The diff is now just one line replaced in RefreshWebcalService.php:

-$etag = md5($sObject);
+$sObjectForEtag = preg_replace('/^DTSTAMP:.*\r?\n/m', '', $sObject);
+$etag = md5($sObjectForEtag);

@Olen Olen force-pushed the fix/strip-dtstamp-webcal-refresh branch from 36fdb9a to 6d10452 Compare February 9, 2026 17:27
@Olen Olen force-pushed the fix/strip-dtstamp-webcal-refresh branch 2 times, most recently from 9d58868 to 6487bb3 Compare February 9, 2026 19:56
@Olen
Copy link
Author

Olen commented Feb 9, 2026

Good point @tcitworld — updated the regex to handle both parameters (DTSTAMP;TZID=...) and RFC 5545 content line folding:

'/^DTSTAMP[;:].*\r?\n([ \t].*\r?\n)*/m'

This matches DTSTAMP starting with either ; (parameters) or : (value), plus any continuation lines starting with a space or tab.

Also added a new test testFoldedDtstampChangeDoesNotTriggerUpdate that uses a DTSTAMP with a long parameter value (X-VOBJ-ORIGINAL-TZID=America/Argentina/Buenos_Aires) exceeding 75 bytes to verify the regex handles folded lines correctly.

@Olen Olen force-pushed the fix/strip-dtstamp-webcal-refresh branch 2 times, most recently from 657d513 to acbac30 Compare February 9, 2026 20:03
Many iCal providers (Google Calendar, Outlook, itslearning) set DTSTAMP
to the current time on every feed request per RFC 5545, causing every
event to appear modified on every subscription refresh.

Strip DTSTAMP lines from a copy of the serialized data used for etag
computation only. The stored calendar data is unchanged — DTSTAMP is
preserved as it is a required property per RFC 5545.

The regex handles DTSTAMP with parameters (DTSTAMP;TZID=...) and
RFC 5545 content line folding where long lines are split with CRLF
followed by a space or tab.

Signed-off-by: Olen <regopa@gmail.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: olen <ola@nytt.no>
@Olen Olen force-pushed the fix/strip-dtstamp-webcal-refresh branch from acbac30 to 496095a Compare February 9, 2026 20:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Optimize Deletion of Objects for Calendar Subscriptions

2 participants