From c6e526279e0ff88e634ee65d2cadf2e1aae5348e Mon Sep 17 00:00:00 2001 From: ECYaz Date: Fri, 7 Aug 2026 11:57:01 -0400 Subject: [PATCH] Reject links entered as contribution names or permalinks A link pasted into the permalink field was rejected, but the error message suggested the slugified link back as a valid example, and pasting that suggestion in is accepted. A link entered as the contribution name with the permalink left blank produced the same garbage permalink silently. Both mistakes gave the contribution a permanent link shaped address only moderators can fix, which is how the ColoredLight permalink in #394 came to be. Reject values shaped like a link in the name and permalink fields with a clear message instead. Existing contributions with such a name or permalink still pass validation untouched, so they are not locked out of their manage page. --- controller/contribution/manage.php | 3 ++- includes/objects/contribution.php | 24 +++++++++++++++++++++++- language/en/contributions.php | 2 ++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/controller/contribution/manage.php b/controller/contribution/manage.php index 453c3f4d1..96df80834 100644 --- a/controller/contribution/manage.php +++ b/controller/contribution/manage.php @@ -216,7 +216,8 @@ public function manage($contrib_type, $contrib) $authors, $this->settings['custom'], $this->contrib->contrib_name_clean, - $this->settings['permalink'] + $this->settings['permalink'], + $old_settings['contrib_name'] )); // Did we succeed or have an error? diff --git a/includes/objects/contribution.php b/includes/objects/contribution.php index c4b74f3d0..5c1d97e23 100644 --- a/includes/objects/contribution.php +++ b/includes/objects/contribution.php @@ -1590,10 +1590,11 @@ public function change_permalink($new_permalink) * @param array $custom_fields Custom field values. * @param string $old_permalink Old permalink. Defaults to empty string. * @param string|null $new_permalink Submitted permalink. Defaults to the value on the entity. + * @param string $old_name Old contribution name. Defaults to empty string. * * @return array Returns array containing any errors found. */ - public function validate($contrib_categories, $authors, $custom_fields, $old_permalink = '', $new_permalink = null) + public function validate($contrib_categories, $authors, $custom_fields, $old_permalink = '', $new_permalink = null, $old_name = '') { phpbb::$user->add_lang('ucp'); @@ -1603,6 +1604,10 @@ public function validate($contrib_categories, $authors, $custom_fields, $old_per { $error[] = phpbb::$user->lang['EMPTY_CONTRIB_NAME']; } + else if ($this->contrib_name !== $old_name && $this->is_link($this->contrib_name)) + { + $error[] = phpbb::$user->lang['CONTRIB_NAME_IS_LINK']; + } $metadata = array( $this->contrib_name, @@ -1800,6 +1805,17 @@ protected function generate_permalink_slug($value) return preg_replace('/[^\p{L}\p{M}\p{N}_]+/u', '_', url::generate_slug($value)); } + /** + * Check whether a value is shaped like a link rather than a name. + * + * @param string $value + * @return bool + */ + protected function is_link($value) + { + return (bool) preg_match('#^(?:[a-z][a-z0-9+.\-]*://|www\.)#i', trim($value)); + } + /* * Validate a contrib permalink * @@ -1816,6 +1832,12 @@ public function validate_permalink($permalink, $old_permalink) return false; } + // A pasted link must not be echoed back as a valid permalink example. + if ($this->is_link($permalink)) + { + return phpbb::$user->lang['CONTRIB_PERMALINK_IS_LINK']; + } + $generated_permalink = $this->generate_permalink_slug($permalink); if ($generated_permalink !== $permalink) { diff --git a/language/en/contributions.php b/language/en/contributions.php index 3de7f78fc..5a6504821 100644 --- a/language/en/contributions.php +++ b/language/en/contributions.php @@ -79,6 +79,7 @@ 'CONTRIB_LOCAL_NAME' => 'Local name', 'CONTRIB_LOCAL_NAME_EXPLAIN' => 'The localized name of the language, e.g. Français.', 'CONTRIB_NAME' => 'Contribution Name', + 'CONTRIB_NAME_IS_LINK' => 'The contribution name cannot be a link. Please enter the name of your contribution.', 'CONTRIB_NEW' => 'New', 'CONTRIB_NONACTIVE_AUTHORS' => 'Non-Active Co-Authors (Past Contributors)', 'CONTRIB_NONACTIVE_AUTHORS_EXPLAIN' => 'Non-Active Co-Authors can not manage anything for the contribution and are only listed as previous authors.', @@ -87,6 +88,7 @@ 'CONTRIB_PERMALINK' => 'Contribution Permalink', 'CONTRIB_PERMALINK_EXISTS' => 'That contribution permalink is already in use.', 'CONTRIB_PERMALINK_EXPLAIN' => 'Cleaned version of the contribution name, used to build the url for the contribution.
Leave blank to have one automatically created based on the contribution name.', + 'CONTRIB_PERMALINK_IS_LINK' => 'The permalink cannot be a link. It is the short address of the contribution page, built from the contribution name.', 'CONTRIB_RELEASE_DATE' => 'Release date', 'CONTRIB_STATUS' => 'Contribution status', 'CONTRIB_STATUS_EXPLAIN' => 'Change the contribution status',