Ladybird/AppKit: Sanitize user-provided URLs with LibWebView

This commit is contained in:
Timothy Flynn 2023-10-13 11:04:07 -04:00 committed by Tim Flynn
parent f023e37de7
commit aa5cd24c90
Notes: sideshowbarker 2024-07-17 02:37:08 +09:00
7 changed files with 58 additions and 95 deletions

View file

@ -9,6 +9,7 @@
#include <AK/Optional.h>
#include <AK/StringView.h>
#include <AK/URL.h>
#include <AK/Vector.h>
#include <LibWeb/CSS/PreferredColorScheme.h>
#include <LibWeb/HTML/ActivateTab.h>
#include <LibWebView/CookieJar.h>
@ -20,7 +21,8 @@
@interface ApplicationDelegate : NSObject <NSApplicationDelegate>
- (nullable instancetype)init:(Optional<URL>)initial_url
- (nullable instancetype)init:(Vector<URL>)initial_urls
newTabPageURL:(URL)new_tab_page_url
withCookieJar:(WebView::CookieJar)cookie_jar
webdriverContentIPCPath:(StringView)webdriver_content_ipc_path;

View file

@ -4,15 +4,12 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <BrowserSettings/Defaults.h>
#import <Application/ApplicationDelegate.h>
#import <LibWebView/UserAgent.h>
#import <UI/LadybirdWebView.h>
#import <UI/Tab.h>
#import <UI/TabController.h>
#import <Utilities/Conversions.h>
#import <Utilities/URL.h>
#if !__has_feature(objc_arc)
# error "This project requires ARC"
@ -20,7 +17,7 @@
@interface ApplicationDelegate ()
{
Optional<URL> m_initial_url;
Vector<URL> m_initial_urls;
URL m_new_tab_page_url;
// This will always be populated, but we cannot have a non-default constructible instance variable.
@ -47,7 +44,8 @@
@implementation ApplicationDelegate
- (instancetype)init:(Optional<URL>)initial_url
- (instancetype)init:(Vector<URL>)initial_urls
newTabPageURL:(URL)new_tab_page_url
withCookieJar:(WebView::CookieJar)cookie_jar
webdriverContentIPCPath:(StringView)webdriver_content_ipc_path
{
@ -66,8 +64,8 @@
self.managed_tabs = [[NSMutableArray alloc] init];
m_initial_url = move(initial_url);
m_new_tab_page_url = Ladybird::rebase_url_on_serenity_resource_root(Browser::default_new_tab_url);
m_initial_urls = move(initial_urls);
m_new_tab_page_url = move(new_tab_page_url);
m_cookie_jar = move(cookie_jar);
@ -481,9 +479,19 @@
- (void)applicationDidFinishLaunching:(NSNotification*)notification
{
[self createNewTab:m_initial_url
fromTab:nil
activateTab:Web::HTML::ActivateTab::Yes];
Tab* tab = nil;
for (auto const& url : m_initial_urls) {
auto activate_tab = tab == nil ? Web::HTML::ActivateTab::Yes : Web::HTML::ActivateTab::No;
auto* controller = [self createNewTab:url
fromTab:tab
activateTab:activate_tab];
tab = (Tab*)[controller window];
}
m_initial_urls.clear();
}
- (void)applicationWillTerminate:(NSNotification*)notification

View file

@ -5,6 +5,7 @@
*/
#include <LibWebView/History.h>
#include <LibWebView/URL.h>
#import <Application/ApplicationDelegate.h>
#import <LibWeb/Loader/ResourceLoader.h>
@ -13,7 +14,6 @@
#import <UI/Tab.h>
#import <UI/TabController.h>
#import <Utilities/Conversions.h>
#import <Utilities/URL.h>
#if !__has_feature(objc_arc)
# error "This project requires ARC"
@ -600,9 +600,11 @@ enum class IsHistoryNavigation {
return NO;
}
auto* url_string = [[text_view textStorage] string];
auto url = Ladybird::sanitize_url(url_string);
[self loadURL:url];
auto url_string = Ladybird::ns_string_to_string([[text_view textStorage] string]);
if (auto url = WebView::sanitize_url(url_string); url.has_value()) {
[self loadURL:*url];
}
[self.window makeFirstResponder:nil];
return YES;

View file

@ -1,21 +0,0 @@
/*
* Copyright (c) 2023, Tim Flynn <trflynn89@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/StringView.h>
#include <AK/URL.h>
#import <System/Cocoa.h>
namespace Ladybird {
URL sanitize_url(NSString*);
URL sanitize_url(StringView);
URL rebase_url_on_serenity_resource_root(StringView);
}

View file

@ -1,51 +0,0 @@
/*
* Copyright (c) 2023, Tim Flynn <trflynn89@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/DeprecatedString.h>
#include <AK/String.h>
#include <AK/Vector.h>
#include <Ladybird/Utilities.h>
#include <LibFileSystem/FileSystem.h>
#import <Utilities/URL.h>
namespace Ladybird {
URL sanitize_url(StringView url_string)
{
if (url_string.starts_with('/') || FileSystem::exists(url_string))
return MUST(String::formatted("file://{}", MUST(FileSystem::real_path(url_string))));
URL url { url_string };
if (!url.is_valid())
url = MUST(String::formatted("https://{}", url_string));
return url;
}
URL sanitize_url(NSString* url_string)
{
auto const* utf8 = [url_string UTF8String];
return sanitize_url({ utf8, strlen(utf8) });
}
URL rebase_url_on_serenity_resource_root(StringView url_string)
{
URL url { url_string };
Vector<DeprecatedString> paths;
for (auto segment : s_serenity_resource_root.split('/'))
paths.append(move(segment));
for (size_t i = 0; i < url.path_segment_count(); ++i)
paths.append(url.path_segment_at_index(i));
url.set_paths(move(paths));
return url;
}
}

View file

@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <BrowserSettings/Defaults.h>
#include <Ladybird/Utilities.h>
#include <LibCore/ArgsParser.h>
#include <LibCore/EventLoop.h>
@ -11,18 +12,34 @@
#include <LibMain/Main.h>
#include <LibWebView/CookieJar.h>
#include <LibWebView/Database.h>
#include <LibWebView/URL.h>
#import <Application/Application.h>
#import <Application/ApplicationDelegate.h>
#import <Application/EventLoopImplementation.h>
#import <UI/Tab.h>
#import <UI/TabController.h>
#import <Utilities/URL.h>
#if !__has_feature(objc_arc)
# error "This project requires ARC"
#endif
static URL rebase_url_on_serenity_resource_root(StringView url_string)
{
URL url { url_string };
Vector<DeprecatedString> paths;
for (auto segment : s_serenity_resource_root.split('/'))
paths.append(move(segment));
for (size_t i = 0; i < url.path_segment_count(); ++i)
paths.append(url.path_segment_at_index(i));
url.set_paths(move(paths));
return url;
}
ErrorOr<int> serenity_main(Main::Arguments arguments)
{
[Application sharedApplication];
@ -36,12 +53,12 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
Gfx::FontDatabase::set_default_font_query("Katica 10 400 0");
Gfx::FontDatabase::set_fixed_width_font_query("Csilla 10 400 0");
StringView url;
Vector<StringView> raw_urls;
StringView webdriver_content_ipc_path;
Core::ArgsParser args_parser;
args_parser.set_general_help("The Ladybird web browser");
args_parser.add_positional_argument(url, "URL to open", "url", Core::ArgsParser::Required::No);
args_parser.add_positional_argument(raw_urls, "URLs to open", "url", Core::ArgsParser::Required::No);
args_parser.add_option(webdriver_content_ipc_path, "Path to WebDriver IPC for WebContent", "webdriver-content-path", 0, "path", Core::ArgsParser::OptionHideMode::CommandLineAndMarkdown);
args_parser.parse(arguments);
@ -49,12 +66,19 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
auto database = TRY(WebView::Database::create(move(sql_server_paths)));
auto cookie_jar = TRY(WebView::CookieJar::create(*database));
Optional<URL> initial_url;
if (auto parsed_url = Ladybird::sanitize_url(url); parsed_url.is_valid()) {
initial_url = move(parsed_url);
auto new_tab_page_url = rebase_url_on_serenity_resource_root(Browser::default_new_tab_url);
Vector<URL> initial_urls;
for (auto const& raw_url : raw_urls) {
if (auto url = WebView::sanitize_url(raw_url); url.has_value())
initial_urls.append(url.release_value());
}
auto* delegate = [[ApplicationDelegate alloc] init:move(initial_url)
if (initial_urls.is_empty())
initial_urls.append(new_tab_page_url);
auto* delegate = [[ApplicationDelegate alloc] init:move(initial_urls)
newTabPageURL:move(new_tab_page_url)
withCookieJar:move(cookie_jar)
webdriverContentIPCPath:webdriver_content_ipc_path];

View file

@ -145,7 +145,6 @@ elseif (APPLE)
AppKit/UI/TabController.mm
AppKit/Utilities/Conversions.mm
AppKit/Utilities/NSString+Ladybird.mm
AppKit/Utilities/URL.mm
)
target_include_directories(ladybird PRIVATE AppKit)
target_link_libraries(ladybird PRIVATE ${COCOA_LIBRARY} LibUnicode)