diff --git a/etemplate/inc/class.vfs_widget.inc.php b/etemplate/inc/class.vfs_widget.inc.php index 948c11b609..24b2aa6c7b 100644 --- a/etemplate/inc/class.vfs_widget.inc.php +++ b/etemplate/inc/class.vfs_widget.inc.php @@ -337,6 +337,11 @@ class vfs_widget { $thparams['thsize'] = $thsize; } + // add modification time to url to allow long caching + if (is_array($value) && $value['mtime']) + { + $thparams['mtime'] = $value['mtime']; + } $value = $GLOBALS['egw']->link('/etemplate/thumbnail.php', $thparams); } diff --git a/etemplate/js/et2_widget_vfs.js b/etemplate/js/et2_widget_vfs.js index 4fafdfc2ba..ddd0a278ad 100644 --- a/etemplate/js/et2_widget_vfs.js +++ b/etemplate/js/et2_widget_vfs.js @@ -333,7 +333,7 @@ var et2_vfsMime = expose(et2_valueWidget.extend([et2_IDetachedDOM], title: _value.name, type: _value.mime, poster:'', // TODO: Should be changed by correct video thumbnail later - thumbnail:this.egw().mime_icon(_value['mime'], _value['path']) , + thumbnail: this.egw().mime_icon(_value.mime, _value.path, undefined, _value.mtime), href: base_url + _value.download_url }]; } @@ -343,7 +343,7 @@ var et2_vfsMime = expose(et2_valueWidget.extend([et2_IDetachedDOM], title: _value.name, href: base_url + _value.download_url, type: _value.mime, - thumbnail: _value.path && _value.mime ? this.egw().mime_icon(_value['mime'], _value['path']) : this.image.attr('src')+ '&thheight=128' + thumbnail: _value.path && _value.mime ? this.egw().mime_icon(_value.mime, _value.path, undefined, _value.mtime) : this.image.attr('src')+ '&thheight=128' }]; } return mediaContent; @@ -355,7 +355,7 @@ var et2_vfsMime = expose(et2_valueWidget.extend([et2_IDetachedDOM], this.egw().debug("warn", "%s only has path, needs array with path & mime", this.id, _value); // Keep going, will be 'unknown type' } - var src = this.egw().mime_icon(_value['mime'], _value['path']); + var src = this.egw().mime_icon(_value.mime, _value.path, undefined, _value.mtime); if(src) { // Set size of thumbnail diff --git a/etemplate/thumbnail.php b/etemplate/thumbnail.php index 6ce4dfb845..805b35af78 100644 --- a/etemplate/thumbnail.php +++ b/etemplate/thumbnail.php @@ -176,8 +176,8 @@ function read_thumbnail($src) if ($dst) { // Allow client to cache these, makes scrolling in filemanager much nicer - header('Pragma: private'); - header('Cache-Control: max-age=300'); + // setting maximum allow caching time of one year, if url contains (non-empty) moditication time + egw_session::cache_control(empty($_GET['mtime']) ? 300 : 31536000, true); // true = private / browser only caching header('Content-Type: '.$output_mime); readfile($dst); return true; @@ -386,6 +386,10 @@ function get_pdf_thumbnail($file) { if(!class_exists('Imagick')) return false; + // switch off max_excution_time, as some thumbnails take longer and + // will be startet over and over again, if they dont finish + @set_time_limit(0); + $im = new Imagick($file); $im->setimageformat('png'); $im->setresolution(300, 300); diff --git a/phpgwapi/inc/class.egw_session.inc.php b/phpgwapi/inc/class.egw_session.inc.php index 76d095a752..2f56a5ea1b 100644 --- a/phpgwapi/inc/class.egw_session.inc.php +++ b/phpgwapi/inc/class.egw_session.inc.php @@ -1599,14 +1599,17 @@ class egw_session } /** - * Controling caching and expires header, based on $GLOBALS['egw_info']['flags']['nocachecontrol']: + * Controling caching and expires header + * + * Headers are send based on given parameters or $GLOBALS['egw_info']['flags']['nocachecontrol']: * - not set of false --> no caching (default) * - true --> private caching by browser (no expires header) * - "public" or integer --> public caching with given cache_expire in minutes or php.ini default session_cache_expire * * @param int $expire =null expiration time in seconds, default $GLOBALS['egw_info']['flags']['nocachecontrol'] or php.ini session.cache_expire + * @param int $private =null allows to set private caching with given expiration time, by setting it to true */ - public static function cache_control($expire=null) + public static function cache_control($expire=null, $private=null) { if (is_null($expire) && isset($GLOBALS['egw_info']['flags']['nocachecontrol']) && is_int($GLOBALS['egw_info']['flags']['nocachecontrol'])) { @@ -1616,18 +1619,19 @@ class egw_session if (!isset($_SESSION)) { // controling caching and expires header - if(!isset($GLOBALS['egw_info']['flags']['nocachecontrol']) || !$GLOBALS['egw_info']['flags']['nocachecontrol']) + if(!isset($expire) && (!isset($GLOBALS['egw_info']['flags']['nocachecontrol']) || + !$GLOBALS['egw_info']['flags']['nocachecontrol'])) { session_cache_limiter('nocache'); } - elseif ($GLOBALS['egw_info']['flags']['nocachecontrol'] === 'public' || is_int($GLOBALS['egw_info']['flags']['nocachecontrol'])) + elseif (isset($expire) || $GLOBALS['egw_info']['flags']['nocachecontrol'] === 'public' || is_int($GLOBALS['egw_info']['flags']['nocachecontrol'])) { // allow public caching: proxys, cdns, ... if (isset($expire)) { session_cache_expire((int)ceil($expire/60)); // in minutes } - session_cache_limiter('public'); + session_cache_limiter($private ? 'private' : 'public'); } else { @@ -1652,6 +1656,11 @@ class egw_session header('Cache-Control: private, max-age='.(60*session_cache_expire())); header_remove('Expires'); } + elseif ($private) + { + header('Cache-Control: private, max-age='.$expire); + header('Expires: ' . gmdate('D, d M Y H:i:s', time()+$expire) . ' GMT'); + } else { header('Cache-Control: public, max-age='.$expire); diff --git a/phpgwapi/js/jsapi/egw_images.js b/phpgwapi/js/jsapi/egw_images.js index 51f2c2edb6..8b069b0b9a 100644 --- a/phpgwapi/js/jsapi/egw_images.js +++ b/phpgwapi/js/jsapi/egw_images.js @@ -119,9 +119,10 @@ egw.extend('images', egw.MODULE_GLOBAL, function() { * @param {string} _mime * @param {string} _path vfs path to generate thumbnails for images * @param {number} _size defaults to 128 (only supported size currently) + * @param {number} _mtime current modification time of file to allow infinit caching as url changes * @returns url of image */ - mime_icon: function(_mime, _path, _size) + mime_icon: function(_mime, _path, _size, _mtime) { if (typeof _size == 'undefined') _size = 128; if (!_mime) _mime = 'unknown'; @@ -137,13 +138,14 @@ egw.extend('images', egw.MODULE_GLOBAL, function() { else if (typeof _path == 'string' && (type[0] == 'image' && type[1].match(/^(png|jpe?g|gif|bmp)$/) || type[0] == 'application' && (type[1].indexOf('vnd.oasis.opendocument.') === 0 || type[1] == 'pdf'))) { - var thsize = this.config('link_list_thumbnail') || 64; - image = this.link('/etemplate/thumbnail.php',{ 'path': _path, 'thsize': thsize}); + var params = { 'path': _path, 'thsize': this.config('link_list_thumbnail') || 64}; + if (_mtime) params.mtime = _mtime; + image = this.link('/etemplate/thumbnail.php', params); } else { if ((typeof type[1] == 'undefined' || !(image = this.image('mime'+_size+'_'+type[0]+'_'+type[1], 'etemplate')) && - !(typeof mime_alias_map[_mime] != 'undefined' && (image=this.mime_icon(mime_alias_map[_mime], _path, _size)))) && + !(typeof mime_alias_map[_mime] != 'undefined' && (image=this.mime_icon(mime_alias_map[_mime], _path, _size, _mtime)))) && !(image = this.image('mime'+_size+'_'+type[0], 'etemplate'))) { image = this.image('mime'+_size+'_unknown', 'etemplate');