From 9fd7f7da34c05c690b91299be60a7c4407a6910b Mon Sep 17 00:00:00 2001 From: Veloman Yunkan Date: Mon, 10 Apr 2023 16:34:28 +0400 Subject: [PATCH] Really enable Chromium to display PDFs in the viewer iframe The previous "fix" (merged PR #924) was buggy. It not only didn't work in Chromium v90, but in more recent versions too. I verified that this fix works in Firefox (v111) and Chromium (v90): - Attempts by the ZIM content to break out of the viewer iframe are blocked. - PDFs are displayed in the viewer. --- src/server/internalServer.cpp | 30 ++++++++++++++++++++++++++++++ src/server/response.cpp | 6 ------ static/viewer.html | 2 +- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/server/internalServer.cpp b/src/server/internalServer.cpp index 52f32be76..67ddb987d 100644 --- a/src/server/internalServer.cpp +++ b/src/server/internalServer.cpp @@ -1123,6 +1123,29 @@ ParameterizedMessage suggestSearchMsg(const std::string& searchURL, const std::s }); } +/////////////////////////////////////////////////////////////////////////////// +// The content security policy below is set on responses to the /content +// endpoint in order to prevent the ZIM content from interfering with the +// viewer (e.g. breaking out of the viewer iframe by performing top-level +// navigation). +const std::string CONTENT_CSP_HEADER = + "default-src 'self' " + "data: " + "blob: " + "about: " + "'unsafe-inline' " + "'unsafe-eval'; " + + "sandbox allow-scripts " + "allow-same-origin " + "allow-modals " + "allow-popups " + "allow-forms " + "allow-downloads;"; + +// End of content security policy +/////////////////////////////////////////////////////////////////////////////// + } // unnamed namespace std::unique_ptr @@ -1184,6 +1207,13 @@ std::unique_ptr InternalServer::handle_content(const RequestContext& r auto response = ItemResponse::build(*this, request, entry.getItem()); response->set_etag_body(archiveUuid); + if ( !startsWith(entry.getItem().getMimetype(), "application/pdf") ) { + // NOTE: Content security policy is not applied to PDF content so that + // NOTE: it can be displayed in the viewer in Chromium-based browsers. + response->add_header("Content-Security-Policy", CONTENT_CSP_HEADER); + response->add_header("Referrer-Policy", "no-referrer"); + } + if (m_verbose.load()) { printf("Found %s\n", entry.getPath().c_str()); printf("mimeType: %s\n", entry.getItem(true).getMimetype().c_str()); diff --git a/src/server/response.cpp b/src/server/response.cpp index 6b4b9fcfc..db20a2fb4 100644 --- a/src/server/response.cpp +++ b/src/server/response.cpp @@ -412,12 +412,6 @@ ContentResponse::ContentResponse(const std::string& root, bool verbose, const st m_mimeType(mimetype) { add_header(MHD_HTTP_HEADER_CONTENT_TYPE, m_mimeType); - if ( !startsWith(m_mimeType, "application/pdf") ) { - add_header("Content-Security-Policy", - "default-src 'self' data: blob: about: chrome-extension: 'unsafe-inline' 'unsafe-eval'; " - "sandbox allow-scripts allow-same-origin allow-modals allow-popups allow-forms allow-downloads;"); - add_header("Referrer-Policy", "no-referrer"); - } } std::unique_ptr ContentResponse::build( diff --git a/static/viewer.html b/static/viewer.html index b9499fc54..fc49f6ac7 100644 --- a/static/viewer.html +++ b/static/viewer.html @@ -4,7 +4,7 @@ ZIM Viewer