diff --git a/phpBB/phpbb/notification/method/webpush.php b/phpBB/phpbb/notification/method/webpush.php index 271e23dffe..a5a3b5e699 100644 --- a/phpBB/phpbb/notification/method/webpush.php +++ b/phpBB/phpbb/notification/method/webpush.php @@ -48,6 +48,9 @@ class webpush extends messenger_base implements extended_method_interface /** @var string Notification push subscriptions table */ protected $push_subscriptions_table; + /** @var int Fallback size for padding if endpoint is mozilla, see https://github.com/web-push-libs/web-push-php/issues/108#issuecomment-2133477054 */ + const MOZILLA_FALLBACK_PADDING = 2820; + /** * Notification Method Web Push constructor * @@ -218,6 +221,7 @@ class webpush extends messenger_base implements extended_method_interface { try { + $this->set_endpoint_padding($web_push, $subscription['endpoint']); $push_subscription = Subscription::create([ 'endpoint' => $subscription['endpoint'], 'keys' => [ @@ -430,4 +434,27 @@ class webpush extends messenger_base implements extended_method_interface $this->remove_subscriptions($remove_subscriptions); } + + /** + * Set web push padding for endpoint + * + * @param \Minishlink\WebPush\WebPush $web_push + * @param string $endpoint + * + * @return void + */ + protected function set_endpoint_padding(\Minishlink\WebPush\WebPush $web_push, string $endpoint): void + { + if (str_contains($endpoint, 'mozilla.com') || str_contains($endpoint, 'mozaws.net')) + { + try + { + $web_push->setAutomaticPadding(self::MOZILLA_FALLBACK_PADDING); + } + catch (\Exception) + { + // This shouldn't happen since we won't pass padding length outside limits + } + } + } } diff --git a/tests/notification/notification_method_webpush_test.php b/tests/notification/notification_method_webpush_test.php index ff95c74b09..1116a62c6f 100644 --- a/tests/notification/notification_method_webpush_test.php +++ b/tests/notification/notification_method_webpush_test.php @@ -653,6 +653,47 @@ class notification_method_webpush_test extends phpbb_tests_notification_base $this->assertCount(0, $cur_notifications, 'Assert that no notifications have been pruned'); } + public function data_set_endpoint_padding(): array + { + return [ + [ + 'foo.mozilla.com', + webpush::MOZILLA_FALLBACK_PADDING + ], + [ + 'foo.mozaws.net', + webpush::MOZILLA_FALLBACK_PADDING + ], + [ + 'foo.android.googleapis.com', + \Minishlink\WebPush\Encryption::MAX_COMPATIBILITY_PAYLOAD_LENGTH, + ], + ]; + } + + /** + * @dataProvider data_set_endpoint_padding + */ + public function test_set_endpoint_padding($endpoint, $expected_padding): void + { + $web_push_reflection = new \ReflectionMethod($this->notification_method_webpush, 'set_endpoint_padding'); + $web_push_reflection->setAccessible(true); + + $auth = [ + 'VAPID' => [ + 'subject' => generate_board_url(), + 'publicKey' => $this->config['webpush_vapid_public'], + 'privateKey' => $this->config['webpush_vapid_private'], + ], + ]; + + $web_push = new \Minishlink\WebPush\WebPush($auth); + + $this->assertEquals(\Minishlink\WebPush\Encryption::MAX_COMPATIBILITY_PAYLOAD_LENGTH, $web_push->getAutomaticPadding()); + $web_push_reflection->invoke($this->notification_method_webpush, $web_push, $endpoint); + $this->assertEquals($expected_padding, $web_push->getAutomaticPadding()); + } + protected function create_subscription_for_user($user_id, bool $invalidate_endpoint = false): array { $client = new \GuzzleHttp\Client();