Fix truncating multibyte chars in section names

Bug: T345648
Change-Id: I968c954aac94e3bbf8fa4a886f2422194ae0608f
This commit is contained in:
Bartosz Dziewoński 2023-09-07 20:44:43 +02:00 committed by Bartosz Dziewoński
parent 2aafd08c4b
commit 07df1ac620
2 changed files with 22 additions and 6 deletions

View file

@ -214,6 +214,13 @@ class SubscriptionStore {
if ( !$user->isRegistered() || $this->userIdentityUtils->isTemp( $user ) ) {
return false;
}
$section = $target->getFragment();
// Truncate to the database field length, taking care not to mess up multibyte characters,
// appending a marker so that we can recognize this happened and display an ellipsis later.
// Using U+001F "Unit Separator" seems appropriate, and it can't occur in wikitext.
$truncSection = strlen( $section ) > 254 ? mb_strcut( $section, 0, 254 ) . "\x1f" : $section;
$dbw = $this->dbProvider->getPrimaryDatabase();
$dbw->upsert(
'discussiontools_subscription',
@ -221,7 +228,7 @@ class SubscriptionStore {
'sub_user' => $user->getId(),
'sub_namespace' => $target->getNamespace(),
'sub_title' => $target->getDBkey(),
'sub_section' => $target->getFragment(),
'sub_section' => $truncSection,
'sub_item' => $itemName,
'sub_state' => $state,
'sub_created' => $dbw->timestamp(),

View file

@ -80,12 +80,21 @@ class TopicSubscriptionsPager extends TablePager {
$this->msg( 'discussiontools-topicsubscription-pager-newtopics-label' )->escaped() .
'</em>';
} else {
$titleSection = Title::makeTitleSafe( $row->sub_namespace, $row->sub_title, $row->sub_section );
if ( !$titleSection ) {
// Handle invalid titles (T345648)
return htmlspecialchars( $row->sub_section );
$section = $row->sub_section;
// Detect truncated section titles: either intentionally truncated by SubscriptionStore,
// or incorrect multibyte truncation of old entries (T345648).
$last = mb_substr( $section, -1 );
if ( $last !== '' && ( $last === "\x1f" || mb_ord( $last ) === false ) ) {
$section = substr( $section, 0, -strlen( $last ) );
// We can't link to the section correctly, since the only link we have is truncated
return htmlspecialchars( $section ) . $this->msg( 'ellipsis' )->escaped();
}
return $linkRenderer->makeLink( $titleSection, $row->sub_section );
$titleSection = Title::makeTitleSafe( $row->sub_namespace, $row->sub_title, $section );
if ( !$titleSection ) {
// Handle invalid titles of any other kind, just in case
return htmlspecialchars( $section );
}
return $linkRenderer->makeLink( $titleSection, $section );
}
case '_page':