Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add orphan inline images below the message body #9326

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 12 additions & 7 deletions program/actions/mail/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -896,10 +896,11 @@ public static function check_safe($message)
* @param string $html HTML
* @param array $p Display parameters
* @param array $cid_replaces CID map replaces (inline images)
* @param array $used_cids List of CIDs appearing in message body
*
* @return string Clean HTML
*/
public static function wash_html($html, $p, $cid_replaces = [])
public static function wash_html($html, $p, $cid_replaces = [], &$used_cids = [])
{
$rcmail = rcmail::get_instance();

Expand Down Expand Up @@ -975,6 +976,7 @@ public static function wash_html($html, $p, $cid_replaces = [])

$html = $washer->wash($html);
self::$REMOTE_OBJECTS = $washer->extlinks;
$used_cids = $washer->get_used_cids();

return $html;
}
Expand All @@ -983,13 +985,14 @@ public static function wash_html($html, $p, $cid_replaces = [])
* Convert the given message part to proper HTML
* which can be displayed the message view
*
* @param string $body Message part body
* @param rcube_message_part $part Message part
* @param array $p Display parameters array
* @param string $body Message part body
* @param rcube_message_part $part Message part
* @param array $p Display parameters array
* @param array $used_cids List of CIDs appearing in message body
*
* @return string Formatted HTML string
*/
public static function print_body($body, $part, $p = [])
public static function print_body($body, $part, $p = [], &$used_cids = [])
{
$rcmail = rcmail::get_instance();

Expand All @@ -1006,6 +1009,8 @@ public static function print_body($body, $part, $p = [])
]
);

$used_cids = [];

// convert html to text/plain
if ($data['plain'] && ($data['type'] == 'html' || $data['type'] == 'enriched')) {
if ($data['type'] == 'enriched') {
Expand All @@ -1017,13 +1022,13 @@ public static function print_body($body, $part, $p = [])
}
// text/html
elseif ($data['type'] == 'html') {
$body = self::wash_html($data['body'], $data, $part->replaces);
$body = self::wash_html($data['body'], $data, $part->replaces, $used_cids);
$part->ctype_secondary = $data['type'];
}
// text/enriched
elseif ($data['type'] == 'enriched') {
$body = rcube_enriched::to_html($data['body']);
$body = self::wash_html($body, $data, $part->replaces);
$body = self::wash_html($body, $data, $part->replaces, $used_cids);
$part->ctype_secondary = 'html';
} else {
// assert plaintext
Expand Down
18 changes: 12 additions & 6 deletions program/actions/mail/show.php
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,8 @@ public static function message_body($attrib)
}
}

$used_cids = [];

if (!empty(self::$MESSAGE->parts)) {
foreach (self::$MESSAGE->parts as $part) {
if ($part->type == 'headers') {
Expand Down Expand Up @@ -715,7 +717,7 @@ public static function message_body($attrib)
];

// Parse the part content for display
$body = self::print_body($body, $part, $body_args);
$body = self::print_body($body, $part, $body_args, $used_cids);

// check if the message body is PGP encrypted
if (strpos($body, '-----BEGIN PGP MESSAGE-----') !== false) {
Expand Down Expand Up @@ -743,17 +745,21 @@ public static function message_body($attrib)
}
}

// list images after mail body
if ($rcmail->config->get('inline_images', true) && !empty(self::$MESSAGE->attachments)) {
// Fetch list of orphan inline parts
$orphan_parts = self::$MESSAGE->get_orphan_inline_parts($used_cids);
$attachments = array_merge(self::$MESSAGE->attachments, $orphan_parts);

// list images after mail body, if it's enabled or if message has orphan parts
if ((!empty($orphan_parts) || $rcmail->config->get('inline_images', true)) && !empty($attachments)) {
$thumbnail_size = $rcmail->config->get('image_thumbnail_size', 240);
$show_label = rcube::Q($rcmail->gettext('showattachment'));
$download_label = rcube::Q($rcmail->gettext('download'));

foreach (self::$MESSAGE->attachments as $attach_prop) {
foreach ($attachments as $attach_prop) {
// Content-Type: image/*...
if ($mimetype = self::part_image_type($attach_prop)) {
// Skip inline images
if (!self::is_attachment(self::$MESSAGE, $attach_prop)) {
// Skip inline images, unless they are not in the body
if (!self::is_attachment(self::$MESSAGE, $attach_prop) && !in_array($attach_prop, $orphan_parts)) {
continue;
}

Expand Down
35 changes: 35 additions & 0 deletions program/lib/Roundcube/rcube_message.php
Original file line number Diff line number Diff line change
Expand Up @@ -1030,6 +1030,41 @@ private function parse_structure($structure, $recursive = false)
}
}

/**
* Return list of orphan parts: inline images that are not included in the message HTML body
*
* @param array $used_cids List of used CIDs in body
*
* @return array
*/
public function get_orphan_inline_parts($used_cids)
{
$orphan_parts = [];

foreach ($this->inline_parts as $i => $part) {
$id = (string) $part->mime_id;

// The orphan part will not be returned if it is already in the attachments list
if (array_key_exists($id, $this->attachments)) {
continue;
}

if (isset($part->content_id)) {
$find = 'cid:' . $part->content_id;
} elseif (!empty($part->content_location)) {
$find = $part->content_location;
} else {
continue;
}

if (!in_array($find, $used_cids)) {
$orphan_parts[$id] = $part;
}
}

return $orphan_parts;
}

/**
* Fill a flat array with references to all parts, indexed by part numbers
*
Expand Down
15 changes: 15 additions & 0 deletions program/lib/Roundcube/rcube_washtml.php
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,9 @@ class rcube_washtml
/** @var string A prefix to be added to id/class/for attribute values */
private $_css_prefix;

/** @var array List of CIDs used in body */
private $_used_cids = [];

/** @var int Max nesting level */
private $max_nesting_level;

Expand Down Expand Up @@ -229,6 +232,16 @@ public function __construct($p = [])
}
}

/**
* Return list of CIDs that haven't been used in HTML
*
* @return array
*/
public function get_used_cids()
{
return array_keys($this->_used_cids);
}

/**
* Register a callback function for a certain tag
*
Expand Down Expand Up @@ -387,11 +400,13 @@ private function wash_attribs($node)
private function wash_uri($uri, $blocked_source = false, $is_image = true)
{
if (!empty($this->config['cid_map'][$uri])) {
$this->_used_cids[$uri] = true;
return $this->config['cid_map'][$uri];
}

$key = $this->config['base_url'] . $uri;
if (!empty($this->config['cid_map'][$key])) {
$this->_used_cids[$key] = true;
return $this->config['cid_map'][$key];
}

Expand Down