summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimothy <timmot@users.noreply.github.com>2021-08-18 23:33:09 +1000
committerAndreas Kling <kling@serenityos.org>2021-09-09 02:34:29 +0200
commit1c78ff1b9fbecf12d02f9435b6b5b963d7db808f (patch)
tree368ac03ea9ddcc3c22bd29d02dbe50428eab5b6f
parentb953588e0e5ff2118954af064cc874d3996bacb6 (diff)
downloadserenity-1c78ff1b9fbecf12d02f9435b6b5b963d7db808f.zip
3DFileViewer: Use unveil and FileSystemAccessServer
This will restrict 3DFileViewer's access to the file system. 3DFileViewer loads a texture based on the path of the model loaded, this will request access to the texture file before loading.
-rw-r--r--Userland/Applications/3DFileViewer/CMakeLists.txt3
-rw-r--r--Userland/Applications/3DFileViewer/main.cpp97
2 files changed, 79 insertions, 21 deletions
diff --git a/Userland/Applications/3DFileViewer/CMakeLists.txt b/Userland/Applications/3DFileViewer/CMakeLists.txt
index 88abb914d6..1a9b2c0233 100644
--- a/Userland/Applications/3DFileViewer/CMakeLists.txt
+++ b/Userland/Applications/3DFileViewer/CMakeLists.txt
@@ -2,6 +2,7 @@ serenity_component(
3DFileViewer
RECOMMENDED
TARGETS 3DFileViewer
+ DEPENDS FileSystemAccessServer
)
set(SOURCES
@@ -11,4 +12,4 @@ set(SOURCES
)
serenity_app(3DFileViewer ICON app-3d-file-viewer)
-target_link_libraries(3DFileViewer LibGUI LibGL)
+target_link_libraries(3DFileViewer LibGUI LibGL LibFileSystemAccessClient)
diff --git a/Userland/Applications/3DFileViewer/main.cpp b/Userland/Applications/3DFileViewer/main.cpp
index a3bae3e2d4..d1ae0549ea 100644
--- a/Userland/Applications/3DFileViewer/main.cpp
+++ b/Userland/Applications/3DFileViewer/main.cpp
@@ -6,6 +6,7 @@
#include <LibCore/ElapsedTimer.h>
#include <LibCore/File.h>
+#include <LibFileSystemAccessClient/Client.h>
#include <LibGL/GL/gl.h>
#include <LibGL/GLContext.h>
#include <LibGUI/ActionGroup.h>
@@ -33,7 +34,9 @@ class GLContextWidget final : public GUI::Frame {
C_OBJECT(GLContextWidget);
public:
- bool load(const String& fname);
+ bool load_path(String const& fname);
+ bool load_fd_and_close(int fd, String const& fname);
+ bool load_file(Core::File& file, String const& fname);
void toggle_rotate_x() { m_rotate_x = !m_rotate_x; }
void toggle_rotate_y() { m_rotate_y = !m_rotate_y; }
void toggle_rotate_z() { m_rotate_z = !m_rotate_z; }
@@ -191,26 +194,43 @@ void GLContextWidget::timer_event(Core::TimerEvent&)
m_cycles++;
}
-bool GLContextWidget::load(const String& filename)
+bool GLContextWidget::load_path(String const& filename)
{
auto file = Core::File::construct(filename);
- if (!file->filename().ends_with(".obj")) {
- GUI::MessageBox::show(window(), String::formatted("Opening \"{}\" failed: invalid file type", filename), "Error", GUI::MessageBox::Type::Error);
+ if (!file->open(Core::OpenMode::ReadOnly) && file->error() != ENOENT) {
+ GUI::MessageBox::show(window(), String::formatted("Opening \"{}\" failed: {}", filename, strerror(errno)), "Error", GUI::MessageBox::Type::Error);
return false;
}
- if (!file->open(Core::OpenMode::ReadOnly) && file->error() != ENOENT) {
+ return load_file(file, filename);
+}
+
+bool GLContextWidget::load_fd_and_close(int fd, String const& filename)
+{
+ auto file = Core::File::construct();
+
+ if (!file->open(fd, Core::OpenMode::ReadOnly, Core::File::ShouldCloseFileDescriptor::Yes) && file->error() != ENOENT) {
GUI::MessageBox::show(window(), String::formatted("Opening \"{}\" failed: {}", filename, strerror(errno)), "Error", GUI::MessageBox::Type::Error);
return false;
}
- if (file->is_device()) {
+ return load_file(file, filename);
+}
+
+bool GLContextWidget::load_file(Core::File& file, String const& filename)
+{
+ if (!filename.ends_with(".obj")) {
+ GUI::MessageBox::show(window(), String::formatted("Opening \"{}\" failed: invalid file type", filename), "Error", GUI::MessageBox::Type::Error);
+ return false;
+ }
+
+ if (file.is_device()) {
GUI::MessageBox::show(window(), String::formatted("Opening \"{}\" failed: Can't open device files", filename), "Error", GUI::MessageBox::Type::Error);
return false;
}
- if (file->is_directory()) {
+ if (file.is_directory()) {
GUI::MessageBox::show(window(), String::formatted("Opening \"{}\" failed: Can't open directories", filename), "Error", GUI::MessageBox::Type::Error);
return false;
}
@@ -226,8 +246,21 @@ bool GLContextWidget::load(const String& filename)
builder.append(filename.split('.').at(0));
builder.append(".bmp");
+ String texture_path = Core::File::absolute_path(builder.string_view());
+
// Attempt to open the texture file from disk
- auto texture_image = Gfx::Bitmap::try_load_from_file(builder.string_view());
+ RefPtr<Gfx::Bitmap> texture_image;
+ if (Core::File::exists(texture_path)) {
+ texture_image = Gfx::Bitmap::try_load_from_file(texture_path);
+ } else {
+ auto result = FileSystemAccessClient::Client::the().request_file(window()->window_id(), builder.string_view(), Core::OpenMode::ReadOnly);
+
+ if (result.error != 0) {
+ return false;
+ }
+
+ texture_image = Gfx::Bitmap::try_load_from_fd_and_close(*result.fd, *result.chosen_file);
+ }
GLuint tex;
glGenTextures(1, &tex);
@@ -249,11 +282,36 @@ int main(int argc, char** argv)
{
auto app = GUI::Application::construct(argc, argv);
- if (pledge("stdio thread recvfd sendfd rpath", nullptr) < 0) {
+ if (pledge("stdio thread recvfd sendfd rpath unix", nullptr) < 0) {
perror("pledge");
return 1;
}
+ if (unveil("/tmp/portal/filesystemaccess", "rw") < 0) {
+ perror("unveil");
+ return 1;
+ }
+
+ if (unveil("/home/anon/Documents/3D Models/teapot.obj", "r") < 0) {
+ perror("unveil");
+ return 1;
+ }
+
+ if (unveil("/home/anon/Documents/3D Models/teapot.bmp", "r") < 0) {
+ perror("unveil");
+ return 1;
+ }
+
+ if (unveil("/res", "r") < 0) {
+ perror("unveil");
+ return 1;
+ }
+
+ if (unveil(nullptr, nullptr) < 0) {
+ perror("unveil");
+ return 1;
+ }
+
// Construct the main window
auto window = GUI::Window::construct();
auto app_icon = GUI::Icon::default_icon("app-3d-file-viewer");
@@ -273,20 +331,16 @@ int main(int argc, char** argv)
auto& file_menu = window->add_menu("&File");
- auto load_model = [&](StringView const& filename) {
- if (widget.load(filename)) {
- auto canonical_path = Core::File::real_path_for(filename);
- window->set_title(String::formatted("{} - 3D File Viewer", canonical_path));
- }
- };
-
file_menu.add_action(GUI::CommonActions::make_open_action([&](auto&) {
- Optional<String> open_path = GUI::FilePicker::get_open_filepath(window);
+ auto result = FileSystemAccessClient::Client::the().open_file(window->window_id());
- if (!open_path.has_value())
+ if (result.error != 0)
return;
- load_model(open_path.value());
+ if (widget.load_fd_and_close(*result.fd, *result.chosen_file)) {
+ auto canonical_path = Core::File::absolute_path(*result.chosen_file);
+ window->set_title(String::formatted("{} - 3D File Viewer", canonical_path));
+ }
}));
file_menu.add_separator();
file_menu.add_action(GUI::CommonActions::make_quit_action([&](auto&) {
@@ -465,7 +519,10 @@ int main(int argc, char** argv)
window->show();
auto filename = argc > 1 ? argv[1] : "/home/anon/Documents/3D Models/teapot.obj";
- load_model(filename);
+ if (widget.load_path(filename)) {
+ auto canonical_path = Core::File::absolute_path(filename);
+ window->set_title(String::formatted("{} - 3D File Viewer", canonical_path));
+ }
return app->exec();
}