Changeset de68765 in github
- Timestamp:
- May 31, 2012 4:42:46 AM (12 months ago)
- Branches:
- master, HEAD, pdo
- Children:
- 8ce6024
- Parents:
- 8c16ea9 (diff), a71039d (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent. - Files:
-
- 1 added
- 7 edited
-
CHANGELOG (modified) (1 diff)
-
program/blank.tif (added)
-
program/include/rcube_image.php (modified) (6 diffs)
-
program/js/app.js (modified) (13 diffs)
-
program/steps/mail/func.inc (modified) (4 diffs)
-
program/steps/mail/get.inc (modified) (3 diffs)
-
program/steps/mail/show.inc (modified) (2 diffs)
-
skins/larry/ui.js (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
CHANGELOG
r8c16ea9 rde68765 3 3 4 4 - Don't let error message popups cover the login form (#1488500) 5 - Display Tiff as Jpeg in browsers without Tiff support (#1488452) 6 - Don't display Pdf/Tiff/Flash attachments inline without browser support (#1488452, #1487929) 5 7 - Don't show errors when moving contacts into groups they are already in (#1488493) 6 8 - Make folders with unread messages in subfolders bold again (#1486793) -
program/include/rcube_image.php
r041c93c r19cc5b9 14 14 | | 15 15 | PURPOSE: | 16 | Image resizer |16 | Image resizer and converter | 17 17 | | 18 18 +-----------------------------------------------------------------------+ … … 25 25 { 26 26 private $image_file; 27 28 const TYPE_GIF = 1; 29 const TYPE_JPG = 2; 30 const TYPE_PNG = 3; 31 const TYPE_TIF = 4; 32 33 public static $extensions = array( 34 self::TYPE_GIF => 'gif', 35 self::TYPE_JPG => 'jpg', 36 self::TYPE_PNG => 'png', 37 self::TYPE_TIF => 'tif', 38 ); 39 27 40 28 41 function __construct($filename) … … 67 80 * @param string $filename Output filename 68 81 * 69 * @return Success of convert as true/false82 * @return bool True on success, False on failure 70 83 */ 71 84 public function resize($size, $filename = null) … … 96 109 97 110 if (in_array($type, explode(',', $p['types']))) { // Valid type? 98 $result = rcube::exec($convert . ' 2>&1 -flatten -auto-orient -colorspace RGB -quality {quality} {-opts} {in} {type}:{out}', $p) === '';99 } 100 101 if ($result ) {111 $result = rcube::exec($convert . ' 2>&1 -flatten -auto-orient -colorspace RGB -quality {quality} {-opts} {in} {type}:{out}', $p); 112 } 113 114 if ($result === '') { 102 115 return true; 103 116 } … … 149 162 } 150 163 164 // @TODO: print error to the log? 165 return false; 166 } 167 168 /** 169 * Convert image to a given type 170 * 171 * @param int $type Destination file type (see class constants) 172 * @param string $filename Output filename (if empty, original file will be used 173 * and filename extension will be modified) 174 * 175 * @return bool True on success, False on failure 176 */ 177 public function convert($type, $filename = null) 178 { 179 $rcube = rcube::get_instance(); 180 $convert = $rcube->config->get('im_convert_path', false); 181 182 if (!$filename) { 183 $filename = $this->image_file; 184 185 // modify extension 186 if ($extension = self::$extensions[$type]) { 187 $filename = preg_replace('/\.[^.]+$/', '', $filename) . '.' . $extension; 188 } 189 } 190 191 // use ImageMagick 192 if ($convert) { 193 $p['in'] = $this->image_file; 194 $p['out'] = $filename; 195 $p['type'] = self::$extensions[$type]; 196 197 $result = rcube::exec($convert . ' 2>&1 -colorspace RGB -quality 75 {in} {type}:{out}', $p); 198 199 if ($result === '') { 200 return true; 201 } 202 } 203 204 // use GD extension (TIFF isn't supported) 205 $props = $this->props(); 206 $gd_types = array(IMAGETYPE_JPEG, IMAGETYPE_GIF, IMAGETYPE_PNG); 207 208 if ($props['gd_type'] && in_array($props['gd_type'], $gd_types)) { 209 if ($props['gd_type'] == IMAGETYPE_JPEG) { 210 $image = imagecreatefromjpeg($this->image_file); 211 } 212 else if ($props['gd_type'] == IMAGETYPE_GIF) { 213 $image = imagecreatefromgif($this->image_file); 214 } 215 else if ($props['gd_type'] == IMAGETYPE_PNG) { 216 $image = imagecreatefrompng($this->image_file); 217 } 218 219 if ($type == self::TYPE_JPG) { 220 $result = imagejpeg($image, $filename, 75); 221 } 222 else if ($type == self::TYPE_GIF) { 223 $result = imagegif($image, $filename); 224 } 225 else if ($type == self::TYPE_PNG) { 226 $result = imagepng($image, $filename, 6, PNG_ALL_FILTERS); 227 } 228 } 151 229 152 230 // @TODO: print error to the log? … … 170 248 } 171 249 } 250 172 251 } -
program/js/app.js
r041c93c ra71039d 308 308 } 309 309 310 // detect browser capabilities 311 if (!this.is_framed()) 312 this.browser_capabilities_check(); 313 310 314 break; 311 315 … … 628 632 if (uid && (!this.env.uid || uid != this.env.uid)) { 629 633 if (this.env.mailbox == this.env.drafts_mailbox) 630 this.goto_url('compose', '_draft_uid='+uid+'&_mbox='+urlencode(this.env.mailbox), true);634 this.goto_url('compose', { _draft_uid: uid, _mbox: this.env.mailbox }, true); 631 635 else 632 636 this.show_message(uid); … … 650 654 651 655 case 'edit': 652 if (this.task =='addressbook' && (cid = this.get_single_cid()))656 if (this.task == 'addressbook' && (cid = this.get_single_cid())) 653 657 this.load_contact(cid, 'edit'); 654 else if (this.task =='settings' && props)658 else if (this.task == 'settings' && props) 655 659 this.load_identity(props, 'edit-identity'); 656 else if (this.task=='mail' && (cid = this.get_single_uid())) { 657 url = (this.env.mailbox == this.env.drafts_mailbox) ? '_draft_uid=' : '_uid='; 658 this.goto_url('compose', url+cid+'&_mbox='+urlencode(this.env.mailbox), true); 660 else if (this.task == 'mail' && (cid = this.get_single_uid())) { 661 url = { _mbox: this.env.mailbox }; 662 url[this.env.mailbox == this.env.drafts_mailbox ? '_draft_uid' : '_uid'] = cid; 663 this.goto_url('compose', url, true); 659 664 } 660 665 break; … … 981 986 case 'reply': 982 987 if (uid = this.get_single_uid()) { 983 url = '_reply_uid='+uid+'&_mbox='+urlencode(this.env.mailbox);988 url = {_reply_uid: uid, _mbox: this.env.mailbox}; 984 989 if (command == 'reply-all') 985 990 // do reply-list, when list is detected and popup menu wasn't used 986 url += '&_all=' +(!props && this.commands['reply-list'] ? 'list' : 'all');991 url._all = (!props && this.commands['reply-list'] ? 'list' : 'all'); 987 992 else if (command == 'reply-list') 988 url += '&_all=list';993 url._all = list; 989 994 990 995 this.goto_url('compose', url, true); … … 995 1000 case 'forward': 996 1001 if (uid = this.get_single_uid()) { 997 url = '_forward_uid='+uid+'&_mbox='+urlencode(this.env.mailbox);1002 url = { _forward_uid: uid, _mbox: this.env.mailbox }; 998 1003 if (command == 'forward-attachment' || (!props && this.env.forward_attachment)) 999 url += '&_attachment=1';1004 url._attachment = 1; 1000 1005 this.goto_url('compose', url, true); 1001 1006 } … … 1023 1028 case 'download': 1024 1029 if (uid = this.get_single_uid()) 1025 this.goto_url('viewsource', '&_uid='+uid+'&_mbox='+urlencode(this.env.mailbox)+'&_save=1');1030 this.goto_url('viewsource', { _uid: uid, _mbox: this.env.mailbox, _save: 1 }); 1026 1031 break; 1027 1032 … … 1076 1081 case 'export': 1077 1082 if (this.contact_list.rowcount > 0) { 1078 this.goto_url('export', { _source: this.env.source, _gid:this.env.group, _search:this.env.search_request });1083 this.goto_url('export', { _source: this.env.source, _gid: this.env.group, _search: this.env.search_request }); 1079 1084 } 1080 1085 break; … … 1577 1582 var uid = list.get_single_selection(); 1578 1583 if (uid && this.env.mailbox == this.env.drafts_mailbox) 1579 this.goto_url('compose', '_draft_uid='+uid+'&_mbox='+urlencode(this.env.mailbox), true);1584 this.goto_url('compose', { _draft_uid: uid, _mbox: this.env.mailbox }, true); 1580 1585 else if (uid) 1581 1586 this.show_message(uid, false, false); … … 1944 1949 url += '&_search='+this.env.search_request; 1945 1950 1946 if (action == 'preview' && String(target.location.href).indexOf(url) >= 0) 1951 // add browser capabilities, so we can properly handle attachments 1952 url += '&_caps='+urlencode(this.browser_capabilities()); 1953 1954 if (preview && String(target.location.href).indexOf(url) >= 0) 1947 1955 this.show_contentframe(true); 1948 1956 else { … … 1950 1958 1951 1959 // mark as read and change mbox unread counter 1952 if ( action == 'preview'&& this.message_list && this.message_list.rows[id] && this.message_list.rows[id].unread && this.env.preview_pane_mark_read >= 0) {1960 if (preview && this.message_list && this.message_list.rows[id] && this.message_list.rows[id].unread && this.env.preview_pane_mark_read >= 0) { 1953 1961 this.preview_read_timer = setTimeout(function() { 1954 1962 ref.set_message(id, 'unread', false); … … 3797 3805 3798 3806 // ...new search value contains old one and previous search was not finished or its result was empty 3799 if (old_value && old_value.length && q.indexOf(old_value) == 0 && (!ac || !ac.num) && this.env.contacts && !this.env.contacts.length)3807 if (old_value && old_value.length && q.indexOf(old_value) == 0 && (!ac || ac.num <= 0) && this.env.contacts && !this.env.contacts.length) 3800 3808 return; 3801 3809 … … 4919 4927 // submit request with appended token 4920 4928 if (confirm(this.get_label('deleteidentityconfirm'))) 4921 this.goto_url('delete-identity', '_iid='+id+'&_token='+this.env.request_token, true);4929 this.goto_url('delete-identity', { _iid: id, _token: this.env.request_token }, true); 4922 4930 4923 4931 return true; … … 6369 6377 }; 6370 6378 6379 // Checks browser capabilities eg. PDF support, TIF support 6380 this.browser_capabilities_check = function() 6381 { 6382 if (!this.env.browser_capabilities) 6383 this.env.browser_capabilities = {}; 6384 6385 if (this.env.browser_capabilities.pdf === undefined) 6386 this.env.browser_capabilities.pdf = this.pdf_support_check(); 6387 6388 if (this.env.browser_capabilities.flash === undefined) 6389 this.env.browser_capabilities.flash = this.flash_support_check(); 6390 6391 if (this.env.browser_capabilities.tif === undefined) 6392 this.tif_support_check(); 6393 }; 6394 6395 // Returns browser capabilities string 6396 this.browser_capabilities = function() 6397 { 6398 if (!this.env.browser_capabilities) 6399 return ''; 6400 6401 var n, ret = []; 6402 6403 for (n in this.env.browser_capabilities) 6404 ret.push(n + '=' + this.env.browser_capabilities[n]); 6405 6406 return ret.join(); 6407 }; 6408 6409 this.tif_support_check = function() 6410 { 6411 var img = new Image(); 6412 6413 img.onload = function() { rcmail.env.browser_capabilities.tif = 1; }; 6414 img.onerror = function() { rcmail.env.browser_capabilities.tif = 0; }; 6415 img.src = 'program/blank.tif'; 6416 }; 6417 6418 this.pdf_support_check = function() 6419 { 6420 var plugin = navigator.mimeTypes ? navigator.mimeTypes["application/pdf"] : {}, 6421 plugins = navigator.plugins, 6422 len = plugins.length, 6423 regex = /Adobe Reader|PDF|Acrobat/i; 6424 6425 if (plugin && plugin.enabledPlugin) 6426 return 1; 6427 6428 if (window.ActiveXObject) { 6429 try { 6430 if (axObj = new ActiveXObject("AcroPDF.PDF")) 6431 return 1; 6432 } 6433 catch (e) {} 6434 try { 6435 if (axObj = new ActiveXObject("PDF.PdfCtrl")) 6436 return 1; 6437 } 6438 catch (e) {} 6439 } 6440 6441 for (i=0; i<len; i++) { 6442 plugin = plugins[i]; 6443 if (typeof plugin === 'String') { 6444 if (regex.test(plugin)) 6445 return 1; 6446 } 6447 else if (plugin.name && regex.test(plugin.name)) 6448 return 1; 6449 } 6450 6451 return 0; 6452 }; 6453 6454 this.flash_support_check = function() 6455 { 6456 var plugin = navigator.mimeTypes ? navigator.mimeTypes["application/x-shockwave-flash"] : {}; 6457 6458 if (plugin && plugin.enabledPlugin) 6459 return 1; 6460 6461 if (window.ActiveXObject) { 6462 try { 6463 if (axObj = new ActiveXObject("ShockwaveFlash.ShockwaveFlash")) 6464 return 1; 6465 } 6466 catch (e) {} 6467 } 6468 6469 return 0; 6470 }; 6471 6371 6472 } // end object rcube_webmail 6372 6473 -
program/steps/mail/func.inc
r041c93c r19cc5b9 82 82 } 83 83 84 $search_mods = $RCMAIL->config->get('search_mods', $SEARCH_MODS_DEFAULT);85 $OUTPUT->set_env('search_mods', $search_mods);84 $search_mods = $RCMAIL->config->get('search_mods', $SEARCH_MODS_DEFAULT); 85 $OUTPUT->set_env('search_mods', $search_mods); 86 86 } 87 87 … … 115 115 if ($CONFIG['junk_mbox']) 116 116 $OUTPUT->set_env('junk_mailbox', $CONFIG['junk_mbox']); 117 118 if (!empty($_SESSION['browser_caps'])) 119 $OUTPUT->set_env('browser_capabilities', $_SESSION['browser_caps']); 117 120 118 121 if (!$OUTPUT->ajax_call) … … 1104 1107 1105 1108 // Content-Type: image/*... 1106 if (preg_match('/^image\//i', $attach_prop->mimetype) || 1107 // ...or known file extension: many clients are using application/octet-stream 1108 ($attach_prop->filename && 1109 preg_match('/^application\/octet-stream$/i', $attach_prop->mimetype) && 1110 preg_match('/\.(jpg|jpeg|png|gif|bmp)$/i', $attach_prop->filename)) 1111 ) { 1109 if (rcmail_part_image_type($attach_prop)) { 1112 1110 $out .= html::tag('hr') . html::p(array('align' => "center"), 1113 1111 html::img(array( … … 1127 1125 } 1128 1126 1127 function rcmail_part_image_type($part) 1128 { 1129 $rcmail = rcmail::get_instance(); 1130 1131 // Skip TIFF images if browser doesn't support this format... 1132 $tiff_support = !empty($_SESSION['browser_caps']) && !empty($_SESSION['browser_caps']['tif']); 1133 // until we can convert them to JPEG 1134 $tiff_support = $tiff_support || $rcmail->config->get('im_convert_path'); 1135 1136 // Content-type regexp 1137 $mime_regex = $tiff_support ? '/^image\//i' : '/^image\/(?!tif)/i'; 1138 1139 // Content-Type: image/*... 1140 if (preg_match($mime_regex, $part->mimetype)) { 1141 return $part->mimetype; 1142 } 1143 1144 // Many clients use application/octet-stream, we'll detect mimetype 1145 // by checking filename extension 1146 1147 // Supported image filename extensions to image type map 1148 $types = array( 1149 'jpg' => 'image/jpeg', 1150 'jpeg' => 'image/jpeg', 1151 'png' => 'image/png', 1152 'gif' => 'image/gif', 1153 'bmp' => 'image/bmp', 1154 ); 1155 if ($tiff_support) { 1156 $types['tif'] = 'image/tiff'; 1157 $types['tiff'] = 'image/tiff'; 1158 } 1159 1160 if ($part->filename 1161 && preg_match('/^application\/octet-stream$/i', $part->mimetype) 1162 && preg_match('/\.([^.])$/i', $part->filename, $m) 1163 && ($extension = strtolower($m[1])) 1164 && isset($types[$extension]) 1165 ) { 1166 return $types[$extension]; 1167 } 1168 } 1129 1169 1130 1170 /** -
program/steps/mail/get.inc
r041c93c r19cc5b9 23 23 // show loading page 24 24 if (!empty($_GET['_preload'])) { 25 $url = preg_replace('/ [&?]+_preload=1/', '', $_SERVER['REQUEST_URI']);25 $url = preg_replace('/([&?]+)_preload=/', '\\1_embed=', $_SERVER['REQUEST_URI']); 26 26 $message = rcube_label('loadingdata'); 27 27 … … 77 77 // overwrite modified vars from plugin 78 78 $mimetype = $plugin['mimetype']; 79 80 // TIFF to JPEG conversion, if needed 81 $tiff_support = !empty($_SESSION['browser_caps']) && !empty($_SESSION['browser_caps']['tif']); 82 if (!empty($_REQUEST['_embed']) && !$tiff_support 83 && $RCMAIL->config->get('im_convert_path') 84 && rcmail_part_image_type($part) == 'image/tiff' 85 ) { 86 $tiff2jpeg = true; 87 $mimetype = 'image/jpeg'; 88 } 89 79 90 list($ctype_primary, $ctype_secondary) = explode('/', $mimetype); 80 91 if ($plugin['body']) … … 151 162 header("Content-Disposition: $disposition; filename=\"$filename\""); 152 163 164 // handle tiff to jpeg conversion 165 if (!empty($tiff2jpeg)) { 166 $temp_dir = unslashify($RCMAIL->config->get('temp_dir')); 167 $file_path = tempnam($temp_dir, 'rcmAttmnt'); 168 169 // write content to temp file 170 if ($part->body) { 171 $saved = file_put_contents($file_path, $part->body); 172 } 173 else if ($part->size) { 174 $fd = fopen($file_path, 'w'); 175 $saved = $RCMAIL->storage->get_message_part($MESSAGE->uid, $part->mime_id, $part, false, $fd); 176 fclose($fd); 177 } 178 179 // convert image to jpeg and send it to the browser 180 if ($saved) { 181 $image = new rcube_image($file_path); 182 if ($image->convert(rcube_image::TYPE_JPG, $file_path)) { 183 header("Content-Length: " . filesize($file_path)); 184 readfile($file_path); 185 } 186 unlink($file_path); 187 } 188 } 153 189 // do content filtering to avoid XSS through fake images 154 if (!empty($_REQUEST['_embed']) && $browser->ie && $browser->ver <= 8) {190 else if (!empty($_REQUEST['_embed']) && $browser->ie && $browser->ver <= 8) { 155 191 if ($part->body) { 156 192 echo preg_match('/<(script|iframe|object)/i', $part->body) ? '' : $part->body; -
program/steps/mail/show.inc
r041c93c r19cc5b9 21 21 22 22 $PRINT_MODE = $RCMAIL->action=='print' ? TRUE : FALSE; 23 24 // Read browser capabilities and store them in session 25 if ($caps = get_input_value('_caps', RCUBE_INPUT_GET)) { 26 $browser_caps = array(); 27 foreach (explode(',', $caps) as $cap) { 28 $cap = explode('=', $cap); 29 $browser_caps[$cap[0]] = $cap[1]; 30 } 31 $_SESSION['browser_caps'] = $browser_caps; 32 } 23 33 24 34 // similar code as in program/steps/mail/get.inc … … 52 62 53 63 // mimetypes supported by the browser (default settings) 54 $mimetypes = $RCMAIL->config->get('client_mimetypes', 'text/plain,text/html,text/xml,image/jpeg,image/gif,image/png,application/x-javascript,application/pdf,application/x-shockwave-flash'); 55 $OUTPUT->set_env('mimetypes', is_string($mimetypes) ? explode(',', $mimetypes) : (array)$mimetypes); 64 $mimetypes = $RCMAIL->config->get('client_mimetypes', 'text/plain,text/html,text/xml,image/jpeg,image/gif,image/png,image/bmp,image/tiff,application/x-javascript,application/pdf,application/x-shockwave-flash'); 65 $mimetypes = is_string($mimetypes) ? explode(',', $mimetypes) : (array)$mimetypes; 66 67 // Remove unsupported types, which makes that attachment which cannot be 68 // displayed in a browser will be downloaded directly without displaying an overlay page 69 if (empty($_SESSION['browser_caps']['pdf']) && ($key = array_search('application/pdf', $mimetypes)) !== false) { 70 unset($mimetypes[$key]); 71 } 72 if (empty($_SESSION['browser_caps']['flash']) && ($key = array_search('application/x-shockwave-flash', $mimetypes)) !== false) { 73 unset($mimetypes[$key]); 74 } 75 if (empty($_SESSION['browser_caps']['tif']) && ($key = array_search('image/tiff', $mimetypes)) !== false) { 76 // we can convert tiff to jpeg 77 if (!$RCMAIL->config->get('im_convert_path')) { 78 unset($mimetypes[$key]); 79 } 80 } 81 82 $OUTPUT->set_env('mimetypes', $mimetypes); 56 83 57 84 if ($CONFIG['drafts_mbox']) -
skins/larry/ui.js
r041c93c r8c16ea9 263 263 264 264 var pos = $(p.object).offset(); 265 pos.top -= (rcmail.env.task == 'login' ? 20 : 160); 265 266 me.messagedialog.dialog('close'); 266 267 me.messagedialog.html(p.message) … … 273 274 me.messagedialog.dialog('destroy').hide(); 274 275 }, 275 position: ['center', pos.top - 160],276 position: ['center', pos.top], 276 277 hide: { effect:'drop', direction:'down' }, 277 278 width: 420,
Note: See TracChangeset
for help on using the changeset viewer.
