gXbfB#) ۻbis_IIߪ ۻbis_IIߪ ۻbis_IIߪ ۻbis_II4&D.5;Aϳކ:}Wۻp%7ޔ_#5L@?ss\,fa\eChɛ+MMX,-\_[6Eq_uC^avh ->]+/Wg׿>|"d2D^1=]mwgFN5K]OElf5F \wgFN5K]OwgFN5K]OwgFN5K]O[_׮|S 6 iS&XVŰįwgFN5K]OwgFN5K]OwgFN5K]Oڵ0.{q[R xƬۉ։my4 S_>A6[E#*H%jgM%]𯄁5Q+RŞԲ&M.x ۻbis_IIߪ ۻbis_IIߪ ۻbis_II߄}BkH1yo@}{YK*Y8` |2`xs[E=c?i}Ns?蛓^8kWBxe(+ 2Oܓ DFe4b䀘QtL̰II#[loyhbՈ:Ŵ{|UZhYF <C!ЍQc-jΞְaOR -}Θ)`K[i8nW˃*eBbsZUp#S!SFa=E,ь']6{{/7PGINK(a7\p"CPV yG:!%Q8d(xHS Ex1SI/Qq@z(ߊ!R~BFW(SV$:fP"Bε s:Dߏ:eW/d8tnY`8E DjmϹ!Ӱ!W(jf . p_/1\#m=#0+wX,nj}"뗧?5h8sI]<'S z/Q^wg3&_45?rGN?Qy8b5?h4Cۛ&ѐ inu ڴ`J(f"nLEY n*Si]ņ8v:+fZN& ]:4֪t4E0[qd%5O32jE:)ZK0=/ژ=MP.C̏t˽ҺvnJ?."A^8SN^I[8go0(1iF<rn՚b)!qs#M3Il1/4}h[xƵzcܩpQ'& Hb#O}׿%%cl'3|QVD%P5E,[6\l,ڢz-KdBd ]Eر&5 kd:n=/(LUP+NÄ AԨ$^X:T$nͰru̢P`|:ˋW!x|F#Ӈ?E=;?8#{88w*MM=h$ƏLC%? .H/QLդG˄w÷HH߄'wl(B(ܣ_W2V iL=~(K5-"owah( 4Fiu;=pF#7L)O~7ٙpvђί}!R nǯ 2 薃8deWn;[G>2}p_oПp+_XTA!Z/Ш}`m.G0SeĪY*VnoqVqHȿT!'K`R$jĤ\K{Hv i'gu9L=et9u­>k^ 8’Ylt8rJ c>Cj0TDZYh0cjAcwm,}aʟnFWCl|F.jR!"HlMNEasqJMbయǂ/xc*xR /39f˩mHH)*/^Kd7A͐mail->user->ID . ':' . $thumbnail_size); $cache_file = rcube_utils::temp_filename($thumb_name, false, false); // render thumbnail image if not done yet if (!is_file($cache_file) && $attachment->body_to_file($orig_name = rcube_utils::temp_filename('attmnt'))) { $image = new rcube_image($orig_name); if ($imgtype = $image->resize($thumbnail_size, $cache_file, true)) { $mimetype = 'image/' . $imgtype; } else { // Resize failed, we need to check the file mimetype // So, we do not exit here, but goto generic file body handler below $_GET['_thumb'] = 0; $_REQUEST['_embed'] = 1; } } if (!empty($_GET['_thumb'])) { if (is_file($cache_file)) { $rcmail->output->future_expire_header(3600); header('Content-Type: ' . $mimetype); header('Content-Length: ' . filesize($cache_file)); readfile($cache_file); } exit; } } // Handle attachment body (display or download) if (empty($_GET['_thumb']) && $attachment->is_valid()) { // require CSRF protected url for downloads if (!empty($_GET['_download'])) { $rcmail->request_security_check(rcube_utils::INPUT_GET); } $extensions = rcube_mime::get_mime_extensions($mimetype); // compare file mimetype with the stated content-type headers and file extension to avoid malicious operations if (!empty($_REQUEST['_embed']) && empty($_REQUEST['_nocheck'])) { $file_extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION)); // 1. compare filename suffix with expected suffix derived from mimetype $valid = $file_extension && in_array($file_extension, (array)$extensions) || empty($extensions) || !empty($_REQUEST['_mimeclass']); // 2. detect the real mimetype of the attachment part and compare it with the stated mimetype and filename extension if ($valid || !$file_extension || $mimetype == 'application/octet-stream' || stripos($mimetype, 'text/') === 0) { $tmp_body = $attachment->body(2048); // detect message part mimetype $real_mimetype = rcube_mime::file_content_type($tmp_body, $filename, $mimetype, true, true); list($real_ctype_primary, $real_ctype_secondary) = explode('/', $real_mimetype); // accept text/plain with any extension if ($real_mimetype == 'text/plain' && self::mimetype_compare($real_mimetype, $mimetype)) { $valid_extension = true; } // ignore differences in text/* mimetypes. Filetype detection isn't very reliable here else if ($real_ctype_primary == 'text' && strpos($mimetype, $real_ctype_primary) === 0) { $real_mimetype = $mimetype; $valid_extension = true; } // ignore filename extension if mimeclass matches (#1489029) else if (!empty($_REQUEST['_mimeclass']) && $real_ctype_primary == $_REQUEST['_mimeclass']) { $valid_extension = true; } else { // get valid file extensions $extensions = rcube_mime::get_mime_extensions($real_mimetype); $valid_extension = !$file_extension || empty($extensions) || in_array($file_extension, (array)$extensions); } if ( // fix mimetype for files wrongly declared as octet-stream ($mimetype == 'application/octet-stream' && $valid_extension) // force detected mimetype for images (#8158) || (strpos($real_mimetype, 'image/') === 0) ) { $mimetype = $real_mimetype; } // "fix" real mimetype the same way the original is before comparison $real_mimetype = rcube_mime::fix_mimetype($real_mimetype); $valid = $valid_extension && self::mimetype_compare($real_mimetype, $mimetype); } else { $real_mimetype = $mimetype; } // show warning if validity checks failed if (!$valid) { // send blocked.gif for expected images if (empty($_REQUEST['_mimewarning']) && strpos($mimetype, 'image/') === 0) { // Do not cache. Failure might be the result of a misconfiguration, // thus real content should be returned once fixed. $content = self::get_resource_content('blocked.gif'); $rcmail->output->nocacheing_headers(); header("Content-Type: image/gif"); header("Content-Transfer-Encoding: binary"); header("Content-Length: " . strlen($content)); echo $content; } // html warning with a button to load the file anyway else { $rcmail->output = new rcmail_html_page(); $rcmail->output->register_inline_warning( $rcmail->gettext([ 'name' => 'attachmentvalidationerror', 'vars' => [ 'expected' => $mimetype . (!empty($file_extension) ? rcube::Q(" (.{$file_extension})") : ''), 'detected' => $real_mimetype . (!empty($extensions[0]) ? " (.{$extensions[0]})" : ''), ] ]), $rcmail->gettext('showanyway'), $rcmail->url(array_merge($_GET, ['_nocheck' => 1])) ); $rcmail->output->write(); } exit; } } // TIFF/WEBP to JPEG conversion, if needed foreach (['tiff', 'webp'] as $type) { $img_support = !empty($_SESSION['browser_caps']) && !empty($_SESSION['browser_caps'][$type]); if ( !empty($_REQUEST['_embed']) && !$img_support && $attachment->image_type() == 'image/' . $type && rcube_image::is_convertable('image/' . $type) ) { $convert2jpeg = true; $mimetype = 'image/jpeg'; break; } } // deliver part content if ($mimetype == 'text/html' && empty($_GET['_download'])) { $rcmail->output = new rcmail_html_page(); $out = ''; // Check if we have enough memory to handle the message in it // #1487424: we need up to 10x more memory than the body if (!rcube_utils::mem_check($attachment->size * 10)) { $rcmail->output->register_inline_warning( $rcmail->gettext('messagetoobig'), $rcmail->gettext('download'), $rcmail->url(array_merge($_GET, ['_download' => 1])) ); } else { // render HTML body $out = $attachment->html(); // insert remote objects warning into HTML body if (self::$REMOTE_OBJECTS) { $rcmail->output->register_inline_warning( $rcmail->gettext('blockedresources'), $rcmail->gettext('allow'), $rcmail->url(array_merge($_GET, ['_safe' => 1])) ); } } $rcmail->output->write($out); exit; } // add filename extension if missing if (!pathinfo($filename, PATHINFO_EXTENSION) && ($extensions = rcube_mime::get_mime_extensions($mimetype))) { $filename .= '.' . $extensions[0]; } $rcmail->output->download_headers($filename, [ 'type' => $mimetype, 'type_charset' => $attachment->charset, 'disposition' => !empty($_GET['_download']) ? 'attachment' : 'inline', ]); // handle tiff to jpeg conversion if (!empty($convert2jpeg)) { $file_path = rcube_utils::temp_filename('attmnt'); // convert image to jpeg and send it to the browser if ($attachment->body_to_file($file_path)) { $image = new rcube_image($file_path); if ($image->convert(rcube_image::TYPE_JPG, $file_path)) { header("Content-Length: " . filesize($file_path)); readfile($file_path); } } } else { $attachment->output($mimetype); } exit; } // if we arrive here, the requested part was not found header('HTTP/1.1 404 Not Found'); exit; } /** * Compares two mimetype strings with making sure that * e.g. image/bmp and image/x-ms-bmp are treated as equal. */ public static function mimetype_compare($type1, $type2) { $regexp = '~/(x-ms-|x-)~'; $type1 = preg_replace($regexp, '/', $type1); $type2 = preg_replace($regexp, '/', $type2); return $type1 === $type2; } /** * Attachment properties table */ public static function message_part_controls($attrib) { if (!self::$attachment->is_valid()) { return ''; } $rcmail = rcmail::get_instance(); $table = new html_table(['cols' => 2]); $table->add('title', rcube::Q($rcmail->gettext('namex')).':'); $table->add('header', rcube::Q(self::$attachment->filename)); $table->add('title', rcube::Q($rcmail->gettext('type')).':'); $table->add('header', rcube::Q(self::$attachment->mimetype)); $table->add('title', rcube::Q($rcmail->gettext('size')).':'); $table->add('header', rcube::Q(self::$attachment->size())); return $table->show($attrib); } /** * Attachment preview frame */ public static function message_part_frame($attrib) { $rcmail = rcmail::get_instance(); if ($rcmail->output->get_env('is_message')) { $url = [ 'task' => 'mail', 'action' => 'preview', 'uid' => $rcmail->output->get_env('uid'), 'mbox' => $rcmail->output->get_env('mailbox'), ]; } else { $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); } }