mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 02:07:35 +00:00
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.
This commit is contained in:
parent
b953588e0e
commit
1c78ff1b9f
2 changed files with 81 additions and 23 deletions
|
@ -2,6 +2,7 @@ serenity_component(
|
||||||
3DFileViewer
|
3DFileViewer
|
||||||
RECOMMENDED
|
RECOMMENDED
|
||||||
TARGETS 3DFileViewer
|
TARGETS 3DFileViewer
|
||||||
|
DEPENDS FileSystemAccessServer
|
||||||
)
|
)
|
||||||
|
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
|
@ -11,4 +12,4 @@ set(SOURCES
|
||||||
)
|
)
|
||||||
|
|
||||||
serenity_app(3DFileViewer ICON app-3d-file-viewer)
|
serenity_app(3DFileViewer ICON app-3d-file-viewer)
|
||||||
target_link_libraries(3DFileViewer LibGUI LibGL)
|
target_link_libraries(3DFileViewer LibGUI LibGL LibFileSystemAccessClient)
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include <LibCore/ElapsedTimer.h>
|
#include <LibCore/ElapsedTimer.h>
|
||||||
#include <LibCore/File.h>
|
#include <LibCore/File.h>
|
||||||
|
#include <LibFileSystemAccessClient/Client.h>
|
||||||
#include <LibGL/GL/gl.h>
|
#include <LibGL/GL/gl.h>
|
||||||
#include <LibGL/GLContext.h>
|
#include <LibGL/GLContext.h>
|
||||||
#include <LibGUI/ActionGroup.h>
|
#include <LibGUI/ActionGroup.h>
|
||||||
|
@ -33,7 +34,9 @@ class GLContextWidget final : public GUI::Frame {
|
||||||
C_OBJECT(GLContextWidget);
|
C_OBJECT(GLContextWidget);
|
||||||
|
|
||||||
public:
|
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_x() { m_rotate_x = !m_rotate_x; }
|
||||||
void toggle_rotate_y() { m_rotate_y = !m_rotate_y; }
|
void toggle_rotate_y() { m_rotate_y = !m_rotate_y; }
|
||||||
void toggle_rotate_z() { m_rotate_z = !m_rotate_z; }
|
void toggle_rotate_z() { m_rotate_z = !m_rotate_z; }
|
||||||
|
@ -191,26 +194,43 @@ void GLContextWidget::timer_event(Core::TimerEvent&)
|
||||||
m_cycles++;
|
m_cycles++;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLContextWidget::load(const String& filename)
|
bool GLContextWidget::load_path(String const& filename)
|
||||||
{
|
{
|
||||||
auto file = Core::File::construct(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);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!file->open(Core::OpenMode::ReadOnly) && file->error() != ENOENT) {
|
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);
|
GUI::MessageBox::show(window(), String::formatted("Opening \"{}\" failed: {}", filename, strerror(errno)), "Error", GUI::MessageBox::Type::Error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file->is_device()) {
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
GUI::MessageBox::show(window(), String::formatted("Opening \"{}\" failed: Can't open device files", filename), "Error", GUI::MessageBox::Type::Error);
|
||||||
return false;
|
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);
|
GUI::MessageBox::show(window(), String::formatted("Opening \"{}\" failed: Can't open directories", filename), "Error", GUI::MessageBox::Type::Error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -226,8 +246,21 @@ bool GLContextWidget::load(const String& filename)
|
||||||
builder.append(filename.split('.').at(0));
|
builder.append(filename.split('.').at(0));
|
||||||
builder.append(".bmp");
|
builder.append(".bmp");
|
||||||
|
|
||||||
|
String texture_path = Core::File::absolute_path(builder.string_view());
|
||||||
|
|
||||||
// Attempt to open the texture file from disk
|
// 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;
|
GLuint tex;
|
||||||
glGenTextures(1, &tex);
|
glGenTextures(1, &tex);
|
||||||
|
@ -249,11 +282,36 @@ int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
auto app = GUI::Application::construct(argc, 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");
|
perror("pledge");
|
||||||
return 1;
|
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
|
// Construct the main window
|
||||||
auto window = GUI::Window::construct();
|
auto window = GUI::Window::construct();
|
||||||
auto app_icon = GUI::Icon::default_icon("app-3d-file-viewer");
|
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& 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&) {
|
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;
|
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_separator();
|
||||||
file_menu.add_action(GUI::CommonActions::make_quit_action([&](auto&) {
|
file_menu.add_action(GUI::CommonActions::make_quit_action([&](auto&) {
|
||||||
|
@ -465,7 +519,10 @@ int main(int argc, char** argv)
|
||||||
window->show();
|
window->show();
|
||||||
|
|
||||||
auto filename = argc > 1 ? argv[1] : "/home/anon/Documents/3D Models/teapot.obj";
|
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();
|
return app->exec();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue