1<?php
2/**
3 * PhotoGallery media passthrough file
4 *
5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 * @author  Marco Nolletti
7 */
8define('DOKU_INC', realpath(__DIR__.'/../../../').'/');
9
10if (!defined('DOKU_DISABLE_GZIP_OUTPUT')) define('DOKU_DISABLE_GZIP_OUTPUT', 1);
11require_once(DOKU_INC.'inc/init.php');
12require_once(DOKU_INC.'inc/fetch.functions.php');
13require_once('inc/pgdefines.php');
14require_once('phpThumb/phpthumb.class.php');
15session_write_close(); //close session
16
17if (defined('SIMPLE_TEST')) {
18    $INPUT = new Input();
19}
20
21// BEGIN main
22$WIDTH  = $INPUT->int('w');
23$HEIGHT = $INPUT->int('h');
24$CACHE  = calc_cache($INPUT->str('cache'));
25$opt = $INPUT->str('opt'); // phpThumb options
26
27$mimetypes = getMimeTypes();
28
29if(!$INPUT->str('src')){
30    //get input
31    $MEDIA  = stripctl(getID('media', false)); // no cleaning except control chars - maybe external
32    $REV    = & $INPUT->ref('rev');
33    //sanitize revision
34    $REV = preg_replace('/[^0-9]/', '', $REV);
35
36    list($EXT, $MIME, $DL) = mimetype($MEDIA, false);
37    if($EXT === false) {
38        $EXT  = 'unknown';
39        $MIME = 'application/octet-stream';
40        $DL   = true;
41    }
42
43    // check for permissions, preconditions and cache external files
44    list($STATUS, $STATUSMESSAGE) = checkFileStatus($MEDIA, $FILE, $REV, $WIDTH, $HEIGHT);
45
46    // prepare data for plugin events
47    $data = array(
48        'media'         => $MEDIA,
49        'file'          => $FILE,
50        'orig'          => $FILE,
51        'mime'          => $MIME,
52        'download'      => $DL,
53        'cache'         => $CACHE,
54        'ext'           => $EXT,
55        'width'         => $WIDTH,
56        'height'        => $HEIGHT,
57        'status'        => $STATUS,
58        'statusmessage' => $STATUSMESSAGE,
59        'ispublic'      => media_ispublic($MEDIA),
60    );
61
62    // handle the file status
63    $evt = new Doku_Event('FETCH_MEDIA_STATUS', $data);
64    if($evt->advise_before()) {
65        // redirects
66        if($data['status'] > 300 && $data['status'] <= 304) {
67            if (defined('SIMPLE_TEST')) return; //TestResponse doesn't recognize redirects
68            send_redirect($data['statusmessage']);
69        }
70        // send any non 200 status
71        if($data['status'] != 200) {
72            http_status($data['status'], $data['statusmessage']);
73        }
74        // die on errors
75        if($data['status'] > 203) {
76            print $data['statusmessage'];
77            if (defined('SIMPLE_TEST')) return;
78            exit;
79        }
80    }
81    $evt->advise_after();
82    unset($evt);
83
84    //handle image resizing/cropping/phpThumbing
85    if((substr($MIME, 0, 5) == 'image') && ($WIDTH || $HEIGHT)) {
86				if ($opt){
87						$data['file'] = $FILE = media_photogallery_image($data['file'],$EXT,$WIDTH,$HEIGHT,$opt);
88				} else {
89						if($HEIGHT && $WIDTH) {
90								$data['file'] = $FILE = media_crop_image($data['file'], $EXT, $WIDTH, $HEIGHT);
91						} else {
92								$data['file'] = $FILE = media_resize_image($data['file'], $EXT, $WIDTH, $HEIGHT);
93						}
94				}
95    }
96
97    // finally send the file to the client
98    $evt = new Doku_Event('MEDIA_SENDFILE', $data);
99    if($evt->advise_before()) {
100        sendFile($data['file'], $data['mime'], $data['download'], $data['cache'], $data['ispublic'], $data['orig']);
101    }
102    // Do something after the download finished.
103    $evt->advise_after();  // will not be emitted on 304 or x-sendfile
104} else{
105		$FILE = PHOTOGALLERY_IMAGES_FILE.$INPUT->str('src');
106		list($EXT, $MIME, $DL) = mimetype($FILE, false);
107		list($STATUS, $STATUSMESSAGE) = checkLocalFileStatus($FILE, $WIDTH, $HEIGHT);
108		// // send any non 200 status
109		if($STATUS != 200) {
110				http_status($STATUS, $STATUSMESSAGE);
111		}
112		if ($opt)
113				$FILE = media_photogallery_image($FILE,$EXT,$WIDTH,$HEIGHT,$opt);
114		else
115				$FILE = media_crop_image($FILE, $EXT, $WIDTH, $HEIGHT);
116		sendFile($FILE, $MIME, $DL, $CACHE, false, $FILE);
117}
118
119// END DO main
120
121/**
122 * Check local image file for preconditions and return correct status code
123 *
124 * READ: MIME, EXT, CACHE
125 * WRITE: FILE, array( STATUS, STATUSMESSAGE )
126 *
127 * @author Marco Nolletti
128 *
129 * @param string $file   reference to the file variable
130 * @param int    $width
131 * @param int    $height
132 * @return array as array(STATUS, STATUSMESSAGE)
133 */
134function checkLocalFileStatus($file, $width=0, $height=0) {
135    global $MIME, $EXT, $CACHE, $INPUT;
136
137    //media to local file
138		if(empty($file)) {
139				return array(400, 'Bad request');
140		}
141		// check token for resized images
142		if (($width || $height) && media_get_token($file, $width, $height) !== $INPUT->str('tok')) {
143				return array(412, 'Precondition Failed');
144		}
145
146    //check file existance
147    if(!file_exists($file)) {
148        return array(404, 'Not Found');
149    }
150
151    return array(200, null);
152}
153
154function media_photogallery_image($file, $ext, $w, $h, $opt){
155
156	//die();
157	// create phpThumb object
158	$phpThumb = new phpThumb();
159
160	// this is very important when using a single object to process multiple images
161	$phpThumb->resetObject();
162
163	// set data source -- do this first, any settings must be made AFTER this call
164	$phpThumb->setSourceFilename($file);
165	// $phpThumb->setParameter('config_document_root', '/home/groups/p/ph/phpthumb/htdocs/');
166	// $phpThumb->setParameter('config_allow_src_above_docroot', true); // needed if you're working outside DOCUMENT_ROOT, in a temp dir for example
167	$phpThumb->setParameter('config_output_format', 'jpg');
168	$phpThumb->setParameter('config_imagemagick_path', '/usr/local/bin/convert');
169	$phpThumb->setParameter('config_temp_directory', DOKU_INC.'data/cache/');
170	$phpThumb->setParameter('config_prefer_imagemagick', true);
171	$phpThumb->setParameter('config_disable_debug',true);
172	$phpThumb->setParameter('config_cache_directory',null);
173	$phpThumb->setParameter('w', $w);
174	$phpThumb->setParameter('h', $h);
175	foreach (explode('!',$opt) as $par) {
176			preg_match('/^(.+)=(.+)$/', $par, $options);
177			$phpThumb->setParameter($options[1], $options[2]);
178	}
179
180	// generate & output thumbnail
181	$output_filename = getCacheName($file,'.media.'.$w.'x'.$h.'.photogallery.'.$phpThumb->config_output_format);
182
183	if ($phpThumb->GenerateThumbnail()) { // this line is VERY important, do not remove it!
184		if ($output_filename) {
185			if ($phpThumb->RenderToFile($output_filename)) {
186				// do something on success
187				return $output_filename;
188				//echo 'Successfully rendered:<br><img src="'.$output_filename.'">';
189			} else {
190				// do something with debug/error messages
191				echo 'Failed (size='.$thumbnail_width.'):<pre>'.implode("\n\n", $phpThumb->debugmessages).'</pre>';
192			}
193			$phpThumb->purgeTempFiles();
194		} else {
195			$phpThumb->OutputThumbnail();
196		}
197	} else {
198		// do something with error messages
199		echo 'Failed (size='.$thumbnail_width.').<br>';
200		echo '<div style="background-color:#FFEEDD; font-weight: bold; padding: 10px;">'.$phpThumb->fatalerror.'</div>';
201		echo '<form><textarea rows="10" cols="60" wrap="off">'.htmlentities(implode("\n* ", $phpThumb->debugmessages)).'</textarea></form><hr>';
202	}
203}