Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion dev2/sites.d/webmail.profullstack.com.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"service": "webmail.profullstack.com",
"repo": null,
"branch": null,
"image": "profullstack/webmail:1.7.5-cal3",
"image": "profullstack/webmail:1.7.5-cal5",
"start_command": "apache2-foreground",
"port_var": "80",
"domains": [
Expand Down
4 changes: 4 additions & 0 deletions dev2/webmail/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,9 @@ RUN f=/usr/src/roundcubemail/plugins/calendar/lib/calendar_ui.php \
&& sed -i "s#html::div('col-sm-8', \$select->show(1))#html::div('col-sm-8', \$select->show(0))#" $f \
&& grep -c "select->show(0))" $f

# Exact-match source patches (fail the build if upstream moves): see patches.php.
COPY patches.php /tmp/patches.php
RUN php /tmp/patches.php && php -l /usr/src/roundcubemail/plugins/libcalendaring/lib/libcalendaring_recurrence.php && rm /tmp/patches.php

COPY --chmod=755 googlecal /usr/src/roundcubemail/plugins/googlecal
COPY --chmod=644 carddav.config.inc.php /usr/src/roundcubemail/plugins/carddav/config.inc.php
8 changes: 8 additions & 0 deletions dev2/webmail/googlecal/googlecal.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,14 @@ public function callback()
$this->rc->output->redirect($back);
return;
}
// Google's consent screen shows calendar access as its own checkbox; without it
// every CalDAV call is 403 insufficientPermissions. Refuse instead of half-connecting.
if (strpos((string) ($r['scope'] ?? ''), 'https://www.googleapis.com/auth/calendar') === false) {
$this->post(self::REVOKE_URL, ['token' => $r['refresh_token']]);
$this->rc->output->show_message('Google did not grant calendar access. Click Connect again and tick "See, edit, share, and permanently delete all the calendars" on Google\'s screen.', 'error', null, true, 30);
$this->rc->output->redirect($back);
return;
}
$email = '';
if (!empty($r['id_token']) && count($parts = explode('.', $r['id_token'])) === 3) {
$claims = json_decode(base64_decode(strtr($parts[1], '-_', '+/')), true);
Expand Down
58 changes: 58 additions & 0 deletions dev2/webmail/patches.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php
// Build-time source patches for plugins installed by composer. Each patch is an exact
// string replacement that must match once; the build fails if upstream changes it.
$patches = [
// libcalendaring 3.6.1: toDateTime() re-parses a recurrence's last occurrence with
// createFromFormat, which can return false; the next line then dies with "Attempt to
// assign property _dateonly on false" and the whole CalDAV sync of that calendar
// aborts (seen on a Google calendar with ~800 events). Fall back to the timestamp,
// and return false (no end) only when there is no date at all.
'/usr/src/roundcubemail/plugins/libcalendaring/lib/libcalendaring_recurrence.php' => [[
<<<'OLD'
if ($date instanceof DateTimeInterface) {
$date = libcalendaring_datetime::createFromFormat(
'Y-m-d\\TH:i:s',
$date->format('Y-m-d\\TH:i:s'),
// Sabre will loose timezone on all-day events, use the event start's timezone
$this->start->getTimezone()
);
}

$date->_dateonly = $this->dateonly;
OLD,
<<<'NEW'
if ($date instanceof DateTimeInterface) {
$src = $date;
$date = libcalendaring_datetime::createFromFormat(
'Y-m-d\\TH:i:s',
$date->format('Y-m-d\\TH:i:s'),
// Sabre will loose timezone on all-day events, use the event start's timezone
$this->start->getTimezone()
);
if (!$date) {
$date = new libcalendaring_datetime('@' . $src->getTimestamp());
$date->setTimezone($this->start->getTimezone());
}
}

if (!is_object($date)) {
return false;
}

$date->_dateonly = $this->dateonly;
NEW,
]],
];

foreach ($patches as $file => $list) {
$src = file_get_contents($file);
foreach ($list as [$old, $new]) {
if (substr_count($src, $old) !== 1) {
fwrite(STDERR, "patch does not apply to $file\n");
exit(1);
}
$src = str_replace($old, $new, $src);
}
file_put_contents($file, $src);
echo "patched $file\n";
}
Loading