diff options
-rw-r--r-- | Userland/Applications/Help/MainWidget.cpp | 45 | ||||
-rw-r--r-- | Userland/Applications/Help/main.cpp | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibManual/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibManual/Path.cpp | 13 | ||||
-rw-r--r-- | Userland/Libraries/LibManual/Path.h | 17 | ||||
-rw-r--r-- | Userland/Libraries/LibManual/SectionNode.cpp | 3 |
6 files changed, 66 insertions, 14 deletions
diff --git a/Userland/Applications/Help/MainWidget.cpp b/Userland/Applications/Help/MainWidget.cpp index 1b42ea98ae..50a6eece2d 100644 --- a/Userland/Applications/Help/MainWidget.cpp +++ b/Userland/Applications/Help/MainWidget.cpp @@ -34,6 +34,7 @@ #include <LibMain/Main.h> #include <LibManual/Node.h> #include <LibManual/PageNode.h> +#include <LibManual/Path.h> #include <LibManual/SectionNode.h> #include <LibMarkdown/Document.h> @@ -98,19 +99,22 @@ MainWidget::MainWidget() m_web_view = find_descendant_of_type_named<WebView::OutOfProcessWebView>("web_view"); m_web_view->on_link_click = [this](auto& url, auto&, unsigned) { if (url.scheme() == "file") { - auto path = url.path(); - if (!path.starts_with("/usr/share/man/"sv)) { + auto path = LexicalPath { url.path() }; + if (!path.is_child_of(Manual::manual_base_path)) { open_external(url); return; } - auto browse_view_index = m_manual_model->index_from_path(path); + auto browse_view_index = m_manual_model->index_from_path(path.string()); if (browse_view_index.has_value()) { dbgln("Found path _{}_ in m_manual_model at index {}", path, browse_view_index.value()); m_browse_view->selection().set(browse_view_index.value()); return; } - m_history.push(path); - open_page(MUST(String::from_utf8(path))); + m_history.push(path.string()); + auto string_path = String::from_utf8(path.string()); + if (string_path.is_error()) + return; + open_page(string_path.value()); } else if (url.scheme() == "help") { if (url.host() == "man") { if (url.paths().size() != 2) { @@ -118,9 +122,24 @@ MainWidget::MainWidget() return; } auto const section = url.paths()[0]; - auto const page = url.paths()[1]; - auto const path = DeprecatedString::formatted("/usr/share/man/man{}/{}.md", section, page); + auto maybe_section_number = section.to_uint(); + if (!maybe_section_number.has_value()) { + dbgln("Bad section number '{}'", section); + return; + } + auto section_number = maybe_section_number.value(); + auto page = String::from_utf8(url.paths()[1]); + if (page.is_error()) + return; + + auto const page_object = try_make_ref_counted<Manual::PageNode>(Manual::sections[section_number - 1], page.release_value()); + if (page_object.is_error()) + return; + auto const maybe_path = page_object.value()->path(); + if (maybe_path.is_error()) + return; + auto path = maybe_path.value().to_deprecated_string(); m_history.push(path); open_url(URL::create_with_file_scheme(path, url.fragment())); } else { @@ -177,9 +196,9 @@ ErrorOr<void> MainWidget::set_start_page(StringView start_page, u32 section) { bool set_start_page = false; if (!start_page.is_null()) { - if (section != 0) { + if (section != 0 && section < Manual::number_of_sections) { // > Help [section] [name] - String path = TRY(String::formatted("/usr/share/man/man{}/{}.md", section, start_page)); + String const path = TRY(TRY(try_make_ref_counted<Manual::PageNode>(Manual::sections[section - 1], TRY(String::from_utf8(start_page))))->path()); m_history.push(path); open_page(path); set_start_page = true; @@ -192,8 +211,8 @@ ErrorOr<void> MainWidget::set_start_page(StringView start_page, u32 section) // > Help [query] // First, see if we can find the page by name - for (auto s : Manual::section_numbers) { - String path = TRY(String::formatted("/usr/share/man/man{}/{}.md", s, start_page)); + for (auto const& section : Manual::sections) { + String const path = TRY(TRY(try_make_ref_counted<Manual::PageNode>(section, TRY(String::from_utf8(start_page))))->path()); if (Core::File::exists(path)) { m_history.push(path); open_page(path); @@ -219,7 +238,7 @@ ErrorOr<void> MainWidget::set_start_page(StringView start_page, u32 section) ErrorOr<void> MainWidget::initialize_fallibles(GUI::Window& window) { - static String help_index_path = TRY(String::from_utf8("/usr/share/man/man7/Help-index.md"sv)); + static String const help_index_path = TRY(TRY(try_make_ref_counted<Manual::PageNode>(Manual::sections[7 - 1], TRY(String::from_utf8("Help-index"sv))))->path()); m_go_home_action = GUI::CommonActions::make_go_home_action([this](auto&) { m_history.push(help_index_path); open_page(help_index_path); @@ -240,7 +259,7 @@ ErrorOr<void> MainWidget::initialize_fallibles(GUI::Window& window) TRY(go_menu->try_add_action(*m_go_home_action)); auto help_menu = TRY(window.try_add_menu("&Help")); - static String help_page_path = TRY(String::from_utf8("/usr/share/man/man1/Help.md"sv)); + String const help_page_path = TRY(TRY(try_make_ref_counted<Manual::PageNode>(Manual::sections[1 - 1], TRY(String::from_utf8("Help"sv))))->path()); TRY(help_menu->try_add_action(GUI::CommonActions::make_command_palette_action(&window))); TRY(help_menu->try_add_action(GUI::Action::create("&Contents", { Key_F1 }, TRY(Gfx::Bitmap::try_load_from_file("/res/icons/16x16/filetype-unknown.png"sv)), [&](auto&) { open_page(help_page_path); diff --git a/Userland/Applications/Help/main.cpp b/Userland/Applications/Help/main.cpp index 52bd2ca23e..8c6da96286 100644 --- a/Userland/Applications/Help/main.cpp +++ b/Userland/Applications/Help/main.cpp @@ -33,6 +33,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments) TRY(Core::System::unveil("/sys/kernel/processes", "r")); TRY(Core::System::unveil("/res", "r")); + // We specifically don't want to load this path from a library, as that can be hijacked with LD_PRELOAD. TRY(Core::System::unveil("/usr/share/man", "r")); TRY(Core::System::unveil("/tmp/session/%sid/portal/filesystemaccess", "rw")); TRY(Core::System::unveil("/tmp/session/%sid/portal/launch", "rw")); diff --git a/Userland/Libraries/LibManual/CMakeLists.txt b/Userland/Libraries/LibManual/CMakeLists.txt index 13f0454acb..0bc2104a03 100644 --- a/Userland/Libraries/LibManual/CMakeLists.txt +++ b/Userland/Libraries/LibManual/CMakeLists.txt @@ -1,5 +1,6 @@ set(SOURCES PageNode.cpp + Path.cpp SectionNode.cpp ) diff --git a/Userland/Libraries/LibManual/Path.cpp b/Userland/Libraries/LibManual/Path.cpp new file mode 100644 index 0000000000..d6f09c9646 --- /dev/null +++ b/Userland/Libraries/LibManual/Path.cpp @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2022, kleines Filmröllchen <filmroellchen@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "Path.h" + +namespace Manual { + +LexicalPath const manual_base_path { "/usr/share/man" }; + +} diff --git a/Userland/Libraries/LibManual/Path.h b/Userland/Libraries/LibManual/Path.h new file mode 100644 index 0000000000..d9f45496f8 --- /dev/null +++ b/Userland/Libraries/LibManual/Path.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2022, the SerenityOS developers. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <AK/LexicalPath.h> + +namespace Manual { + +extern LexicalPath const manual_base_path; + +constexpr StringView const top_level_section_prefix = "man"sv; + +} diff --git a/Userland/Libraries/LibManual/SectionNode.cpp b/Userland/Libraries/LibManual/SectionNode.cpp index d7466e5054..deae4a482d 100644 --- a/Userland/Libraries/LibManual/SectionNode.cpp +++ b/Userland/Libraries/LibManual/SectionNode.cpp @@ -6,6 +6,7 @@ #include "SectionNode.h" #include "PageNode.h" +#include "Path.h" #include <AK/LexicalPath.h> #include <AK/QuickSort.h> #include <LibCore/DirIterator.h> @@ -14,7 +15,7 @@ namespace Manual { ErrorOr<String> SectionNode::path() const { - return String::formatted("/usr/share/man/man{}", m_section); + return String::formatted("{}/{}{}", manual_base_path, top_level_section_prefix, m_section); } ErrorOr<String> SectionNode::name() const |