Skip to content

Commit

Permalink
Validate site short name when entered in ACP
Browse files Browse the repository at this point in the history
Signed-off-by: Matt Friedman <[email protected]>
  • Loading branch information
iMattPro committed Sep 12, 2024
1 parent 93cf693 commit 2a21525
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 32 deletions.
99 changes: 69 additions & 30 deletions event/listener.php
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,9 @@ public function acp_pwa_options($event)

$my_config_vars = [
'legend_pwa_settings'=> 'PWA_SETTINGS',
'pwa_short_name' => ['lang' => 'PWA_SHORT_NAME', 'validate' => 'string', 'type' => 'custom', 'function' => [$this, 'pwa_short_sitename'], 'explain' => true],
'pwa_icon_small' => ['lang' => 'PWA_ICON_SMALL', 'validate' => 'pwa_options', 'type' => 'custom', 'function' => [$this, 'pwa_icon_name'], 'explain' => true],
'pwa_icon_large' => ['lang' => 'PWA_ICON_LARGE', 'validate' => 'pwa_options', 'type' => 'custom', 'function' => [$this, 'pwa_icon_name'], 'explain' => true],
'pwa_short_name' => ['lang' => 'PWA_SHORT_NAME', 'validate' => 'pwa_options:string', 'type' => 'custom', 'function' => [$this, 'pwa_short_sitename'], 'explain' => true],
'pwa_icon_small' => ['lang' => 'PWA_ICON_SMALL', 'validate' => 'pwa_options:icons', 'type' => 'custom', 'function' => [$this, 'pwa_icon_name'], 'explain' => true],
'pwa_icon_large' => ['lang' => 'PWA_ICON_LARGE', 'validate' => 'pwa_options:icons', 'type' => 'custom', 'function' => [$this, 'pwa_icon_name'], 'explain' => true],
];

$event->update_subarray('display_vars', 'vars', phpbb_insert_config_array($event['display_vars']['vars'], $my_config_vars, ['before' => 'legend4']));
Expand Down Expand Up @@ -203,40 +203,79 @@ public function pwa_short_sitename($value, $key)
*/
public function validate_pwa_options($event)
{
// Ignore validation if icon fields are empty
if ($event['config_definition']['validate'] !== 'pwa_options' || (empty($event['cfg_array']['pwa_icon_small']) && empty($event['cfg_array']['pwa_icon_large'])))
{
return;
}
$type = 0;
$mode = 1;

$value = $event['cfg_array'][$event['config_name']];
$validator = explode(':', $event['config_definition']['validate']);

// Don't allow empty values, if one icon is set, both must be set.
if (empty($value))
if ($validator[$type] !== 'pwa_options')
{
$this->add_error($event, 'PWA_IMAGE_NOT_PROVIDED', $this->language->lang(strtoupper($event['config_name'])));
return;
}

// Check if image is valid
$image = $this->root_path . $this->config['icons_path'] . '/' . $value;
$image_info = $this->imagesize->getImageSize($image);
if ($image_info !== false)
{
if (($event['config_name'] === 'pwa_icon_small' && $image_info['width'] !== 192 && $image_info['height'] !== 192) ||
($event['config_name'] === 'pwa_icon_large' && $image_info['width'] !== 512 && $image_info['height'] !== 512))
{
$this->add_error($event, 'PWA_ICON_SIZE_INVALID', $value);
}

if ($image_info['type'] !== IMAGETYPE_PNG)
{
$this->add_error($event, 'PWA_ICON_MIME_INVALID', $value);
}
}
else
switch ($validator[$mode])
{
$this->add_error($event, 'PWA_IMAGE_INVALID', $value);
case 'string':
// Ignore validation if icon fields are empty
if (empty($event['cfg_array']['pwa_short_name']))
{
return;
}

$short_name = $event['cfg_array']['pwa_short_name'];

// Do not allow multibyte characters or emoji
if (strlen($short_name) !== mb_strlen($short_name, 'UTF-8'))
{
$this->add_error($event, 'PWA_SHORT_NAME_INVALID');
return;
}

// Do not allow strings longer than 12 characters
if (strlen($short_name) > 12)
{
$this->add_error($event, 'PWA_SHORT_NAME_INVALID');
return;
}
break;

case 'icons':
// Ignore validation if icon fields are empty
if (empty($event['cfg_array']['pwa_icon_small']) && empty($event['cfg_array']['pwa_icon_large']))
{
return;
}

$value = $event['cfg_array'][$event['config_name']];

// Don't allow empty values, if one icon is set, both must be set.
if (empty($value))
{
$this->add_error($event, 'PWA_IMAGE_NOT_PROVIDED', $this->language->lang(strtoupper($event['config_name'])));
return;
}

// Check if image is valid
$image = $this->root_path . $this->config['icons_path'] . '/' . $value;
$image_info = $this->imagesize->getImageSize($image);
if ($image_info !== false)
{
if (($event['config_name'] === 'pwa_icon_small' && $image_info['width'] !== 192 && $image_info['height'] !== 192) ||
($event['config_name'] === 'pwa_icon_large' && $image_info['width'] !== 512 && $image_info['height'] !== 512))
{
$this->add_error($event, 'PWA_ICON_SIZE_INVALID', $value);
}

if ($image_info['type'] !== IMAGETYPE_PNG)
{
$this->add_error($event, 'PWA_ICON_MIME_INVALID', $value);
}
}
else
{
$this->add_error($event, 'PWA_IMAGE_INVALID', $value);
}
break;
}
}

Expand Down
1 change: 1 addition & 0 deletions language/en/webpushnotifications_common_acp.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
'PWA_SETTINGS' => 'Progressive web application options',
'PWA_SHORT_NAME' => 'Short site name',
'PWA_SHORT_NAME_EXPLAIN' => 'Your site name in 12 characters or fewer, which may be used as a label for an icon on a mobile device’s home screen. (If this field is left empty, the first 12 characters of the <samp>Site name</samp> will be used.)',
'PWA_SHORT_NAME_INVALID' => '“Short site name” contains illegal characters or exceeds the 12 character limit.',
'PWA_ICON_SMALL' => 'Small mobile device icon',
'PWA_ICON_SMALL_EXPLAIN' => 'File name of a 192px x 192px PNG image. This file must be uploaded to your board’s <samp>icons</samp> directory.',
'PWA_ICON_LARGE' => 'Large mobile device icon',
Expand Down
29 changes: 27 additions & 2 deletions tests/event/listener_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -334,36 +334,61 @@ public function validate_pwa_options_data()
{
return [
[
'pwa_options:icons',
['pwa_icon_small' => '192.png', 'pwa_icon_large' => '512.png'],
[],
],
[
'pwa_options:icons',
['pwa_icon_small' => '1.png', 'pwa_icon_large' => '512.png'],
['PWA_ICON_SIZE_INVALID'],
],
[
'pwa_options:icons',
['pwa_icon_small' => '1.png', 'pwa_icon_large' => '12.png'],
['PWA_ICON_SIZE_INVALID'],
],
[
'pwa_options:icons',
['pwa_icon_small' => '192.jpg', 'pwa_icon_large' => '512.gif'],
['PWA_ICON_MIME_INVALID'],
],
[
'pwa_options:icons',
['pwa_icon_small' => '', 'pwa_icon_large' => ''],
[],
],
[
'pwa_options:string',
['pwa_short_name' => 'foo'],
[],
],
[
'pwa_options:string',
['pwa_short_name' => ''],
[],
],
[
'pwa_options:string',
['pwa_short_name' => 'foo❤️'],
['PWA_SHORT_NAME_INVALID'],
],
[
'pwa_options:string',
['pwa_short_name' => str_repeat('a', 50)],
['PWA_SHORT_NAME_INVALID'],
],
];
}

/**
* @dataProvider validate_pwa_options_data
*/
public function test_validate_pwa_options($cfg_array, $expected_error)
public function test_validate_pwa_options($validate, $cfg_array, $expected_error)
{
$this->config['icons_path'] = 'images/icons';
$config_name = key($cfg_array);
$config_definition = ['validate' => 'pwa_options'];
$config_definition = ['validate' => $validate];
$small_image = $cfg_array['pwa_icon_small'] ? explode('.', $cfg_array['pwa_icon_small']) : ['', ''];
$large_image = $cfg_array['pwa_icon_large'] ? explode('.', $cfg_array['pwa_icon_large']) : ['', ''];
$error = [];
Expand Down

0 comments on commit 2a21525

Please sign in to comment.