New feature: display attached images as thumbnails below message body
| | |
| | | // path to imagemagick convert binary |
| | | $rcmail_config['im_convert_path'] = null; |
| | | |
| | | // Size of thumbnails from image attachments displayed below the message content. |
| | | // Note: whether images are displayed at all depends on the 'inline_images' option. |
| | | // Set to 0 to display images in full size. |
| | | $rcmail_config['image_thumbnail_size'] = 240; |
| | | |
| | | // maximum size of uploaded contact photos in pixel |
| | | $rcmail_config['contact_photo_size'] = 160; |
| | | |
| | |
| | | * @return string HTML code |
| | | * @see html::tag() |
| | | */ |
| | | public static function br() |
| | | public static function br($attrib = array()) |
| | | { |
| | | return self::tag('br'); |
| | | return self::tag('br', $attrib); |
| | | } |
| | | |
| | | /** |
| | |
| | | * |
| | | * @param int $size Max width/height size |
| | | * @param string $filename Output filename |
| | | * @param boolean $browser_compat Convert to image type displayable by any browser |
| | | * |
| | | * @return bool True on success, False on failure |
| | | * @return mixed Output type on success, False on failure |
| | | */ |
| | | public function resize($size, $filename = null) |
| | | public function resize($size, $filename = null, $browser_compat = false) |
| | | { |
| | | $result = false; |
| | | $rcube = rcube::get_instance(); |
| | |
| | | } |
| | | |
| | | $type = strtr($type, array("jpeg" => "jpg", "tiff" => "tif", "ps" => "eps", "ept" => "eps")); |
| | | $p['intype'] = $type; |
| | | |
| | | // convert to an image format every browser can display |
| | | if ($browser_compat && !in_array($type, array('jpg','gif','png'))) { |
| | | $type = 'jpg'; |
| | | } |
| | | |
| | | $p += array('type' => $type, 'types' => "bmp,eps,gif,jp2,jpg,png,svg,tif", 'quality' => 75); |
| | | $p['-opts'] = array('-resize' => $size.'>'); |
| | | $p['-opts'] = array('-resize' => $p['size'].'>'); |
| | | |
| | | if (in_array($type, explode(',', $p['types']))) { // Valid type? |
| | | $result = rcube::exec($convert . ' 2>&1 -flatten -auto-orient -colorspace RGB -quality {quality} {-opts} {in} {type}:{out}', $p); |
| | | $result = rcube::exec($convert . ' 2>&1 -flatten -auto-orient -colorspace RGB -quality {quality} {-opts} {intype}:{in} {type}:{out}', $p); |
| | | } |
| | | |
| | | if ($result === '') { |
| | | return true; |
| | | return $type; |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | if ($props['gd_type'] == IMAGETYPE_JPEG) { |
| | | $result = imagejpeg($image, $filename, 75); |
| | | $type = 'jpg'; |
| | | } |
| | | elseif($props['gd_type'] == IMAGETYPE_GIF) { |
| | | $result = imagegif($image, $filename); |
| | | $type = 'gid'; |
| | | } |
| | | elseif($props['gd_type'] == IMAGETYPE_PNG) { |
| | | $result = imagepng($image, $filename, 6, PNG_ALL_FILTERS); |
| | | $type = 'png'; |
| | | } |
| | | |
| | | if ($result) { |
| | | return true; |
| | | return $type; |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | // list images after mail body |
| | | if ($CONFIG['inline_images'] && !empty($MESSAGE->attachments)) { |
| | | if ($RCMAIL->config->get('inline_images', true) && !empty($MESSAGE->attachments)) { |
| | | $thumbnail_size = $RCMAIL->config->get('image_thumbnail_size', 240); |
| | | |
| | | foreach ($MESSAGE->attachments as $attach_prop) { |
| | | // skip inline images |
| | | if ($attach_prop->content_id && $attach_prop->disposition == 'inline') { |
| | |
| | | |
| | | // Content-Type: image/*... |
| | | if (rcmail_part_image_type($attach_prop)) { |
| | | $out .= html::tag('hr') . html::p(array('align' => "center"), |
| | | html::img(array( |
| | | 'src' => $MESSAGE->get_part_url($attach_prop->mime_id, true), |
| | | 'title' => $attach_prop->filename, |
| | | 'alt' => $attach_prop->filename, |
| | | ))); |
| | | // display thumbnails |
| | | if ($thumbnail_size) { |
| | | $show_link = array( |
| | | 'href' => $MESSAGE->get_part_url($attach_prop->mime_id, false), |
| | | 'onclick' => sprintf( |
| | | 'return %s.command(\'load-attachment\',{part:\'%s\', mimetype:\'%s\'},this)', |
| | | JS_OBJECT_NAME, |
| | | $attach_prop->mime_id, |
| | | rcmail_fix_mimetype($attach_prop->mimetype)) |
| | | ); |
| | | $out .= html::p('image-attachment', |
| | | html::a($show_link + array('class' => 'image-link'), |
| | | html::img(array( |
| | | 'class' => 'image-thumbnail', |
| | | 'src' => $MESSAGE->get_part_url($attach_prop->mime_id, true) . '&_thumb=1', |
| | | 'title' => $attach_prop->filename, |
| | | 'alt' => $attach_prop->filename, |
| | | 'style' => sprintf('max-width:%dpx; max-height:%dpx', $thumbnail_size, $thumbnail_size), |
| | | )) |
| | | ) . |
| | | html::span('image-filename', Q($attach_prop->filename)) . |
| | | html::span('image-filesize', Q($RCMAIL->show_bytes($attach_prop->size))) . |
| | | html::span('attachment-links', |
| | | html::a($show_link['href'] . '&_download=1', rcube_label('download')) |
| | | ) . |
| | | html::br(array('style' => 'clear:both')) |
| | | ); |
| | | } |
| | | else { |
| | | $out .= html::tag('fieldset', 'image-attachment', |
| | | html::tag('legend', 'image-filename', Q($attach_prop->filename)) . |
| | | html::p(array('align' => "center"), |
| | | html::img(array( |
| | | 'src' => $MESSAGE->get_part_url($attach_prop->mime_id, true), |
| | | 'title' => $attach_prop->filename, |
| | | 'alt' => $attach_prop->filename, |
| | | ))) |
| | | ); |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | exit; |
| | | } |
| | | |
| | | // render thumbnail of an image attachment |
| | | else if ($_GET['_thumb']) { |
| | | $pid = get_input_value('_part', RCUBE_INPUT_GET); |
| | | if ($part = $MESSAGE->mime_parts[$pid]) { |
| | | $thumbnail_size = $RCMAIL->config->get('image_thumbnail_size', 240); |
| | | $temp_dir = $RCMAIL->config->get('temp_dir'); |
| | | list(,$ext) = explode('/', $part->mimetype); |
| | | $cache_basename = $temp_dir . '/' . md5($MESSAGE->headers->messageID . $part->mime_id . ':' . $RCMAIL->user->ID . ':' . $thumbnail_size); |
| | | $cache_file = $cache_basename . '.' . $ext; |
| | | $mimetype = $part->mimetype; |
| | | |
| | | // render thumbnail image if not done yet |
| | | if (!is_file($cache_file)) { |
| | | $fp = fopen(($orig_name = $cache_basename . '.orig.' . $ext), 'w'); |
| | | $MESSAGE->get_part_content($part->mime_id, $fp); |
| | | fclose($fp); |
| | | |
| | | $image = new rcube_image($orig_name); |
| | | if ($imgtype = $image->resize($RCMAIL->config->get('image_thumbnail_size', 240), $cache_file, true)) { |
| | | $mimetype = 'image/' . $imgtype; |
| | | unlink($orig_name); |
| | | } |
| | | else { |
| | | rename($orig_name, $cache_file); |
| | | } |
| | | } |
| | | |
| | | if (is_file($cache_file)) { |
| | | header('Content-Type: ' . $mimetype); |
| | | readfile($cache_file); |
| | | } |
| | | } |
| | | |
| | | exit; |
| | | } |
| | | |
| | | else if (strlen($pid = get_input_value('_part', RCUBE_INPUT_GET))) { |
| | | |
| | | if ($part = $MESSAGE->mime_parts[$pid]) { |
| | |
| | | color: #333333; |
| | | } |
| | | |
| | | #messagebody fieldset.image-attachment { |
| | | border: 0; |
| | | border-top: 1px solid #ccc; |
| | | margin: 1em 1em 0 1em; |
| | | } |
| | | |
| | | #messagebody fieldset.image-attachment p > img |
| | | { |
| | | max-width: 80%; |
| | | } |
| | | |
| | | #messagebody legend.image-filename |
| | | { |
| | | color: #999; |
| | | font-size: 0.9em; |
| | | } |
| | | |
| | | #messagebody p.image-attachment |
| | | { |
| | | margin: 0 1em; |
| | | padding: 1em; |
| | | border-top: 1px solid #ccc; |
| | | } |
| | | |
| | | #messagebody p.image-attachment a.image-link |
| | | { |
| | | float: left; |
| | | margin-right: 2em; |
| | | min-width: 160px; |
| | | min-height: 60px; |
| | | text-align: center; |
| | | } |
| | | |
| | | #messagebody p.image-attachment .image-filename |
| | | { |
| | | display: block; |
| | | font-weight: bold; |
| | | line-height: 1.6em; |
| | | } |
| | | |
| | | #messagebody p.image-attachment .image-filesize |
| | | { |
| | | font-size: 11px; |
| | | padding-right: 1em; |
| | | } |
| | | |
| | | #messagebody p.image-attachment .attachment-links a |
| | | { |
| | | margin-right: 0.6em; |
| | | color: #cc0000; |
| | | font-size: 11px; |
| | | text-decoration: none; |
| | | } |
| | | |
| | | #messagebody p.image-attachment .attachment-links a:hover |
| | | { |
| | | text-decoration: underline; |
| | | } |
| | | |
| | | #openextwinlink |
| | | { |
| | | position: absolute; |
| | |
| | | border-bottom: 2px solid #f0f0f0; |
| | | } |
| | | |
| | | #messagebody > p > img { |
| | | #messagebody fieldset.image-attachment { |
| | | border: 0; |
| | | border-top: 1px solid #ccc; |
| | | margin-top: 1em; |
| | | } |
| | | |
| | | #messagebody fieldset.image-attachment p > img { |
| | | max-width: 80%; |
| | | } |
| | | |
| | | #messagebody legend.image-filename { |
| | | color: #999; |
| | | font-size: 0.9em; |
| | | margin: 0 1em; |
| | | } |
| | | |
| | | #messagebody p.image-attachment { |
| | | position: relative; |
| | | padding: 1em; |
| | | border-top: 1px solid #ccc; |
| | | } |
| | | |
| | | #messagebody p.image-attachment a.image-link { |
| | | float: left; |
| | | display: block; |
| | | margin-right: 2em; |
| | | min-width: 160px; |
| | | min-height: 60px; |
| | | text-align: center; |
| | | } |
| | | |
| | | #messagebody p.image-attachment .image-filename { |
| | | display: block; |
| | | font-weight: bold; |
| | | line-height: 1.6em; |
| | | } |
| | | |
| | | #messagebody p.image-attachment .image-filesize { |
| | | padding-right: 1em; |
| | | } |
| | | |
| | | #messagebody p.image-attachment .attachment-links a { |
| | | margin-right: 0.6em; |
| | | } |
| | | |
| | | #messagepartcontainer { |
| | | position: absolute; |
| | | top: 60px; |
| | |
| | | <title><roundcube:object name="pagetitle" /></title> |
| | | <roundcube:include file="/includes/links.html" /> |
| | | </head> |
| | | <body class="extwin"> |
| | | <body class="partwin"> |
| | | |
| | | <div id="header"> |
| | | <div id="topline"> |