Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix some image attachments in comments not loading in game #30866

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions osu.Game.Tests/Visual/Online/TestSceneImageProxying.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using System;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Textures;
using osu.Framework.Platform;
using osu.Game.Graphics.Containers.Markdown;
using osu.Game.Online;

namespace osu.Game.Tests.Visual.Online
{
public partial class TestSceneImageProxying : OsuTestScene
{
[Resolved]
private GameHost host { get; set; } = null!;

[Test]
public void TestExternalImageLink()
{
AddStep("load image", () => Child = new OsuMarkdownContainer
{
RelativeSizeAxes = Axes.Both,
Text = "![](https://github.com/ppy/osu-wiki/blob/master/wiki/Announcement_messages/img/notification.png?raw=true)",
});
}

[Test]
public void TestLocalImageLink()
{
AddStep("load image", () => Child = new OsuMarkdownContainer
{
RelativeSizeAxes = Axes.Both,
Text = "![](https://osu.ppy.sh/help/wiki/shared/news/banners/monthly-beatmapping-contest.png)",
});
}

[Test]
public void TestInvalidImageLink()
{
AddStep("load image", () => Child = new OsuMarkdownContainer
{
RelativeSizeAxes = Axes.Both,
Text = "![](https://this-site-does-not-exist.com/img.png)",
});
}
}
}
7 changes: 4 additions & 3 deletions osu.Game/Audio/PreviewTrackManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
using osu.Framework.Audio.Track;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.IO.Stores;
using osu.Framework.Logging;
using osu.Game.Beatmaps;
using osu.Game.Online;
using osu.Game.Online.API;

namespace osu.Game.Audio
{
Expand All @@ -28,9 +29,9 @@ public PreviewTrackManager(IAdjustableAudioComponent mainTrackAdjustments)
}

[BackgroundDependencyLoader]
private void load(AudioManager audioManager)
private void load(AudioManager audioManager, IAPIProvider api)
{
trackStore = audioManager.GetTrackStore(new OnlineStore());
trackStore = audioManager.GetTrackStore(new OsuOnlineStore(api.APIEndpointUrl));
}

/// <summary>
Expand Down
3 changes: 3 additions & 0 deletions osu.Game/Graphics/Containers/Markdown/OsuMarkdownImage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,8 @@ public OsuMarkdownImage(LinkInline linkInline)
{
TooltipText = linkInline.Title;
}

protected override ImageContainer CreateImageContainer(string url)
=> base.CreateImageContainer($@"https://osu.ppy.sh/beatmapsets/discussions/media-url?url={url}");
}
}
30 changes: 30 additions & 0 deletions osu.Game/Online/OsuOnlineStore.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using System;
using osu.Framework.IO.Stores;
using osu.Framework.Logging;

namespace osu.Game.Online
{
public class OsuOnlineStore : OnlineStore
{
private readonly string apiEndpointUrl;

public OsuOnlineStore(string apiEndpointUrl)
{
this.apiEndpointUrl = apiEndpointUrl;
}

protected override string GetLookupUrl(string url)

Check failure on line 19 in osu.Game/Online/OsuOnlineStore.cs

View workflow job for this annotation

GitHub Actions / Code Quality

'OsuOnlineStore.GetLookupUrl(string)': no suitable method found to override

Check failure on line 19 in osu.Game/Online/OsuOnlineStore.cs

View workflow job for this annotation

GitHub Actions / Code Quality

'OsuOnlineStore.GetLookupUrl(string)': no suitable method found to override

Check failure on line 19 in osu.Game/Online/OsuOnlineStore.cs

View workflow job for this annotation

GitHub Actions / Test (Windows, windows-latest, SingleThread)

'OsuOnlineStore.GetLookupUrl(string)': no suitable method found to override

Check failure on line 19 in osu.Game/Online/OsuOnlineStore.cs

View workflow job for this annotation

GitHub Actions / Test (Windows, windows-latest, SingleThread)

'OsuOnlineStore.GetLookupUrl(string)': no suitable method found to override

Check failure on line 19 in osu.Game/Online/OsuOnlineStore.cs

View workflow job for this annotation

GitHub Actions / Build only (iOS)

'OsuOnlineStore.GetLookupUrl(string)': no suitable method found to override

Check failure on line 19 in osu.Game/Online/OsuOnlineStore.cs

View workflow job for this annotation

GitHub Actions / Build only (iOS)

'OsuOnlineStore.GetLookupUrl(string)': no suitable method found to override

Check failure on line 19 in osu.Game/Online/OsuOnlineStore.cs

View workflow job for this annotation

GitHub Actions / Test (Windows, windows-latest, MultiThreaded)

'OsuOnlineStore.GetLookupUrl(string)': no suitable method found to override

Check failure on line 19 in osu.Game/Online/OsuOnlineStore.cs

View workflow job for this annotation

GitHub Actions / Test (Windows, windows-latest, MultiThreaded)

'OsuOnlineStore.GetLookupUrl(string)': no suitable method found to override

Check failure on line 19 in osu.Game/Online/OsuOnlineStore.cs

View workflow job for this annotation

GitHub Actions / Test (Linux, ubuntu-latest, SingleThread)

'OsuOnlineStore.GetLookupUrl(string)': no suitable method found to override

Check failure on line 19 in osu.Game/Online/OsuOnlineStore.cs

View workflow job for this annotation

GitHub Actions / Test (Linux, ubuntu-latest, SingleThread)

'OsuOnlineStore.GetLookupUrl(string)': no suitable method found to override

Check failure on line 19 in osu.Game/Online/OsuOnlineStore.cs

View workflow job for this annotation

GitHub Actions / Test (Linux, ubuntu-latest, MultiThreaded)

'OsuOnlineStore.GetLookupUrl(string)': no suitable method found to override

Check failure on line 19 in osu.Game/Online/OsuOnlineStore.cs

View workflow job for this annotation

GitHub Actions / Test (Linux, ubuntu-latest, MultiThreaded)

'OsuOnlineStore.GetLookupUrl(string)': no suitable method found to override
{
if (!Uri.TryCreate(url, UriKind.Absolute, out Uri? uri) || !uri.Host.EndsWith(@".ppy.sh", StringComparison.OrdinalIgnoreCase))
{
Logger.Log($@"Blocking resource lookup from external website: {url}", LoggingTarget.Network, LogLevel.Important);
return string.Empty;
}

return $@"{apiEndpointUrl}/beatmapsets/discussions/media-url?url={url}";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure if this is a big deal, but it feels wrong to me for lazer to be explicitly depending on a non-api route, even if it will still function properly in this case. and it should probably be updated to not have a uri specific to discussions 🤔

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not entirely sure what the concern is with a non-API route. As for the definition of the endpoint looking like it's specific to discussions, that's probably something to bring to @ppy/team-web, if action is deemed necessary and feasible.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I dunno about this.

I believe that endpoint should only be used for discussion links (are we somehow limiting this? could an abusive user be using this endpoint to create arbitrary proxied links?). If we're using it for more than this it should be something more generalised.

Can the store be used local to the discussions/comments system? And the default osu!-side online store just blocks all non-ppy resources?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds feasible, will update as such.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe that endpoint should only be used for discussion links (are we somehow limiting this? could an abusive user be using this endpoint to create arbitrary proxied links?)

https://i.ppy.sh/b5810b2de4431c96218200725bcdb795376c780f/68747470733a2f2f7570322e636c6179746f6e2e63632f6970707973682e706e67

I guess this is more of a web issue then...

Copy link
Collaborator

@bdach bdach Nov 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am so baffled as to how things got as far as this PR without talking about any of the concerns with using the route in question in such an undocumented manner first.

To me this either should have not been ever PR'd, or should have at least been preempted with a "is this even ok to do" sanity check.

Wholehearted agreement with @cl8n, and if anything I think that remark was too subtle. This 100% feels too broken to live and is susceptible to breakage in the future because no sane person would assume the discussions route would be used by client in contexts it is clearly not supposed to be used in.

The route either needs to be somehow generalised, or the entire burden of doing this should be offloaded to web by doing something like replacing the broken URLs with the proxied URLs on the server side so that the proxying is transparent to the client.

Copy link

@nanaya nanaya Nov 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm yeah, I'm thinking of changing the url to something more generic (ppy/osu-web#11686). Dunno if api will need its own specific url under /api but I suppose it can be added...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bdach I think you've extremely raised the tone up there, I will say I have chose to open this PR so that if it's alright then it's alright and if it's not then the points of why and whatever are discussed appropriately in here with easier access to the diff, period.

Copy link

@notbakaneko notbakaneko Nov 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll point out that the media-url proxying on discussions is mainly so someone can't just drop in an image for link tracking or fingerprinting users and only partly for caching if the host falls over. If there's a way to do that without proxying, that would be preferable.

Copy link

@nanaya nanaya Nov 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the proxying happens on all user posted images...

media-url thing is specifically because the markdown parsing happens on frontend so it doesn't have the camo key and can't just generate the actual proxied link like in backend.

it's currently only beatmapset discussions it happens on frontend (on web) so that's why it's been sitting there.

}
}
}
3 changes: 3 additions & 0 deletions osu.Game/OsuGame.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
using osu.Framework.Input.Bindings;
using osu.Framework.Input.Events;
using osu.Framework.Input.Handlers.Tablet;
using osu.Framework.IO.Stores;
using osu.Framework.Localisation;
using osu.Framework.Logging;
using osu.Framework.Platform;
Expand Down Expand Up @@ -819,6 +820,8 @@

protected override Container CreateScalingContainer() => new ScalingContainer(ScalingMode.Everything);

protected override OnlineStore CreateOnlineStore() => new OsuOnlineStore(CreateEndpoints().APIEndpointUrl);

Check failure on line 823 in osu.Game/OsuGame.cs

View workflow job for this annotation

GitHub Actions / Code Quality

'OsuGame.CreateOnlineStore()': no suitable method found to override

Check failure on line 823 in osu.Game/OsuGame.cs

View workflow job for this annotation

GitHub Actions / Code Quality

'OsuGame.CreateOnlineStore()': no suitable method found to override

Check failure on line 823 in osu.Game/OsuGame.cs

View workflow job for this annotation

GitHub Actions / Test (Windows, windows-latest, SingleThread)

'OsuGame.CreateOnlineStore()': no suitable method found to override

Check failure on line 823 in osu.Game/OsuGame.cs

View workflow job for this annotation

GitHub Actions / Test (Windows, windows-latest, SingleThread)

'OsuGame.CreateOnlineStore()': no suitable method found to override

Check failure on line 823 in osu.Game/OsuGame.cs

View workflow job for this annotation

GitHub Actions / Build only (iOS)

'OsuGame.CreateOnlineStore()': no suitable method found to override

Check failure on line 823 in osu.Game/OsuGame.cs

View workflow job for this annotation

GitHub Actions / Build only (iOS)

'OsuGame.CreateOnlineStore()': no suitable method found to override

Check failure on line 823 in osu.Game/OsuGame.cs

View workflow job for this annotation

GitHub Actions / Test (Windows, windows-latest, MultiThreaded)

'OsuGame.CreateOnlineStore()': no suitable method found to override

Check failure on line 823 in osu.Game/OsuGame.cs

View workflow job for this annotation

GitHub Actions / Test (Windows, windows-latest, MultiThreaded)

'OsuGame.CreateOnlineStore()': no suitable method found to override

Check failure on line 823 in osu.Game/OsuGame.cs

View workflow job for this annotation

GitHub Actions / Test (Linux, ubuntu-latest, SingleThread)

'OsuGame.CreateOnlineStore()': no suitable method found to override

Check failure on line 823 in osu.Game/OsuGame.cs

View workflow job for this annotation

GitHub Actions / Test (Linux, ubuntu-latest, SingleThread)

'OsuGame.CreateOnlineStore()': no suitable method found to override

Check failure on line 823 in osu.Game/OsuGame.cs

View workflow job for this annotation

GitHub Actions / Test (Linux, ubuntu-latest, MultiThreaded)

'OsuGame.CreateOnlineStore()': no suitable method found to override

Check failure on line 823 in osu.Game/OsuGame.cs

View workflow job for this annotation

GitHub Actions / Test (Linux, ubuntu-latest, MultiThreaded)

'OsuGame.CreateOnlineStore()': no suitable method found to override

#region Beatmap progression

private void beatmapChanged(ValueChangedEvent<WorkingBeatmap> beatmap)
Expand Down
2 changes: 1 addition & 1 deletion osu.Game/OsuGameBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ private void load(ReadableKeyCombinationProvider keyCombinationProvider, Framewo
dependencies.CacheAs(Storage);

var largeStore = new LargeTextureStore(Host.Renderer, Host.CreateTextureLoaderStore(new NamespacedResourceStore<byte[]>(Resources, @"Textures")));
largeStore.AddTextureSource(Host.CreateTextureLoaderStore(new OnlineStore()));
largeStore.AddTextureSource(Host.CreateTextureLoaderStore(CreateOnlineStore()));
dependencies.Cache(largeStore);

dependencies.CacheAs(LocalConfig);
Expand Down
Loading