Browse Source

Validate urls in theming settings and properly handle error messages

Signed-off-by: Julius Härtl <jus@bitgrid.net>
tags/v17.0.0beta1
Julius Härtl 4 years ago
parent
commit
47a0254bb3
No account linked to committer's email address

+ 3
- 3
apps/theming/js/settings-admin.js View File

hideUndoButton(setting, value); hideUndoButton(setting, value);
preview(setting, value, response.data.serverCssUrl); preview(setting, value, response.data.serverCssUrl);
}).fail(function(response) { }).fail(function(response) {
OC.msg.finishedSaving('#theming_settings_msg', response);
OC.msg.finishedSaving('#theming_settings_msg', response.responseJSON);
$('#theming_settings_loading').hide(); $('#theming_settings_loading').hide();
}); });
} }
return true; return true;
} else { } else {
throw t('theming', 'Name cannot be empty'); throw t('theming', 'Name cannot be empty');
}
}
} catch (error) { } catch (error) {
$('#theming-name').attr('title', error); $('#theming-name').attr('title', error);
$('#theming-name').tooltip({placement: 'top', trigger: 'manual'}); $('#theming-name').tooltip({placement: 'top', trigger: 'manual'});
if (checkName()) { if (checkName()) {
$('#theming-name').tooltip('hide'); $('#theming-name').tooltip('hide');
$('#theming-name').removeClass('error'); $('#theming-name').removeClass('error');
}
}
}); });


$('#theming-name').change(function(e) { $('#theming-name').change(function(e) {

+ 32
- 36
apps/theming/lib/Controller/ThemingController.php View File

*/ */
public function updateStylesheet($setting, $value) { public function updateStylesheet($setting, $value) {
$value = trim($value); $value = trim($value);
$error = null;
switch ($setting) { switch ($setting) {
case 'name': case 'name':
if (strlen($value) > 250) { if (strlen($value) > 250) {
return new DataResponse([
'data' => [
'message' => $this->l10n->t('The given name is too long'),
],
'status' => 'error'
]);
$error = $this->l10n->t('The given name is too long');
} }
break; break;
case 'url': case 'url':
if (strlen($value) > 500) { if (strlen($value) > 500) {
return new DataResponse([
'data' => [
'message' => $this->l10n->t('The given web address is too long'),
],
'status' => 'error'
]);
$error = $this->l10n->t('The given web address is too long');
}
if (!$this->isValidUrl($value)) {
$error = $this->l10n->t('The given web address is not a valid URL');
} }
break; break;
case 'imprintUrl': case 'imprintUrl':
if (strlen($value) > 500) { if (strlen($value) > 500) {
return new DataResponse([
'data' => [
'message' => $this->l10n->t('The given legal notice address is too long'),
],
'status' => 'error'
]);
$error = $this->l10n->t('The given legal notice address is too long');
}
if (!$this->isValidUrl($value)) {
$error = $this->l10n->t('The given legal notice address is not a valid URL');
} }
break; break;
case 'privacyUrl': case 'privacyUrl':
if (strlen($value) > 500) { if (strlen($value) > 500) {
return new DataResponse([
'data' => [
'message' => $this->l10n->t('The given privacy policy address is too long'),
],
'status' => 'error'
]);
$error = $this->l10n->t('The given privacy policy address is too long');
}
if (!$this->isValidUrl($value)) {
$error = $this->l10n->t('The given privacy policy address is not a valid URL');
} }
break; break;
case 'slogan': case 'slogan':
if (strlen($value) > 500) { if (strlen($value) > 500) {
return new DataResponse([
'data' => [
'message' => $this->l10n->t('The given slogan is too long'),
],
'status' => 'error'
]);
$error = $this->l10n->t('The given slogan is too long');
} }
break; break;
case 'color': case 'color':
if (!preg_match('/^\#([0-9a-f]{3}|[0-9a-f]{6})$/i', $value)) { if (!preg_match('/^\#([0-9a-f]{3}|[0-9a-f]{6})$/i', $value)) {
return new DataResponse([
'data' => [
'message' => $this->l10n->t('The given color is invalid'),
],
'status' => 'error'
]);
$error = $this->l10n->t('The given color is invalid');
} }
break; break;
} }
if ($error !== null) {
return new DataResponse([
'data' => [
'message' => $error,
],
'status' => 'error'
], Http::STATUS_BAD_REQUEST);
}


$this->themingDefaults->set($setting, $value); $this->themingDefaults->set($setting, $value);


); );
} }


/**
* Check that a string is a valid http/https url
*/
private function isValidUrl(string $url): bool {
return ((strpos($url, 'http://') === 0 || strpos($url, 'https://') === 0) &&
filter_var($url, FILTER_VALIDATE_URL) !== false);
}

/** /**
* @return DataResponse * @return DataResponse
* @throws NotPermittedException * @throws NotPermittedException

+ 14
- 4
apps/theming/tests/Controller/ThemingControllerTest.php View File

public function dataUpdateStylesheetSuccess() { public function dataUpdateStylesheetSuccess() {
return [ return [
['name', str_repeat('a', 250), 'Saved'], ['name', str_repeat('a', 250), 'Saved'],
['url', str_repeat('a', 500), 'Saved'],
['url', 'https://nextcloud.com/' . str_repeat('a', 478), 'Saved'],
['slogan', str_repeat('a', 500), 'Saved'], ['slogan', str_repeat('a', 500), 'Saved'],
['color', '#0082c9', 'Saved'], ['color', '#0082c9', 'Saved'],
['color', '#0082C9', 'Saved'], ['color', '#0082C9', 'Saved'],
['color', '#0082C9', 'Saved'],
['imprintUrl', 'https://nextcloud.com/' . str_repeat('a', 478), 'Saved'],
['privacyUrl', 'https://nextcloud.com/' . str_repeat('a', 478), 'Saved'],
]; ];
} }


public function dataUpdateStylesheetError() { public function dataUpdateStylesheetError() {
return [ return [
['name', str_repeat('a', 251), 'The given name is too long'], ['name', str_repeat('a', 251), 'The given name is too long'],
['url', str_repeat('a', 501), 'The given web address is too long'],
['url', 'http://example.com/' . str_repeat('a', 501), 'The given web address is too long'],
['url', str_repeat('a', 501), 'The given web address is not a valid URL'],
['url', 'javascript:alert(1)', 'The given web address is not a valid URL'],
['slogan', str_repeat('a', 501), 'The given slogan is too long'], ['slogan', str_repeat('a', 501), 'The given slogan is too long'],
['color', '0082C9', 'The given color is invalid'], ['color', '0082C9', 'The given color is invalid'],
['color', '#0082Z9', 'The given color is invalid'], ['color', '#0082Z9', 'The given color is invalid'],
['color', 'Nextcloud', 'The given color is invalid'], ['color', 'Nextcloud', 'The given color is invalid'],
['imprintUrl', '0082C9', 'The given legal notice address is not a valid URL'],
['imprintUrl', '0082C9', 'The given legal notice address is not a valid URL'],
['imprintUrl', 'javascript:foo', 'The given legal notice address is not a valid URL'],
['privacyUrl', '#0082Z9', 'The given privacy policy address is not a valid URL'],
]; ];
} }


->method('set') ->method('set')
->with($setting, $value); ->with($setting, $value);
$this->l10n $this->l10n
->expects($this->once())
->expects($this->any())
->method('t') ->method('t')
->will($this->returnCallback(function($str) { ->will($this->returnCallback(function($str) {
return $str; return $str;
'message' => $message, 'message' => $message,
], ],
'status' => 'error', 'status' => 'error',
]
],
Http::STATUS_BAD_REQUEST
); );
$this->assertEquals($expected, $this->themingController->updateStylesheet($setting, $value)); $this->assertEquals($expected, $this->themingController->updateStylesheet($setting, $value));
} }

Loading…
Cancel
Save