Changeset d487cd5a in github


Ignore:
Timestamp:
May 30, 2012 6:17:26 AM (12 months ago)
Author:
Aleksander Machniak <alec@…>
Branches:
master, HEAD, pdo
Children:
528c78a
Parents:
ca1c2a8 (diff), 19cc5b9 (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.
Message:

Merge branch 'dev-browser-capabilities'

Conflicts:

CHANGELOG

Files:
1 added
13 edited

Legend:

Unmodified
Added
Removed
  • CHANGELOG

    rca1c2a8 rd487cd5a  
    22=========================== 
    33 
     4- Display Tiff as Jpeg in browsers without Tiff support (#1488452) 
     5- Don't display Pdf/Tiff/Flash attachments inline without browser support (#1488452, #1487929) 
    46- Don't show errors when moving contacts into groups they are already in (#1488493) 
    57- Make folders with unread messages in subfolders bold again (#1486793) 
  • program/include/rcube_image.php

    r041c93c r19cc5b9  
    1414 |                                                                       | 
    1515 | PURPOSE:                                                              | 
    16  |   Image resizer                                                       | 
     16 |   Image resizer and converter                                         | 
    1717 |                                                                       | 
    1818 +-----------------------------------------------------------------------+ 
     
    2525{ 
    2626    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 
    2740 
    2841    function __construct($filename) 
     
    6780     * @param string $filename  Output filename 
    6881     * 
    69      * @return Success of convert as true/false 
     82     * @return bool True on success, False on failure 
    7083     */ 
    7184    public function resize($size, $filename = null) 
     
    96109 
    97110            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 === '') { 
    102115                return true; 
    103116            } 
     
    149162        } 
    150163 
     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        } 
    151229 
    152230        // @TODO: print error to the log? 
     
    170248        } 
    171249    } 
     250 
    172251} 
  • program/js/app.js

    r041c93c rb9854b8  
    307307          this.http_post(postact, postdata); 
    308308        } 
     309 
     310        // detect browser capabilities 
     311        if (!this.is_framed()) 
     312          this.browser_capabilities_check(); 
    309313 
    310314        break; 
     
    19441948      url += '&_search='+this.env.search_request; 
    19451949 
    1946     if (action == 'preview' && String(target.location.href).indexOf(url) >= 0) 
     1950    // add browser capabilities, so we can properly handle attachments 
     1951    url += '&_caps='+urlencode(this.browser_capabilities()); 
     1952 
     1953    if (preview && String(target.location.href).indexOf(url) >= 0) 
    19471954      this.show_contentframe(true); 
    19481955    else { 
     
    19501957 
    19511958      // 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) { 
     1959      if (preview && this.message_list && this.message_list.rows[id] && this.message_list.rows[id].unread && this.env.preview_pane_mark_read >= 0) { 
    19531960        this.preview_read_timer = setTimeout(function() { 
    19541961          ref.set_message(id, 'unread', false); 
     
    63696376  }; 
    63706377 
     6378  // Checks browser capabilities eg. PDF support, TIF support 
     6379  this.browser_capabilities_check = function() 
     6380  { 
     6381    if (!this.env.browser_capabilities) 
     6382      this.env.browser_capabilities = {}; 
     6383 
     6384    if (this.env.browser_capabilities.pdf === undefined) 
     6385      this.env.browser_capabilities.pdf = this.pdf_support_check(); 
     6386 
     6387    if (this.env.browser_capabilities.flash === undefined) 
     6388      this.env.browser_capabilities.flash = this.flash_support_check(); 
     6389 
     6390    if (this.env.browser_capabilities.tif === undefined) 
     6391      this.tif_support_check(); 
     6392  }; 
     6393 
     6394  // Returns browser capabilities string 
     6395  this.browser_capabilities = function() 
     6396  { 
     6397    if (!this.env.browser_capabilities) 
     6398      return ''; 
     6399 
     6400    var n, ret = []; 
     6401 
     6402    for (n in this.env.browser_capabilities) 
     6403      ret.push(n + '=' + this.env.browser_capabilities[n]); 
     6404 
     6405    return ret.join(); 
     6406  }; 
     6407 
     6408  this.tif_support_check = function() 
     6409  { 
     6410    var img = new Image(); 
     6411 
     6412    img.onload = function() { rcmail.env.browser_capabilities.tif = 1; }; 
     6413    img.onerror = function() { rcmail.env.browser_capabilities.tif = 0; }; 
     6414    img.src = 'program/blank.tif'; 
     6415  }; 
     6416 
     6417  this.pdf_support_check = function() 
     6418  { 
     6419    var plugin = navigator.mimeTypes ? navigator.mimeTypes["application/pdf"] : {}, 
     6420      plugins = navigator.plugins, 
     6421      len = plugins.length, 
     6422      regex = /Adobe Reader|PDF|Acrobat/i; 
     6423 
     6424    if (plugin && plugin.enabledPlugin) 
     6425        return 1; 
     6426 
     6427    if (window.ActiveXObject) { 
     6428      try { 
     6429        if (axObj = new ActiveXObject("AcroPDF.PDF")) 
     6430          return 1; 
     6431      } 
     6432      catch (e) {} 
     6433      try { 
     6434        if (axObj = new ActiveXObject("PDF.PdfCtrl")) 
     6435          return 1; 
     6436      } 
     6437      catch (e) {} 
     6438    } 
     6439 
     6440    for (i=0; i<len; i++) { 
     6441      plugin = plugins[i]; 
     6442      if (typeof plugin === 'String') { 
     6443        if (regex.test(plugin)) 
     6444          return 1; 
     6445      } 
     6446      else if (plugin.name && regex.test(plugin.name)) 
     6447        return 1; 
     6448    } 
     6449 
     6450    return 0; 
     6451  }; 
     6452 
     6453  this.flash_support_check = function() 
     6454  { 
     6455    var plugin = navigator.mimeTypes ? navigator.mimeTypes["application/x-shockwave-flash"] : {}; 
     6456 
     6457    if (plugin && plugin.enabledPlugin) 
     6458        return 1; 
     6459 
     6460    if (window.ActiveXObject) { 
     6461      try { 
     6462        if (axObj = new ActiveXObject("ShockwaveFlash.ShockwaveFlash")) 
     6463          return 1; 
     6464      } 
     6465      catch (e) {} 
     6466    } 
     6467 
     6468    return 0; 
     6469  }; 
     6470 
    63716471}  // end object rcube_webmail 
    63726472 
  • program/steps/mail/func.inc

    r041c93c r19cc5b9  
    8282    } 
    8383 
    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); 
    8686  } 
    8787 
     
    115115  if ($CONFIG['junk_mbox']) 
    116116    $OUTPUT->set_env('junk_mailbox', $CONFIG['junk_mbox']); 
     117 
     118  if (!empty($_SESSION['browser_caps'])) 
     119    $OUTPUT->set_env('browser_capabilities', $_SESSION['browser_caps']); 
    117120 
    118121  if (!$OUTPUT->ajax_call) 
     
    11041107 
    11051108      // 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)) { 
    11121110        $out .= html::tag('hr') . html::p(array('align' => "center"), 
    11131111          html::img(array( 
     
    11271125} 
    11281126 
     1127function 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} 
    11291169 
    11301170/** 
  • program/steps/mail/get.inc

    r041c93c r19cc5b9  
    2323// show loading page 
    2424if (!empty($_GET['_preload'])) { 
    25   $url = preg_replace('/[&?]+_preload=1/', '', $_SERVER['REQUEST_URI']); 
     25  $url = preg_replace('/([&?]+)_preload=/', '\\1_embed=', $_SERVER['REQUEST_URI']); 
    2626  $message = rcube_label('loadingdata'); 
    2727 
     
    7777    // overwrite modified vars from plugin 
    7878    $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 
    7990    list($ctype_primary, $ctype_secondary) = explode('/', $mimetype); 
    8091    if ($plugin['body']) 
     
    151162      header("Content-Disposition: $disposition; filename=\"$filename\""); 
    152163 
     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      } 
    153189      // 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) { 
    155191        if ($part->body) { 
    156192          echo preg_match('/<(script|iframe|object)/i', $part->body) ? '' : $part->body; 
  • program/steps/mail/show.inc

    r041c93c r19cc5b9  
    2121 
    2222$PRINT_MODE = $RCMAIL->action=='print' ? TRUE : FALSE; 
     23 
     24// Read browser capabilities and store them in session 
     25if ($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} 
    2333 
    2434// similar code as in program/steps/mail/get.inc 
     
    5262 
    5363  // 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); 
    5683 
    5784  if ($CONFIG['drafts_mbox']) 
  • program/include/rcube_contacts.php

    r041c93c rca1c2a8  
    935935            ); 
    936936 
    937             if (!$this->db->db_error) 
     937            if ($this->db->db_error) 
     938                $this->set_error(self::ERROR_SAVING, $this->db->db_error_msg); 
     939            else 
    938940                $added++; 
    939941        } 
  • program/localization/de_CH/messages.inc

    r1103607 rca1c2a8  
    116116$messages['contactaddedtogroup'] = 'Kontakte wurden dieser Gruppe hinzugefÃŒgt.'; 
    117117$messages['contactremovedfromgroup'] = 'Kontakte wurden aus dieser Gruppe entfernt.'; 
     118$messages['nogroupassignmentschanged'] = 'Es wurde keine Gruppenzuweisung verÀndert.'; 
    118119$messages['importwait'] = 'Daten werden importiert, bitte warten...'; 
    119120$messages['importerror'] = 'Import fehlgeschlagen! Die hochgeladene Datei ist nicht im vCard-Format.'; 
  • program/localization/de_DE/messages.inc

    r5cea366 rca1c2a8  
    114114$messages['contactaddedtogroup'] = 'Kontakte wurden dieser Gruppe hinzugefÃŒgt.'; 
    115115$messages['contactremovedfromgroup'] = 'Kontakte wurden aus dieser Gruppe entfernt.'; 
     116$messages['nogroupassignmentschanged'] = 'Es wurde keine Gruppenzuweisung verÀndert.'; 
    116117$messages['importwait'] = 'Daten werden importiert, bitte warten...'; 
    117118$messages['importerror'] = 'Import fehlgeschlagen! Die hochgeladene Datei ist nicht im vCard-Format.'; 
  • program/localization/en_US/messages.inc

    r1103607 rca1c2a8  
    122122$messages['contactaddedtogroup'] = 'Successfully added the contacts to this group.'; 
    123123$messages['contactremovedfromgroup'] = 'Successfully removed contacts from this group.'; 
     124$messages['nogroupassignmentschanged'] = 'No group assignments changed.'; 
    124125$messages['importwait'] = 'Importing, please wait...'; 
    125126$messages['importerror'] = 'Import failed! The uploaded file is not a valid vCard file.'; 
  • program/steps/addressbook/groups.inc

    r041c93c rca1c2a8  
    4848    if ($result) 
    4949      $OUTPUT->show_message('contactaddedtogroup'); 
     50    else if ($plugin['abort'] || $CONTACTS->get_error()) 
     51      $OUTPUT->show_message($plugin['message'] ? $plugin['message'] : 'errorsaving', 'error'); 
    5052    else 
    51       $OUTPUT->show_message($plugin['message'] ? $plugin['message'] : 'errorsaving', 'error'); 
     53      $OUTPUT->show_message($plugin['message'] ? $plugin['message'] : 'nogroupassignmentschanged'); 
    5254  } 
    5355} 
  • skins/larry/mail.css

    r4e10131a rdcf23b9  
    185185#mailboxlist li.mailbox.archive.selected > a { 
    186186        background-position: 6px -1723px; 
     187} 
     188 
     189#mailboxlist li.unread { 
     190        font-weight: bold; 
    187191} 
    188192 
  • skins/larry/styles.css

    r92be3ee r96077f6  
    19171917        text-decoration: none; 
    19181918        white-space: nowrap; 
     1919        overflow: hidden; 
     1920        text-overflow: ellipsis; 
     1921} 
     1922 
     1923#compose-attachments ul li { 
     1924        padding-right: 28px; 
    19191925} 
    19201926 
Note: See TracChangeset for help on using the changeset viewer.