From f1c40c8aa9983f80331a94abf86bfb56caa2275e Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Tue, 19 Mar 2019 13:01:53 +0100 Subject: [PATCH] Fix bug where attachment preview didn't work with x_frame_options=deny (#6688) --- CHANGELOG | 1 + program/include/rcmail_output_html.php | 23 ++++++++++++++++++----- program/js/app.js | 3 ++- program/steps/mail/get.inc | 26 ++++++++++++++++---------- 4 files changed, 37 insertions(+), 16 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 2f219025d..e68ba6d30 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -10,6 +10,7 @@ CHANGELOG Roundcube Webmail - Fix so "Open in new window" consistently displays "external window" interface (#6659) - Fix bug where next row wasn't selected after deleting a collapsed thread (#6655) - Fix bug where external content (e.g. mail body) was passed to templates parsing code (#6640) +- Fix bug where attachment preview didn't work with x_frame_options=deny (#6688) RELEASE 1.4-rc1 --------------- diff --git a/program/include/rcmail_output_html.php b/program/include/rcmail_output_html.php index 33e08f597..e1d67d6c2 100644 --- a/program/include/rcmail_output_html.php +++ b/program/include/rcmail_output_html.php @@ -631,16 +631,29 @@ EOF; $this->add_script($commands, 'head_top'); } + $this->page_headers(); + + // call super method + $this->_write($template, $this->config->get('skin_path')); + } + + /** + * Send common page headers + * For now it only (re)sets X-Frame-Options when needed + */ + public function page_headers() + { + if (headers_sent()) { + return; + } + // allow (legal) iframe content to be loaded - $iframe = $this->framed || $this->env['framed']; - if (!headers_sent() && $iframe && ($xopt = $this->app->config->get('x_frame_options', 'sameorigin'))) { + $framed = $this->framed || $this->env['framed']; + if ($framed && ($xopt = $this->app->config->get('x_frame_options', 'sameorigin'))) { if (strtolower($xopt) === 'deny') { header('X-Frame-Options: sameorigin', true); } } - - // call super method - $this->_write($template, $this->config->get('skin_path')); } /** diff --git a/program/js/app.js b/program/js/app.js index 3b872525e..0fe8919be 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -1100,7 +1100,8 @@ function rcube_webmail() // open attachment in frame if it's of a supported mimetype if (command != 'download-attachment' && mimetype && this.env.mimetypes && $.inArray(mimetype, this.env.mimetypes) >= 0) { - if (this.open_window(this.url('get', $.extend({_frame: 1}, params)))) + // Note: We disable _framed for proper X-Frame-Options:deny support (#6688) + if (this.open_window(this.url('get', $.extend({_frame: 1, _framed: 0}, params)))) break; } diff --git a/program/steps/mail/get.inc b/program/steps/mail/get.inc index f42addfe1..c757dcb52 100644 --- a/program/steps/mail/get.inc +++ b/program/steps/mail/get.inc @@ -20,6 +20,8 @@ +-----------------------------------------------------------------------+ */ +// This resets X-Frame-Options for framed output (#6688) +$OUTPUT->page_headers(); // show loading page if (!empty($_GET['_preload'])) { @@ -316,20 +318,24 @@ function rcmail_message_part_frame($attrib) global $RCMAIL; if ($RCMAIL->output->get_env('is_message')) { - $attrib['src'] = $RCMAIL->url(array( - 'task' => 'mail', - 'action' => 'preview', - 'uid' => $RCMAIL->output->get_env('uid'), - 'mbox' => $RCMAIL->output->get_env('mailbox'), - 'framed' => 1, - )); + $url = array( + 'task' => 'mail', + 'action' => 'preview', + 'uid' => $RCMAIL->output->get_env('uid'), + 'mbox' => $RCMAIL->output->get_env('mailbox'), + ); } else { - $mimetype = $RCMAIL->output->get_env('mimetype'); - $frame_replace = strpos($mimetype, 'text/') === 0 ? '_embed=' : '_preload='; - $attrib['src'] = './?' . str_replace('_frame=', $frame_replace, $_SERVER['QUERY_STRING']); + $mimetype = $RCMAIL->output->get_env('mimetype'); + $url = $_GET; + $url[strpos($mimetype, 'text/') === 0 ? '_embed' : '_preload'] = 1; + unset($url['_frame']); } + $url['_framed'] = 1; // For proper X-Frame-Options:deny handling + + $attrib['src'] = $RCMAIL->url($url); + $RCMAIL->output->add_gui_object('messagepartframe', $attrib['id']); return html::iframe($attrib);