132b3c81e4a0ec81fc2602b5b3aff238ddde379b
[Packages/TYPO3.CMS.git] / t3lib / thumbs.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 1999-2011 Kasper Skårhøj (kasperYYYY@typo3.com)
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 * A copy is found in the textfile GPL.txt and important notices to the license
17 * from the author is found in LICENSE.txt distributed with these scripts.
18 *
19 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27 /**
28 * Generates a thumbnail and returns an image stream, either GIF/PNG or JPG
29 *
30 * Revised for TYPO3 3.6 July/2003 by Kasper Skårhøj
31 *
32 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
33 */
34
35
36 // *******************************
37 // Set error reporting
38 // *******************************
39 error_reporting(E_ALL ^ E_NOTICE ^ E_DEPRECATED);
40
41
42
43 // ******************
44 // Constants defined
45 // ******************
46 define('TYPO3_OS', stristr(PHP_OS,'win')&&!stristr(PHP_OS,'darwin')?'WIN':'');
47 define('TYPO3_MODE','BE');
48
49 if(!defined('PATH_thisScript')) {
50 define('PATH_thisScript', str_replace('//', '/', str_replace('\\', '/',
51 (PHP_SAPI == 'fpm-fcgi' || PHP_SAPI == 'cgi' || PHP_SAPI == 'isapi' || PHP_SAPI == 'cgi-fcgi') &&
52 ($_SERVER['ORIG_PATH_TRANSLATED'] ? $_SERVER['ORIG_PATH_TRANSLATED'] : $_SERVER['PATH_TRANSLATED']) ?
53 ($_SERVER['ORIG_PATH_TRANSLATED'] ? $_SERVER['ORIG_PATH_TRANSLATED'] : $_SERVER['PATH_TRANSLATED']) :
54 ($_SERVER['ORIG_SCRIPT_FILENAME'] ? $_SERVER['ORIG_SCRIPT_FILENAME'] : $_SERVER['SCRIPT_FILENAME']))));
55 }
56
57 if(!defined('PATH_site')) define('PATH_site', preg_replace('/[^\/]*.[^\/]*$/','',PATH_thisScript)); // the path to the website folder (see init.php)
58 if(!defined('PATH_t3lib')) define('PATH_t3lib', PATH_site.'t3lib/');
59 define('PATH_typo3conf', PATH_site.'typo3conf/');
60 define('TYPO3_mainDir', 'typo3/'); // This is the directory of the backend administration for the sites of this TYPO3 installation.
61 define('PATH_typo3', PATH_site.TYPO3_mainDir);
62
63
64 // ******************
65 // Including config
66 // ******************
67 require_once(PATH_t3lib.'class.t3lib_div.php');
68 require_once(PATH_t3lib.'class.t3lib_extmgm.php');
69
70 require(PATH_t3lib.'config_default.php');
71 if (!defined ('TYPO3_db')) {
72 die ('The configuration file was not included.');
73 }
74 if (!$GLOBALS['TYPO3_CONF_VARS']['GFX']['image_processing']) {
75 die ('ImageProcessing was disabled!');
76 }
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94 /**
95 * Class for generating a thumbnail from the input parameters given to the script
96 *
97 * Input GET var, &file: relative or absolute reference to an imagefile. WILL be validated against PATH_site / lockRootPath
98 * Input GET var, &size: integer-values defining size of thumbnail, format '[int]' or '[int]x[int]'
99 *
100 * Relative paths MUST BE the first two characters ONLY: eg: '../dir/file.gif', otherwise it is expect to be absolute
101 *
102 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
103 * @package TYPO3
104 * @subpackage t3lib
105 */
106 class SC_t3lib_thumbs {
107 var $include_once = array();
108
109 var $outdir = 'typo3temp/'; // The output directory of temporary files in PATH_site
110 var $output = '';
111 var $sizeDefault='64x64';
112
113 var $imageList; // Coming from $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext']
114 var $input; // Contains the absolute path to the file for which to make a thumbnail (after init())
115
116 // Internal, static: GPvar:
117 var $file; // Holds the input filename (GET: file)
118 var $size; // Holds the input size (GET: size)
119 var $mtime = 0; // Last modification time of the supplied file
120
121
122 /**
123 * Initialize; reading parameters with GPvar and checking file path
124 * Results in internal var, $this->input, being set to the absolute path of the file for which to make the thumbnail.
125 *
126 * @return void
127 */
128 function init() {
129 // Setting GPvars:
130 $file = t3lib_div::_GP('file');
131 $size = t3lib_div::_GP('size');
132 $md5sum = t3lib_div::_GP('md5sum');
133
134 // Image extension list is set:
135 $this->imageList = $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext']; // valid extensions. OBS: No spaces in the list, all lowercase...
136
137 // If the filereference $this->file is relative, we correct the path
138 if (substr($file,0,3)=='../') {
139 $file = PATH_site.substr($file,3);
140 }
141
142 $mtime = 0;
143 // Now the path is absolute.
144 // Checking for backpath and double slashes + the thumbnail can be made from files which are in the PATH_site OR the lockRootPath only!
145 if (t3lib_div::isAllowedAbsPath($file)) {
146 $mtime = filemtime($file);
147 }
148
149 // Do an MD5 check to prevent viewing of images without permission
150 $OK = FALSE;
151 if ($mtime) {
152 // Always use the absolute path for this check!
153 $check = basename($file).':'.$mtime.':'.$GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'];
154 $md5pre47 = t3lib_div::shortMD5($check);
155 $md5from47 = md5($check);
156 if (!strcmp($md5pre47, $md5sum) || !strcmp($md5from47, $md5sum)) {
157 $OK = TRUE;
158 }
159 }
160
161 if ($OK) {
162 $this->input = $file;
163 $this->size = $size;
164 $this->mtime = $mtime;
165 } else {
166 // hide the path to the document root;
167 $publicFilename = substr($file, strlen(PATH_site));
168 throw new RuntimeException(
169 'TYPO3 Fatal Error: Image \'' . $publicFilename . '\' does not exist and/or MD5 checksum did not match. ' .
170 'If the target file exists and its file name contains special characters, the setting of ' .
171 '$TYPO3_CONF_VARS[SYS][systemLocale] might be wrong.'
172 ,
173 1270853950
174 );
175 }
176 }
177
178 /**
179 * Create the thumbnail
180 * Will exit before return if all is well.
181 *
182 * @return void
183 */
184 function main() {
185 // If file exists, we make a thumbsnail of the file.
186 if ($this->input && file_exists($this->input)) {
187
188 // Check file extension:
189 $reg = array();
190 if (preg_match('/(.*)\.([^\.]*$)/', $this->input, $reg)) {
191 $ext=strtolower($reg[2]);
192 $ext=($ext=='jpeg') ? 'jpg' : $ext;
193 if ($ext=='ttf') {
194 $this->fontGif($this->input); // Make font preview... (will not return)
195 } elseif (!t3lib_div::inList($this->imageList, $ext)) {
196 $this->errorGif('Not imagefile!', $ext, basename($this->input));
197 }
198 } else {
199 $this->errorGif('Not imagefile!', 'No ext!', basename($this->input));
200 }
201
202 // ... so we passed the extension test meaning that we are going to make a thumbnail here:
203 if (!$this->size) $this->size = $this->sizeDefault; // default
204
205 // I added extra check, so that the size input option could not be fooled to pass other values. That means the value is exploded, evaluated to an integer and the imploded to [value]x[value]. Furthermore you can specify: size=340 and it'll be translated to 340x340.
206 $sizeParts = explode('x', $this->size . 'x' . $this->size); // explodes the input size (and if no "x" is found this will add size again so it is the same for both dimensions)
207 $sizeParts = array(t3lib_utility_Math::forceIntegerInRange($sizeParts[0], 1, 1000), t3lib_utility_Math::forceIntegerInRange($sizeParts[1], 1, 1000)); // Cleaning it up, only two parameters now.
208 $this->size = implode('x', $sizeParts); // Imploding the cleaned size-value back to the internal variable
209 $sizeMax = max($sizeParts); // Getting max value
210
211 // Init
212 $outpath = PATH_site . $this->outdir;
213
214 // Should be - ? 'png' : 'gif' - , but doesn't work (ImageMagick prob.?)
215 // René: png work for me
216 $thmMode = t3lib_utility_Math::forceIntegerInRange($GLOBALS['TYPO3_CONF_VARS']['GFX']['thumbnails_png'], 0);
217 $outext = ($ext!='jpg' || ($thmMode & 2)) ? ($thmMode & 1 ? 'png' : 'gif') : 'jpg';
218
219 $outfile = 'tmb_' . substr(md5($this->input . $this->mtime . $this->size), 0, 10) . '.' . $outext;
220 $this->output = $outpath . $outfile;
221
222 if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['im']) {
223 // If thumbnail does not exist, we generate it
224 if (!file_exists($this->output)) {
225 $parameters = '-sample ' . $this->size . ' ' . $this->wrapFileName($this->input) . '[0] ' . $this->wrapFileName($this->output);
226 $cmd = t3lib_div::imageMagickCommand('convert', $parameters);
227 t3lib_utility_Command::exec($cmd);
228 if (!file_exists($this->output)) {
229 $this->errorGif('No thumb','generated!', basename($this->input));
230 } else {
231 t3lib_div::fixPermissions($this->output);
232 }
233 }
234 // The thumbnail is read and output to the browser
235 if (($fd = @fopen($this->output, 'rb'))) {
236 $fileModificationTime = filemtime($this->output);
237 header('Content-type: image/' . $outext);
238 header('Last-Modified: '. date('r', $fileModificationTime));
239 header('Etag: ' . md5($this->output) . '-' . $fileModificationTime);
240 // Expiration time is choosen arbitrary to 1 month
241 header('Expires: ' . date('r', $fileModificationTime + 30*24*60*60));
242 fpassthru($fd);
243 fclose($fd);
244 } else {
245 $this->errorGif('Read problem!', '', $this->output);
246 }
247 } else exit;
248 } else {
249 $this->errorGif('No valid','inputfile!', basename($this->input));
250 }
251 }
252
253
254
255
256
257
258
259
260
261
262
263 /***************************
264 *
265 * OTHER FUNCTIONS:
266 *
267 ***************************/
268
269 /**
270 * Creates error image based on gfx/notfound_thumb.png
271 * Requires GD lib enabled, otherwise it will exit with the three textstrings outputted as text.
272 * Outputs the image stream to browser and exits!
273 *
274 * @param string Text line 1
275 * @param string Text line 2
276 * @param string Text line 3
277 * @return void
278 */
279 function errorGif($l1,$l2,$l3) {
280 if (!$GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib']) {
281 throw new RuntimeException(
282 'TYPO3 Fatal Error: No gdlib. ' . $l1 . ' ' . $l2 . ' ' . $l3,
283 1270853952
284 );
285 }
286
287 // Creates the basis for the error image
288 if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib_png']) {
289 header('Content-type: image/png');
290 $im = imagecreatefrompng(PATH_typo3 . 'gfx/notfound_thumb.png');
291 } else {
292 header('Content-type: image/gif');
293 $im = imagecreatefromgif(PATH_typo3 . 'gfx/notfound_thumb.gif');
294 }
295 // Sets background color and print color.
296 $white = imageColorAllocate($im, 255, 255, 255);
297 $black = imageColorAllocate($im, 0, 0, 0);
298
299 // Prints the text strings with the build-in font functions of GD
300 $x=0;
301 $font=0;
302 if ($l1) {
303 imagefilledrectangle($im, $x, 9, 56, 16, $white);
304 imageString($im, $font, $x, 9, $l1, $black);
305 }
306 if ($l2) {
307 imagefilledrectangle($im, $x, 19, 56, 26, $white);
308 imageString($im, $font, $x, 19, $l2, $black);
309 }
310 if ($l3) {
311 imagefilledrectangle($im, $x, 29, 56, 36, $white);
312 imageString($im, $font, $x, 29, substr($l3, -14), $black);
313 }
314
315 // Outputting the image stream and exit
316 if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib_png']) {
317 imagePng($im);
318 } else {
319 imageGif($im);
320 }
321 imagedestroy($im);
322 exit;
323 }
324
325 /**
326 * Creates a font-preview thumbnail.
327 * This means a PNG/GIF file with the text "AaBbCc...." set with the font-file given as input and in various sizes to show how the font looks
328 * Requires GD lib enabled.
329 * Outputs the image stream to browser and exits!
330 *
331 * @param string The filepath to the font file (absolute, probably)
332 * @return void
333 */
334 function fontGif($font) {
335 if (!$GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib']) {
336 throw new RuntimeException(
337 'TYPO3 Fatal Error: No gdlib.',
338 1270853953
339 );
340 }
341
342 // Create image and set background color to white.
343 $im = imageCreate(250, 76);
344 $white = imageColorAllocate($im, 255, 255, 255);
345 $col = imageColorAllocate($im, 0, 0, 0);
346
347 // The test string and offset in x-axis.
348 $string = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZzÆæØøÅåÄäÖöÜüß';
349 $x=13;
350
351 // Print (with non-ttf font) the size displayed
352 imagestring ($im, 1, 0, 2, '10', $col);
353 imagestring ($im, 1, 0, 15, '12', $col);
354 imagestring ($im, 1, 0, 30, '14', $col);
355 imagestring ($im, 1, 0, 47, '18', $col);
356 imagestring ($im, 1, 0, 68, '24', $col);
357
358 // Print with ttf-font the test string
359 imagettftext ($im, t3lib_div::freetypeDpiComp(10), 0, $x, 8, $col, $font, $string);
360 imagettftext ($im, t3lib_div::freetypeDpiComp(12), 0, $x, 21, $col, $font, $string);
361 imagettftext ($im, t3lib_div::freetypeDpiComp(14), 0, $x, 36, $col, $font, $string);
362 imagettftext ($im, t3lib_div::freetypeDpiComp(18), 0, $x, 53, $col, $font, $string);
363 imagettftext ($im, t3lib_div::freetypeDpiComp(24), 0, $x, 74, $col, $font, $string);
364
365 // Output PNG or GIF based on $GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib_png']
366 if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib_png']) {
367 header('Content-type: image/png');
368 imagePng($im);
369 } else {
370 header('Content-type: image/gif');
371 imageGif($im);
372 }
373 imagedestroy($im);
374 exit;
375 }
376
377 /**
378 * Escapes a file name so it can safely be used on the command line.
379 *
380 * @param string $inputName filename to safeguard, must not be empty
381 *
382 * @return string $inputName escaped as needed
383 */
384 protected function wrapFileName($inputName) {
385 if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['UTF8filesystem']) {
386 $currentLocale = setlocale(LC_CTYPE, 0);
387 setlocale(LC_CTYPE, $GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLocale']);
388 }
389 $escapedInputName = escapeshellarg($inputName);
390 if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['UTF8filesystem']) {
391 setlocale(LC_CTYPE, $currentLocale);
392 }
393 return $escapedInputName;
394 }
395 }
396
397 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/thumbs.php'])) {
398 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/thumbs.php']);
399 }
400
401
402
403
404 // Make instance:
405 $SOBE = t3lib_div::makeInstance('SC_t3lib_thumbs');
406 $SOBE->init();
407 $SOBE->main();
408
409 ?>