diff --git a/Content.Client/CartridgeLoader/Cartridges/NewsReaderUiFragment.xaml.cs b/Content.Client/CartridgeLoader/Cartridges/NewsReaderUiFragment.xaml.cs index 2d4d192ea8..cf667ff7e9 100644 --- a/Content.Client/CartridgeLoader/Cartridges/NewsReaderUiFragment.xaml.cs +++ b/Content.Client/CartridgeLoader/Cartridges/NewsReaderUiFragment.xaml.cs @@ -1,8 +1,11 @@ using Content.Client.Message; +using Content.Client.UserInterface.RichText; // DeltaV - Sanitize markup; see https://github.com/space-wizards/space-station-14/pull/41799 using Content.Shared.MassMedia.Systems; using Robust.Client.AutoGenerated; using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.RichText; // DeltaV - Sanitize markup; see https://github.com/space-wizards/space-station-14/pull/41799 using Robust.Client.UserInterface.XAML; +using Robust.Shared.Utility; // DeltaV - Sanitize markup; see https://github.com/space-wizards/space-station-14/pull/41799 namespace Content.Client.CartridgeLoader.Cartridges; @@ -14,6 +17,18 @@ public sealed partial class NewsReaderUiFragment : BoxContainer public event Action? OnNotificationSwithPressed; + // DeltaV - Sanitize markup; see https://github.com/space-wizards/space-station-14/pull/41799 + private static readonly Type[] AllowedTags = + [ + typeof(BoldItalicTag), + typeof(BoldTag), + typeof(BulletTag), + typeof(ColorTag), + typeof(HeadingTag), + typeof(ItalicTag), + typeof(MonoTag), + ]; + public NewsReaderUiFragment() { RobustXamlLoader.Load(this); @@ -31,16 +46,17 @@ public sealed partial class NewsReaderUiFragment : BoxContainer Author.Visible = true; PageName.Text = article.Title; - PageText.SetMarkupPermissive(article.Content); + PageText.SetMessage(FormattedMessage.FromMarkupPermissive(article.Content), AllowedTags); // DeltaV - Sanitize markup; see https://github.com/space-wizards/space-station-14/pull/41799 PageNum.Text = $"{targetNum}/{totalNum}"; NotificationSwitch.Text = Loc.GetString(notificationOn ? "news-read-ui-notification-on" : "news-read-ui-notification-off"); - string shareTime = article.ShareTime.ToString(@"hh\:mm\:ss"); + var shareTime = article.ShareTime.ToString(@"hh\:mm\:ss"); ShareTime.SetMarkup(Loc.GetString("news-read-ui-time-prefix-text") + " " + shareTime); - Author.SetMarkup(Loc.GetString("news-read-ui-author-prefix") + " " + (article.Author != null ? article.Author : Loc.GetString("news-read-ui-no-author"))); + var author = Loc.GetString("news-read-ui-author-prefix") + " " + (article.Author ?? Loc.GetString("news-read-ui-no-author")); // DeltaV - Sanitize markup; see https://github.com/space-wizards/space-station-14/pull/41799 + Author.SetMessage(FormattedMessage.FromMarkupPermissive(author), AllowedTags); // DeltaV - Sanitize markup; see https://github.com/space-wizards/space-station-14/pull/41799 Prev.Disabled = targetNum <= 1; Next.Disabled = targetNum >= totalNum; diff --git a/Content.Client/MassMedia/Ui/ArticleEditorPanel.xaml.cs b/Content.Client/MassMedia/Ui/ArticleEditorPanel.xaml.cs index 90a66bec7f..e56633214a 100644 --- a/Content.Client/MassMedia/Ui/ArticleEditorPanel.xaml.cs +++ b/Content.Client/MassMedia/Ui/ArticleEditorPanel.xaml.cs @@ -1,10 +1,12 @@ using Content.Client.Message; using Content.Client.Stylesheets; +using Content.Client.UserInterface.RichText; // DeltaV - Sanitize markup; see https://github.com/space-wizards/space-station-14/pull/41799 using Content.Shared.MassMedia.Systems; using Robust.Client.AutoGenerated; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.CustomControls; +using Robust.Client.UserInterface.RichText; // DeltaV - Sanitize markup; see https://github.com/space-wizards/space-station-14/pull/41799 using Robust.Client.UserInterface.XAML; using Robust.Shared.Utility; @@ -18,6 +20,18 @@ public sealed partial class ArticleEditorPanel : Control private bool _preview; + // DeltaV - Sanitize markup; see https://github.com/space-wizards/space-station-14/pull/41799 + private static readonly Type[] AllowedTags = + [ + typeof(BoldItalicTag), + typeof(BoldTag), + typeof(BulletTag), + typeof(ColorTag), + typeof(HeadingTag), + typeof(ItalicTag), + typeof(MonoTag), + ]; + public ArticleEditorPanel() { RobustXamlLoader.Load(this); @@ -29,7 +43,7 @@ public sealed partial class ArticleEditorPanel : Control // Customize scrollbar width and margin. This is not possible in xaml var scrollbar = ContentField.GetChild(1); scrollbar.SetWidth = 6f; - scrollbar.Margin = new Thickness(9, 0, 2 , 0); + scrollbar.Margin = new Thickness(9, 0, 2, 0); RichTextInfoLabel.TooltipSupplier = sender => { @@ -81,7 +95,9 @@ public sealed partial class ArticleEditorPanel : Control TextEditPanel.Visible = !_preview; PreviewPanel.Visible = _preview; - PreviewLabel.SetMarkupPermissive(Rope.Collapse(ContentField.TextRope)); + + var articleBody = Rope.Collapse(ContentField.TextRope); // DeltaV - Sanitize markup; see https://github.com/space-wizards/space-station-14/pull/41799 + PreviewLabel.SetMessage(FormattedMessage.FromMarkupPermissive(articleBody), AllowedTags); // DeltaV - Sanitize markup; see https://github.com/space-wizards/space-station-14/pull/41799 } private void OnCancel(BaseButton.ButtonEventArgs eventArgs) diff --git a/Content.Client/PDA/PdaMenu.xaml.cs b/Content.Client/PDA/PdaMenu.xaml.cs index 38da9c9077..a530f36328 100644 --- a/Content.Client/PDA/PdaMenu.xaml.cs +++ b/Content.Client/PDA/PdaMenu.xaml.cs @@ -146,7 +146,7 @@ namespace Content.Client.PDA if (state.PdaOwnerInfo.ActualOwnerName != null) { - _pdaOwner = state.PdaOwnerInfo.ActualOwnerName; + _pdaOwner = FormattedMessage.EscapeText(state.PdaOwnerInfo.ActualOwnerName); // DeltaV - Escape actual owner PdaOwnerLabel.SetMarkup(Loc.GetString("comp-pda-ui-owner", ("actualOwnerName", _pdaOwner))); PdaOwnerLabel.Visible = true; @@ -159,8 +159,8 @@ namespace Content.Client.PDA if (state.PdaOwnerInfo.IdOwner != null || state.PdaOwnerInfo.JobTitle != null) { - _owner = state.PdaOwnerInfo.IdOwner ?? Loc.GetString("comp-pda-ui-unknown"); - _jobTitle = state.PdaOwnerInfo.JobTitle ?? Loc.GetString("comp-pda-ui-unassigned"); + _owner = FormattedMessage.EscapeText(state.PdaOwnerInfo.IdOwner ?? Loc.GetString("comp-pda-ui-unknown")); // DeltaV - Escape owner and job + _jobTitle = FormattedMessage.EscapeText(state.PdaOwnerInfo.JobTitle ?? Loc.GetString("comp-pda-ui-unassigned")); // DeltaV - Escape owner and job IdInfoLabel.SetMarkup(Loc.GetString("comp-pda-ui", ("owner", _owner), ("jobTitle", _jobTitle))); diff --git a/Content.Client/_DV/CartridgeLoader/Cartridges/NanoChatEntry.xaml.cs b/Content.Client/_DV/CartridgeLoader/Cartridges/NanoChatEntry.xaml.cs index 00f0ba9ddd..15d03f5a81 100644 --- a/Content.Client/_DV/CartridgeLoader/Cartridges/NanoChatEntry.xaml.cs +++ b/Content.Client/_DV/CartridgeLoader/Cartridges/NanoChatEntry.xaml.cs @@ -4,6 +4,7 @@ using Content.Shared.Access.Components; using Robust.Client.AutoGenerated; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.XAML; +using Robust.Shared.Utility; namespace Content.Client._DV.CartridgeLoader.Cartridges; @@ -38,9 +39,10 @@ public sealed partial class NanoChatEntry : BoxContainer _pressHandler = _ => OnPressed?.Invoke(_number); ChatButton.OnPressed += _pressHandler; - NameLabel.Text = SharedNanoChatSystem.Truncate(recipient.Name, _maxNameLength); - JobLabel.Text = SharedNanoChatSystem.Truncate(recipient.JobTitle ?? "", _maxIdJobLength); - JobLabel.Visible = !string.IsNullOrEmpty(recipient.JobTitle); + // FIXME: Truncate and Escape can lead to stray `\`, if the truncate cuts a markup tag in half + NameLabel.Text = FormattedMessage.EscapeText(SharedNanoChatSystem.Truncate(recipient.Name, _maxNameLength)); + JobLabel.Text = FormattedMessage.EscapeText(SharedNanoChatSystem.Truncate(recipient.JobTitle ?? string.Empty, _maxIdJobLength)); + JobLabel.Visible = !string.IsNullOrWhiteSpace(JobLabel.Text); UnreadIndicator.Visible = recipient.HasUnread; ChatButton.ModulateSelfOverride = isSelected ? NanoChatMessageBubble.OwnMessageColor : null; diff --git a/Content.Client/_DV/CartridgeLoader/Cartridges/NanoChatMessageBubble.xaml.cs b/Content.Client/_DV/CartridgeLoader/Cartridges/NanoChatMessageBubble.xaml.cs index 3a4e37d040..e93e23ebea 100644 --- a/Content.Client/_DV/CartridgeLoader/Cartridges/NanoChatMessageBubble.xaml.cs +++ b/Content.Client/_DV/CartridgeLoader/Cartridges/NanoChatMessageBubble.xaml.cs @@ -3,6 +3,7 @@ using Robust.Client.AutoGenerated; using Robust.Client.Graphics; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.XAML; +using Robust.Shared.Utility; namespace Content.Client._DV.CartridgeLoader.Cartridges; @@ -31,7 +32,7 @@ public sealed partial class NanoChatMessageBubble : BoxContainer style.BorderColor = BorderColor; // Set message content - MessageText.Text = message.Content; + MessageText.Text = FormattedMessage.EscapeText(message.Content); MessageText.Modulate = TextColor; // Show delivery failed text if needed (only for own messages) diff --git a/Content.Shared/Access/Systems/IdExaminableSystem.cs b/Content.Shared/Access/Systems/IdExaminableSystem.cs index c05262f2f6..de80c3b047 100644 --- a/Content.Shared/Access/Systems/IdExaminableSystem.cs +++ b/Content.Shared/Access/Systems/IdExaminableSystem.cs @@ -69,12 +69,14 @@ public sealed class IdExaminableSystem : EntitySystem { var jobSuffix = string.IsNullOrWhiteSpace(id.LocalizedJobTitle) ? string.Empty : $" ({id.LocalizedJobTitle})"; - var val = string.IsNullOrWhiteSpace(id.FullName) + var val = FormattedMessage.EscapeText( // DeltaV - Escape job + string.IsNullOrWhiteSpace(id.FullName) ? Loc.GetString(id.NameLocId, ("jobSuffix", jobSuffix)) : Loc.GetString(id.FullNameLocId, ("fullName", id.FullName), - ("jobSuffix", jobSuffix)); + ("jobSuffix", jobSuffix)) + ); return val; } diff --git a/Content.Shared/Labels/EntitySystems/LabelSystem.cs b/Content.Shared/Labels/EntitySystems/LabelSystem.cs index 9674ba0e5b..827f110aed 100644 --- a/Content.Shared/Labels/EntitySystems/LabelSystem.cs +++ b/Content.Shared/Labels/EntitySystems/LabelSystem.cs @@ -60,7 +60,7 @@ public sealed partial class LabelSystem : EntitySystem return; label ??= EnsureComp(uid); - label.CurrentLabel = text; + label.CurrentLabel = text == null ? null : FormattedMessage.EscapeText(text); _nameModifier.RefreshNameModifiers(uid); Dirty(uid, label);