diff --git a/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp b/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp index a2526951084..9dc2c156f2e 100644 --- a/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp +++ b/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp @@ -488,6 +488,39 @@ void CascadiaSettings::_validateAllSchemesExist() } } +static bool _validateSingleMediaResource(std::wstring_view resource) +{ + // URI + try + { + winrt::Windows::Foundation::Uri resourceUri{ resource }; + if (!resourceUri) + { + return false; + } + + const auto scheme{ resourceUri.SchemeName() }; + // Only file: URIs and ms-* URIs are permissible. http, https, ftp, gopher, etc. are not. + return til::equals_insensitive_ascii(scheme, L"file") || til::starts_with_insensitive_ascii(scheme, L"ms-"); + } + catch (...) + { + // fall through + } + + // Not a URI? Try a path. + try + { + std::filesystem::path resourcePath{ resource }; + return std::filesystem::exists(resourcePath); + } + catch (...) + { + // fall through + } + return false; +} + // Method Description: // - Ensures that all specified images resources (icons and background images) are valid URIs. // This does not verify that the icon or background image files are encoded as an image. @@ -501,24 +534,26 @@ void CascadiaSettings::_validateAllSchemesExist() // we find any invalid icon images. void CascadiaSettings::_validateMediaResources() { - auto invalidBackground{ false }; - auto invalidIcon{ false }; + auto warnInvalidBackground{ false }; + auto warnInvalidIcon{ false }; for (auto profile : _allProfiles) { if (const auto path = profile.DefaultAppearance().ExpandedBackgroundImagePath(); !path.empty()) { - // Attempt to convert the path to a URI, the ctor will throw if it's invalid/unparseable. - // This covers file paths on the machine, app data, URLs, and other resource paths. - try + if (!_validateSingleMediaResource(path)) { - winrt::Windows::Foundation::Uri imagePath{ path }; - } - catch (...) - { - // reset background image path - profile.DefaultAppearance().ClearBackgroundImagePath(); - invalidBackground = true; + if (profile.DefaultAppearance().HasBackgroundImagePath()) + { + // Only warn and delete if the user set this at the top level (do not warn for fragments, just clear it) + warnInvalidBackground = true; + profile.DefaultAppearance().ClearBackgroundImagePath(); + } + else + { + // reset background image path (set it to blank as an override for any fragment value) + profile.DefaultAppearance().BackgroundImagePath({}); + } } } @@ -526,17 +561,18 @@ void CascadiaSettings::_validateMediaResources() { if (const auto path = profile.UnfocusedAppearance().ExpandedBackgroundImagePath(); !path.empty()) { - // Attempt to convert the path to a URI, the ctor will throw if it's invalid/unparseable. - // This covers file paths on the machine, app data, URLs, and other resource paths. - try + if (!_validateSingleMediaResource(path)) { - winrt::Windows::Foundation::Uri imagePath{ path }; - } - catch (...) - { - // reset background image path - profile.UnfocusedAppearance().ClearBackgroundImagePath(); - invalidBackground = true; + if (profile.UnfocusedAppearance().HasBackgroundImagePath()) + { + warnInvalidBackground = true; + profile.UnfocusedAppearance().ClearBackgroundImagePath(); + } + else + { + // reset background image path (set it to blank as an override for any fragment value) + profile.UnfocusedAppearance().BackgroundImagePath({}); + } } } } @@ -552,24 +588,27 @@ void CascadiaSettings::_validateMediaResources() if (const auto icon = profile.Icon(); icon.size() > 2 && icon != HideIconValue) { const auto iconPath{ wil::ExpandEnvironmentStringsW(icon.c_str()) }; - try - { - winrt::Windows::Foundation::Uri imagePath{ iconPath }; - } - catch (...) + if (!_validateSingleMediaResource(iconPath)) { - profile.ClearIcon(); - invalidIcon = true; + if (profile.HasIcon()) + { + warnInvalidIcon = true; + profile.ClearIcon(); + } + else + { + profile.Icon({}); + } } } } - if (invalidBackground) + if (warnInvalidBackground) { _warnings.Append(SettingsLoadWarnings::InvalidBackgroundImage); } - if (invalidIcon) + if (warnInvalidIcon) { _warnings.Append(SettingsLoadWarnings::InvalidIcon); }