Blame view

sources/lib/private/preview.php 18.2 KB
31b7f2792   Kload   Upgrade to ownclo...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  <?php
  /**
   * Copyright (c) 2013 Frank Karlitschek frank@owncloud.org
   * Copyright (c) 2013 Georg Ehrke georg@ownCloud.com
   * This file is licensed under the Affero General Public License version 3 or
   * later.
   * See the COPYING-README file.
   *
   * Thumbnails:
   * structure of filename:
   * /data/user/thumbnails/pathhash/x-y.png
   *
   */
  namespace OC;
6d9380f96   Cédric Dupont   Update sources OC...
15
  use OC\Preview\Provider;
31b7f2792   Kload   Upgrade to ownclo...
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
  require_once 'preview/image.php';
  require_once 'preview/movies.php';
  require_once 'preview/mp3.php';
  require_once 'preview/pdf.php';
  require_once 'preview/svg.php';
  require_once 'preview/txt.php';
  require_once 'preview/unknown.php';
  require_once 'preview/office.php';
  
  class Preview {
  	//the thumbnail folder
  	const THUMBNAILS_FOLDER = 'thumbnails';
  
  	//config
  	private $maxScaleFactor;
  	private $configMaxX;
  	private $configMaxY;
  
  	//fileview object
  	private $fileView = null;
  	private $userView = null;
  
  	//vars
  	private $file;
  	private $maxX;
  	private $maxY;
6d9380f96   Cédric Dupont   Update sources OC...
42
43
44
45
46
47
48
  	private $scalingUp;
  	private $mimeType;
  	private $keepAspect = false;
  
  	//filemapper used for deleting previews
  	// index is path, value is fileinfo
  	static public $deleteFileMapper = array();
31b7f2792   Kload   Upgrade to ownclo...
49

31b7f2792   Kload   Upgrade to ownclo...
50
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
51
52
  	 * preview images object
  	 *
31b7f2792   Kload   Upgrade to ownclo...
53
54
55
56
57
58
59
60
61
  	 * @var \OC_Image
  	 */
  	private $preview;
  
  	//preview providers
  	static private $providers = array();
  	static private $registeredProviders = array();
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
62
63
64
65
66
67
  	 * @var \OCP\Files\FileInfo
  	 */
  	protected $info;
  
  	/**
  	 * check if thumbnail or bigger version of thumbnail of file is cached
31b7f2792   Kload   Upgrade to ownclo...
68
69
70
71
72
73
  	 * @param string $user userid - if no user is given, OC_User::getUser will be used
  	 * @param string $root path of root
  	 * @param string $file The path to the file where you want a thumbnail from
  	 * @param int $maxX The maximum X size of the thumbnail. It can be smaller depending on the shape of the image
  	 * @param int $maxY The maximum Y size of the thumbnail. It can be smaller depending on the shape of the image
  	 * @param bool $scalingUp Disable/Enable upscaling of previews
6d9380f96   Cédric Dupont   Update sources OC...
74
  	 * @throws \Exception
31b7f2792   Kload   Upgrade to ownclo...
75
  	 * @return mixed (bool / string)
6d9380f96   Cédric Dupont   Update sources OC...
76
77
78
79
  	 *                    false if thumbnail does not exist
  	 *                    path to thumbnail if thumbnail exists
  	 */
  	public function __construct($user = '', $root = '/', $file = '', $maxX = 1, $maxY = 1, $scalingUp = true) {
31b7f2792   Kload   Upgrade to ownclo...
80
  		//init fileviews
6d9380f96   Cédric Dupont   Update sources OC...
81
  		if ($user === '') {
31b7f2792   Kload   Upgrade to ownclo...
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
  			$user = \OC_User::getUser();
  		}
  		$this->fileView = new \OC\Files\View('/' . $user . '/' . $root);
  		$this->userView = new \OC\Files\View('/' . $user);
  
  		//set config
  		$this->configMaxX = \OC_Config::getValue('preview_max_x', null);
  		$this->configMaxY = \OC_Config::getValue('preview_max_y', null);
  		$this->maxScaleFactor = \OC_Config::getValue('preview_max_scale_factor', 2);
  
  		//save parameters
  		$this->setFile($file);
  		$this->setMaxX($maxX);
  		$this->setMaxY($maxY);
  		$this->setScalingUp($scalingUp);
  
  		$this->preview = null;
  
  		//check if there are preview backends
6d9380f96   Cédric Dupont   Update sources OC...
101
  		if (empty(self::$providers)) {
31b7f2792   Kload   Upgrade to ownclo...
102
103
  			self::initProviders();
  		}
6d9380f96   Cédric Dupont   Update sources OC...
104
  		if (empty(self::$providers)) {
31b7f2792   Kload   Upgrade to ownclo...
105
106
107
108
109
110
  			\OC_Log::write('core', 'No preview providers exist', \OC_Log::ERROR);
  			throw new \Exception('No preview providers');
  		}
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
111
  	 * returns the path of the file you want a thumbnail from
31b7f2792   Kload   Upgrade to ownclo...
112
  	 * @return string
6d9380f96   Cédric Dupont   Update sources OC...
113
114
  	 */
  	public function getFile() {
31b7f2792   Kload   Upgrade to ownclo...
115
116
117
118
  		return $this->file;
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
119
  	 * returns the max width of the preview
31b7f2792   Kload   Upgrade to ownclo...
120
  	 * @return integer
6d9380f96   Cédric Dupont   Update sources OC...
121
  	 */
31b7f2792   Kload   Upgrade to ownclo...
122
123
124
125
126
  	public function getMaxX() {
  		return $this->maxX;
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
127
  	 * returns the max height of the preview
31b7f2792   Kload   Upgrade to ownclo...
128
  	 * @return integer
6d9380f96   Cédric Dupont   Update sources OC...
129
  	 */
31b7f2792   Kload   Upgrade to ownclo...
130
131
132
133
134
  	public function getMaxY() {
  		return $this->maxY;
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
135
  	 * returns whether or not scalingup is enabled
31b7f2792   Kload   Upgrade to ownclo...
136
  	 * @return bool
6d9380f96   Cédric Dupont   Update sources OC...
137
  	 */
31b7f2792   Kload   Upgrade to ownclo...
138
  	public function getScalingUp() {
6d9380f96   Cédric Dupont   Update sources OC...
139
  		return $this->scalingUp;
31b7f2792   Kload   Upgrade to ownclo...
140
141
142
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
143
  	 * returns the name of the thumbnailfolder
31b7f2792   Kload   Upgrade to ownclo...
144
  	 * @return string
6d9380f96   Cédric Dupont   Update sources OC...
145
  	 */
31b7f2792   Kload   Upgrade to ownclo...
146
147
148
149
150
  	public function getThumbnailsFolder() {
  		return self::THUMBNAILS_FOLDER;
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
151
152
153
  	 * returns the max scale factor
  	 * @return string
  	 */
31b7f2792   Kload   Upgrade to ownclo...
154
155
156
157
158
  	public function getMaxScaleFactor() {
  		return $this->maxScaleFactor;
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
159
160
161
  	 * returns the max width set in ownCloud's config
  	 * @return string
  	 */
31b7f2792   Kload   Upgrade to ownclo...
162
163
164
165
166
  	public function getConfigMaxX() {
  		return $this->configMaxX;
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
167
168
169
  	 * returns the max height set in ownCloud's config
  	 * @return string
  	 */
31b7f2792   Kload   Upgrade to ownclo...
170
171
172
173
174
  	public function getConfigMaxY() {
  		return $this->configMaxY;
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
  	 * @return false|Files\FileInfo|\OCP\Files\FileInfo
  	 */
  	protected function getFileInfo() {
  		$absPath = $this->fileView->getAbsolutePath($this->file);
  		$absPath = Files\Filesystem::normalizePath($absPath);
  		if(array_key_exists($absPath, self::$deleteFileMapper)) {
  			$this->info = self::$deleteFileMapper[$absPath];
  		} else if (!$this->info) {
  			$this->info = $this->fileView->getFileInfo($this->file);
  		}
  		return $this->info;
  	}
  
  	/**
  	 * set the path of the file you want a thumbnail from
31b7f2792   Kload   Upgrade to ownclo...
190
  	 * @param string $file
6d9380f96   Cédric Dupont   Update sources OC...
191
192
  	 * @return \OC\Preview $this
  	 */
31b7f2792   Kload   Upgrade to ownclo...
193
194
  	public function setFile($file) {
  		$this->file = $file;
6d9380f96   Cédric Dupont   Update sources OC...
195
  		$this->info = null;
31b7f2792   Kload   Upgrade to ownclo...
196
  		if ($file !== '') {
6d9380f96   Cédric Dupont   Update sources OC...
197
198
199
200
  			$this->getFileInfo();
  			if($this->info !== null && $this->info !== false) {
  				$this->mimeType = $this->info->getMimetype();
  			}
31b7f2792   Kload   Upgrade to ownclo...
201
202
203
204
205
  		}
  		return $this;
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
206
207
  	 * set mime type explicitly
  	 * @param string $mimeType
31b7f2792   Kload   Upgrade to ownclo...
208
  	 */
6d9380f96   Cédric Dupont   Update sources OC...
209
210
  	public function setMimetype($mimeType) {
  		$this->mimeType = $mimeType;
31b7f2792   Kload   Upgrade to ownclo...
211
212
213
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
214
  	 * set the the max width of the preview
31b7f2792   Kload   Upgrade to ownclo...
215
  	 * @param int $maxX
6d9380f96   Cédric Dupont   Update sources OC...
216
217
218
219
220
  	 * @throws \Exception
  	 * @return \OC\Preview $this
  	 */
  	public function setMaxX($maxX = 1) {
  		if ($maxX <= 0) {
31b7f2792   Kload   Upgrade to ownclo...
221
222
223
  			throw new \Exception('Cannot set width of 0 or smaller!');
  		}
  		$configMaxX = $this->getConfigMaxX();
6d9380f96   Cédric Dupont   Update sources OC...
224
225
  		if (!is_null($configMaxX)) {
  			if ($maxX > $configMaxX) {
31b7f2792   Kload   Upgrade to ownclo...
226
227
228
229
230
231
232
233
234
  				\OC_Log::write('core', 'maxX reduced from ' . $maxX . ' to ' . $configMaxX, \OC_Log::DEBUG);
  				$maxX = $configMaxX;
  			}
  		}
  		$this->maxX = $maxX;
  		return $this;
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
235
  	 * set the the max height of the preview
31b7f2792   Kload   Upgrade to ownclo...
236
  	 * @param int $maxY
6d9380f96   Cédric Dupont   Update sources OC...
237
238
239
240
241
  	 * @throws \Exception
  	 * @return \OC\Preview $this
  	 */
  	public function setMaxY($maxY = 1) {
  		if ($maxY <= 0) {
31b7f2792   Kload   Upgrade to ownclo...
242
243
244
  			throw new \Exception('Cannot set height of 0 or smaller!');
  		}
  		$configMaxY = $this->getConfigMaxY();
6d9380f96   Cédric Dupont   Update sources OC...
245
246
  		if (!is_null($configMaxY)) {
  			if ($maxY > $configMaxY) {
31b7f2792   Kload   Upgrade to ownclo...
247
248
249
250
251
252
253
254
255
  				\OC_Log::write('core', 'maxX reduced from ' . $maxY . ' to ' . $configMaxY, \OC_Log::DEBUG);
  				$maxY = $configMaxY;
  			}
  		}
  		$this->maxY = $maxY;
  		return $this;
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
256
  	 * set whether or not scalingup is enabled
31b7f2792   Kload   Upgrade to ownclo...
257
  	 * @param bool $scalingUp
6d9380f96   Cédric Dupont   Update sources OC...
258
259
  	 * @return \OC\Preview $this
  	 */
31b7f2792   Kload   Upgrade to ownclo...
260
  	public function setScalingup($scalingUp) {
6d9380f96   Cédric Dupont   Update sources OC...
261
  		if ($this->getMaxScaleFactor() === 1) {
31b7f2792   Kload   Upgrade to ownclo...
262
263
  			$scalingUp = false;
  		}
6d9380f96   Cédric Dupont   Update sources OC...
264
265
266
267
268
269
  		$this->scalingUp = $scalingUp;
  		return $this;
  	}
  
  	public function setKeepAspect($keepAspect) {
  		$this->keepAspect = $keepAspect;
31b7f2792   Kload   Upgrade to ownclo...
270
271
272
273
  		return $this;
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
274
  	 * check if all parameters are valid
31b7f2792   Kload   Upgrade to ownclo...
275
  	 * @return bool
6d9380f96   Cédric Dupont   Update sources OC...
276
  	 */
31b7f2792   Kload   Upgrade to ownclo...
277
278
  	public function isFileValid() {
  		$file = $this->getFile();
6d9380f96   Cédric Dupont   Update sources OC...
279
  		if ($file === '') {
31b7f2792   Kload   Upgrade to ownclo...
280
281
282
  			\OC_Log::write('core', 'No filename passed', \OC_Log::DEBUG);
  			return false;
  		}
6d9380f96   Cédric Dupont   Update sources OC...
283
  		if (!$this->fileView->file_exists($file)) {
31b7f2792   Kload   Upgrade to ownclo...
284
285
286
287
288
289
290
291
  			\OC_Log::write('core', 'File:"' . $file . '" not found', \OC_Log::DEBUG);
  			return false;
  		}
  
  		return true;
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
292
  	 * deletes previews of a file with specific x and y
31b7f2792   Kload   Upgrade to ownclo...
293
  	 * @return bool
6d9380f96   Cédric Dupont   Update sources OC...
294
  	 */
31b7f2792   Kload   Upgrade to ownclo...
295
296
  	public function deletePreview() {
  		$file = $this->getFile();
6d9380f96   Cédric Dupont   Update sources OC...
297
298
299
  		$fileInfo = $this->getFileInfo($file);
  		if($fileInfo !== null && $fileInfo !== false) {
  			$fileId = $fileInfo->getId();
31b7f2792   Kload   Upgrade to ownclo...
300

6d9380f96   Cédric Dupont   Update sources OC...
301
302
303
304
  			$previewPath = $this->buildCachePath($fileId);
  			return $this->userView->unlink($previewPath);
  		}
  		return false;
31b7f2792   Kload   Upgrade to ownclo...
305
306
307
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
308
  	 * deletes all previews of a file
31b7f2792   Kload   Upgrade to ownclo...
309
  	 * @return bool
6d9380f96   Cédric Dupont   Update sources OC...
310
  	 */
31b7f2792   Kload   Upgrade to ownclo...
311
312
  	public function deleteAllPreviews() {
  		$file = $this->getFile();
6d9380f96   Cédric Dupont   Update sources OC...
313
314
315
  		$fileInfo = $this->getFileInfo($file);
  		if($fileInfo !== null && $fileInfo !== false) {
  			$fileId = $fileInfo->getId();
31b7f2792   Kload   Upgrade to ownclo...
316

6d9380f96   Cédric Dupont   Update sources OC...
317
318
319
320
321
  			$previewPath = $this->getThumbnailsFolder() . '/' . $fileId . '/';
  			$this->userView->deleteAll($previewPath);
  			return $this->userView->rmdir($previewPath);
  		}
  		return false;
31b7f2792   Kload   Upgrade to ownclo...
322
323
324
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
325
326
327
328
329
330
331
332
  	 * check if thumbnail or bigger version of thumbnail of file is cached
  	 * @param int $fileId fileId of the original image
  	 * @return string|false path to thumbnail if it exists or false
  	 */
  	public function isCached($fileId) {
  		if (is_null($fileId)) {
  			return false;
  		}
31b7f2792   Kload   Upgrade to ownclo...
333

6d9380f96   Cédric Dupont   Update sources OC...
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
  		$preview = $this->buildCachePath($fileId);
  
  		//does a preview with the wanted height and width already exist?
  		if ($this->userView->file_exists($preview)) {
  			return $preview;
  		}
  
  		return $this->isCachedBigger($fileId);
  	}
  
  	/**
  	 * check if a bigger version of thumbnail of file is cached
  	 * @param int $fileId fileId of the original image
  	 * @return string|false path to bigger thumbnail if it exists or false
  	*/
  	private function isCachedBigger($fileId) {
31b7f2792   Kload   Upgrade to ownclo...
350

6d9380f96   Cédric Dupont   Update sources OC...
351
  		if (is_null($fileId)) {
31b7f2792   Kload   Upgrade to ownclo...
352
353
  			return false;
  		}
6d9380f96   Cédric Dupont   Update sources OC...
354
355
  		// in order to not loose quality we better generate aspect preserving previews from the original file
  		if ($this->keepAspect) {
31b7f2792   Kload   Upgrade to ownclo...
356
357
  			return false;
  		}
6d9380f96   Cédric Dupont   Update sources OC...
358
359
360
361
362
363
364
365
366
367
368
  		$maxX = $this->getMaxX();
  
  		//array for usable cached thumbnails
  		$possibleThumbnails = $this->getPossibleThumbnails($fileId);
  
  		foreach ($possibleThumbnails as $width => $path) {
  			if ($width < $maxX) {
  				continue;
  			} else {
  				return $path;
  			}
31b7f2792   Kload   Upgrade to ownclo...
369
  		}
6d9380f96   Cédric Dupont   Update sources OC...
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
  		return false;
  	}
  
  	/**
  	 * get possible bigger thumbnails of the given image
  	 * @param int $fileId fileId of the original image
  	 * @return array an array of paths to bigger thumbnails
  	*/
  	private function getPossibleThumbnails($fileId) {
  
  		if (is_null($fileId)) {
  			return array();
  		}
  
  		$previewPath = $this->getThumbnailsFolder() . '/' . $fileId . '/';
  
  		$wantedAspectRatio = (float) ($this->getMaxX() / $this->getMaxY());
31b7f2792   Kload   Upgrade to ownclo...
387
388
389
390
391
  
  		//array for usable cached thumbnails
  		$possibleThumbnails = array();
  
  		$allThumbnails = $this->userView->getDirectoryContent($previewPath);
6d9380f96   Cédric Dupont   Update sources OC...
392
  		foreach ($allThumbnails as $thumbnail) {
31b7f2792   Kload   Upgrade to ownclo...
393
  			$name = rtrim($thumbnail['name'], '.png');
6d9380f96   Cédric Dupont   Update sources OC...
394
  			list($x, $y, $aspectRatio) = $this->getDimensionsFromFilename($name);
31b7f2792   Kload   Upgrade to ownclo...
395

6d9380f96   Cédric Dupont   Update sources OC...
396
397
398
  			if (abs($aspectRatio - $wantedAspectRatio) >= 0.000001
  				|| $this->unscalable($x, $y)
  			) {
31b7f2792   Kload   Upgrade to ownclo...
399
400
  				continue;
  			}
31b7f2792   Kload   Upgrade to ownclo...
401
402
  			$possibleThumbnails[$x] = $thumbnail['path'];
  		}
6d9380f96   Cédric Dupont   Update sources OC...
403
  		ksort($possibleThumbnails);
31b7f2792   Kload   Upgrade to ownclo...
404

6d9380f96   Cédric Dupont   Update sources OC...
405
406
  		return $possibleThumbnails;
  	}
31b7f2792   Kload   Upgrade to ownclo...
407

6d9380f96   Cédric Dupont   Update sources OC...
408
409
410
411
412
413
414
415
416
417
418
  	/**
  	 * @param string $name
  	 * @return array
  	 */
  	private function getDimensionsFromFilename($name) {
  			$size = explode('-', $name);
  			$x = (int) $size[0];
  			$y = (int) $size[1];
  			$aspectRatio = (float) ($x / $y);
  			return array($x, $y, $aspectRatio);
  	}
31b7f2792   Kload   Upgrade to ownclo...
419

6d9380f96   Cédric Dupont   Update sources OC...
420
421
422
423
424
425
  	/**
  	 * @param int $x
  	 * @param int $y
  	 * @return bool
  	 */
  	private function unscalable($x, $y) {
31b7f2792   Kload   Upgrade to ownclo...
426

6d9380f96   Cédric Dupont   Update sources OC...
427
428
429
430
  		$maxX = $this->getMaxX();
  		$maxY = $this->getMaxY();
  		$scalingUp = $this->getScalingUp();
  		$maxScaleFactor = $this->getMaxScaleFactor();
31b7f2792   Kload   Upgrade to ownclo...
431

6d9380f96   Cédric Dupont   Update sources OC...
432
433
434
435
436
437
438
439
  		if ($x < $maxX || $y < $maxY) {
  			if ($scalingUp) {
  				$scalefactor = $maxX / $x;
  				if ($scalefactor > $maxScaleFactor) {
  					return true;
  				}
  			} else {
  				return true;
31b7f2792   Kload   Upgrade to ownclo...
440
441
  			}
  		}
6d9380f96   Cédric Dupont   Update sources OC...
442
  		return false;
31b7f2792   Kload   Upgrade to ownclo...
443
444
445
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
446
  	 * return a preview of a file
31b7f2792   Kload   Upgrade to ownclo...
447
  	 * @return \OC_Image
6d9380f96   Cédric Dupont   Update sources OC...
448
  	 */
31b7f2792   Kload   Upgrade to ownclo...
449
  	public function getPreview() {
6d9380f96   Cédric Dupont   Update sources OC...
450
  		if (!is_null($this->preview) && $this->preview->valid()) {
31b7f2792   Kload   Upgrade to ownclo...
451
452
453
454
455
456
457
458
  			return $this->preview;
  		}
  
  		$this->preview = null;
  		$file = $this->getFile();
  		$maxX = $this->getMaxX();
  		$maxY = $this->getMaxY();
  		$scalingUp = $this->getScalingUp();
6d9380f96   Cédric Dupont   Update sources OC...
459
460
461
462
463
  		$fileInfo = $this->getFileInfo($file);
  		if($fileInfo === null || $fileInfo === false) {
  			return new \OC_Image();
  		}
  		$fileId = $fileInfo->getId();
31b7f2792   Kload   Upgrade to ownclo...
464

6d9380f96   Cédric Dupont   Update sources OC...
465
466
467
468
469
  		$cached = $this->isCached($fileId);
  		if ($cached) {
  			$stream = $this->userView->fopen($cached, 'r');
  			$image = new \OC_Image();
  			$image->loadFromFileHandle($stream);
31b7f2792   Kload   Upgrade to ownclo...
470
  			$this->preview = $image->valid() ? $image : null;
6d9380f96   Cédric Dupont   Update sources OC...
471

31b7f2792   Kload   Upgrade to ownclo...
472
  			$this->resizeAndCrop();
6d9380f96   Cédric Dupont   Update sources OC...
473
  			fclose($stream);
31b7f2792   Kload   Upgrade to ownclo...
474
  		}
6d9380f96   Cédric Dupont   Update sources OC...
475
  		if (is_null($this->preview)) {
31b7f2792   Kload   Upgrade to ownclo...
476
  			$preview = null;
6d9380f96   Cédric Dupont   Update sources OC...
477
478
  			foreach (self::$providers as $supportedMimeType => $provider) {
  				if (!preg_match($supportedMimeType, $this->mimeType)) {
31b7f2792   Kload   Upgrade to ownclo...
479
480
481
482
  					continue;
  				}
  
  				\OC_Log::write('core', 'Generating preview for "' . $file . '" with "' . get_class($provider) . '"', \OC_Log::DEBUG);
6d9380f96   Cédric Dupont   Update sources OC...
483
  				/** @var $provider Provider */
31b7f2792   Kload   Upgrade to ownclo...
484
  				$preview = $provider->getThumbnail($file, $maxX, $maxY, $scalingUp, $this->fileView);
6d9380f96   Cédric Dupont   Update sources OC...
485
  				if (!($preview instanceof \OC_Image)) {
31b7f2792   Kload   Upgrade to ownclo...
486
487
488
489
490
491
492
  					continue;
  				}
  
  				$this->preview = $preview;
  				$this->resizeAndCrop();
  
  				$previewPath = $this->getThumbnailsFolder() . '/' . $fileId . '/';
6d9380f96   Cédric Dupont   Update sources OC...
493
  				$cachePath = $this->buildCachePath($fileId);
31b7f2792   Kload   Upgrade to ownclo...
494

6d9380f96   Cédric Dupont   Update sources OC...
495
  				if ($this->userView->is_dir($this->getThumbnailsFolder() . '/') === false) {
31b7f2792   Kload   Upgrade to ownclo...
496
497
  					$this->userView->mkdir($this->getThumbnailsFolder() . '/');
  				}
6d9380f96   Cédric Dupont   Update sources OC...
498
  				if ($this->userView->is_dir($previewPath) === false) {
31b7f2792   Kload   Upgrade to ownclo...
499
500
501
502
503
504
505
506
  					$this->userView->mkdir($previewPath);
  				}
  
  				$this->userView->file_put_contents($cachePath, $preview->data());
  
  				break;
  			}
  		}
6d9380f96   Cédric Dupont   Update sources OC...
507
  		if (is_null($this->preview)) {
31b7f2792   Kload   Upgrade to ownclo...
508
509
510
511
512
513
514
  			$this->preview = new \OC_Image();
  		}
  
  		return $this->preview;
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
515
  	 * show preview
31b7f2792   Kload   Upgrade to ownclo...
516
  	 * @return void
6d9380f96   Cédric Dupont   Update sources OC...
517
518
  	 */
  	public function showPreview($mimeType = null) {
31b7f2792   Kload   Upgrade to ownclo...
519
  		\OCP\Response::enableCaching(3600 * 24); // 24 hours
6d9380f96   Cédric Dupont   Update sources OC...
520
  		if (is_null($this->preview)) {
31b7f2792   Kload   Upgrade to ownclo...
521
522
  			$this->getPreview();
  		}
6d9380f96   Cédric Dupont   Update sources OC...
523
  		$this->preview->show($mimeType);
31b7f2792   Kload   Upgrade to ownclo...
524
525
526
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
527
  	 * resize, crop and fix orientation
31b7f2792   Kload   Upgrade to ownclo...
528
  	 * @return void
6d9380f96   Cédric Dupont   Update sources OC...
529
  	 */
31b7f2792   Kload   Upgrade to ownclo...
530
531
532
533
534
  	private function resizeAndCrop() {
  		$image = $this->preview;
  		$x = $this->getMaxX();
  		$y = $this->getMaxY();
  		$scalingUp = $this->getScalingUp();
6d9380f96   Cédric Dupont   Update sources OC...
535
  		$maxScaleFactor = $this->getMaxScaleFactor();
31b7f2792   Kload   Upgrade to ownclo...
536

6d9380f96   Cédric Dupont   Update sources OC...
537
  		if (!($image instanceof \OC_Image)) {
31b7f2792   Kload   Upgrade to ownclo...
538
539
540
541
542
  			\OC_Log::write('core', '$this->preview is not an instance of OC_Image', \OC_Log::DEBUG);
  			return;
  		}
  
  		$image->fixOrientation();
6d9380f96   Cédric Dupont   Update sources OC...
543
544
545
546
547
548
549
550
551
552
553
554
555
  		$realX = (int)$image->width();
  		$realY = (int)$image->height();
  
  		// compute $maxY and $maxX using the aspect of the generated preview
  		if ($this->keepAspect) {
  			$ratio = $realX / $realY;
  			if($x / $ratio < $y) {
  				// width restricted
  				$y = $x / $ratio;
  			} else {
  				$x = $y * $ratio;
  			}
  		}
31b7f2792   Kload   Upgrade to ownclo...
556

6d9380f96   Cédric Dupont   Update sources OC...
557
  		if ($x === $realX && $y === $realY) {
31b7f2792   Kload   Upgrade to ownclo...
558
559
560
  			$this->preview = $image;
  			return;
  		}
6d9380f96   Cédric Dupont   Update sources OC...
561
562
  		$factorX = $x / $realX;
  		$factorY = $y / $realY;
31b7f2792   Kload   Upgrade to ownclo...
563

6d9380f96   Cédric Dupont   Update sources OC...
564
  		if ($factorX >= $factorY) {
31b7f2792   Kload   Upgrade to ownclo...
565
  			$factor = $factorX;
6d9380f96   Cédric Dupont   Update sources OC...
566
  		} else {
31b7f2792   Kload   Upgrade to ownclo...
567
568
  			$factor = $factorY;
  		}
6d9380f96   Cédric Dupont   Update sources OC...
569
570
  		if ($scalingUp === false) {
  			if ($factor > 1) {
31b7f2792   Kload   Upgrade to ownclo...
571
572
573
  				$factor = 1;
  			}
  		}
6d9380f96   Cédric Dupont   Update sources OC...
574
575
576
577
  		if (!is_null($maxScaleFactor)) {
  			if ($factor > $maxScaleFactor) {
  				\OC_Log::write('core', 'scale factor reduced from ' . $factor . ' to ' . $maxScaleFactor, \OC_Log::DEBUG);
  				$factor = $maxScaleFactor;
31b7f2792   Kload   Upgrade to ownclo...
578
579
  			}
  		}
6d9380f96   Cédric Dupont   Update sources OC...
580
581
  		$newXSize = (int)($realX * $factor);
  		$newYSize = (int)($realY * $factor);
31b7f2792   Kload   Upgrade to ownclo...
582

6d9380f96   Cédric Dupont   Update sources OC...
583
  		$image->preciseResize($newXSize, $newYSize);
31b7f2792   Kload   Upgrade to ownclo...
584

6d9380f96   Cédric Dupont   Update sources OC...
585
  		if ($newXSize === $x && $newYSize === $y) {
31b7f2792   Kload   Upgrade to ownclo...
586
587
588
  			$this->preview = $image;
  			return;
  		}
6d9380f96   Cédric Dupont   Update sources OC...
589
590
  		if ($newXSize >= $x && $newYSize >= $y) {
  			$cropX = floor(abs($x - $newXSize) * 0.5);
31b7f2792   Kload   Upgrade to ownclo...
591
592
593
594
595
596
597
598
599
  			//don't crop previews on the Y axis, this sucks if it's a document.
  			//$cropY = floor(abs($y - $newYsize) * 0.5);
  			$cropY = 0;
  
  			$image->crop($cropX, $cropY, $x, $y);
  
  			$this->preview = $image;
  			return;
  		}
6d9380f96   Cédric Dupont   Update sources OC...
600
601
602
603
  		if (($newXSize < $x || $newYSize < $y) && $scalingUp) {
  			if ($newXSize > $x) {
  				$cropX = floor(($newXSize - $x) * 0.5);
  				$image->crop($cropX, 0, $x, $newYSize);
31b7f2792   Kload   Upgrade to ownclo...
604
  			}
6d9380f96   Cédric Dupont   Update sources OC...
605
606
607
  			if ($newYSize > $y) {
  				$cropY = floor(($newYSize - $y) * 0.5);
  				$image->crop(0, $cropY, $newXSize, $y);
31b7f2792   Kload   Upgrade to ownclo...
608
  			}
6d9380f96   Cédric Dupont   Update sources OC...
609
610
  			$newXSize = (int)$image->width();
  			$newYSize = (int)$image->height();
31b7f2792   Kload   Upgrade to ownclo...
611
612
  
  			//create transparent background layer
6d9380f96   Cédric Dupont   Update sources OC...
613
614
615
  			$backgroundLayer = imagecreatetruecolor($x, $y);
  			$white = imagecolorallocate($backgroundLayer, 255, 255, 255);
  			imagefill($backgroundLayer, 0, 0, $white);
31b7f2792   Kload   Upgrade to ownclo...
616
617
  
  			$image = $image->resource();
6d9380f96   Cédric Dupont   Update sources OC...
618
619
  			$mergeX = floor(abs($x - $newXSize) * 0.5);
  			$mergeY = floor(abs($y - $newYSize) * 0.5);
31b7f2792   Kload   Upgrade to ownclo...
620

6d9380f96   Cédric Dupont   Update sources OC...
621
  			imagecopy($backgroundLayer, $image, $mergeX, $mergeY, 0, 0, $newXSize, $newYSize);
31b7f2792   Kload   Upgrade to ownclo...
622
623
624
  
  			//$black = imagecolorallocate(0,0,0);
  			//imagecolortransparent($transparentlayer, $black);
6d9380f96   Cédric Dupont   Update sources OC...
625
  			$image = new \OC_Image($backgroundLayer);
31b7f2792   Kload   Upgrade to ownclo...
626
627
628
629
630
631
632
  
  			$this->preview = $image;
  			return;
  		}
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
633
  	 * register a new preview provider to be used
31b7f2792   Kload   Upgrade to ownclo...
634
635
636
  	 * @param array $options
  	 * @return void
  	 */
6d9380f96   Cédric Dupont   Update sources OC...
637
638
  	public static function registerProvider($class, $options = array()) {
  		self::$registeredProviders[] = array('class' => $class, 'options' => $options);
31b7f2792   Kload   Upgrade to ownclo...
639
640
641
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
642
  	 * create instances of all the registered preview providers
31b7f2792   Kload   Upgrade to ownclo...
643
644
645
  	 * @return void
  	 */
  	private static function initProviders() {
6d9380f96   Cédric Dupont   Update sources OC...
646
  		if (!\OC_Config::getValue('enable_previews', true)) {
31b7f2792   Kload   Upgrade to ownclo...
647
648
649
650
  			$provider = new Preview\Unknown(array());
  			self::$providers = array($provider->getMimeType() => $provider);
  			return;
  		}
6d9380f96   Cédric Dupont   Update sources OC...
651
  		if (count(self::$providers) > 0) {
31b7f2792   Kload   Upgrade to ownclo...
652
653
  			return;
  		}
6d9380f96   Cédric Dupont   Update sources OC...
654
655
656
  		foreach (self::$registeredProviders as $provider) {
  			$class = $provider['class'];
  			$options = $provider['options'];
31b7f2792   Kload   Upgrade to ownclo...
657

6d9380f96   Cédric Dupont   Update sources OC...
658
  			/** @var $object Provider */
31b7f2792   Kload   Upgrade to ownclo...
659
660
661
662
663
664
665
666
667
668
  			$object = new $class($options);
  
  			self::$providers[$object->getMimeType()] = $object;
  		}
  
  		$keys = array_map('strlen', array_keys(self::$providers));
  		array_multisort($keys, SORT_DESC, self::$providers);
  	}
  
  	public static function post_write($args) {
6d9380f96   Cédric Dupont   Update sources OC...
669
670
671
672
673
  		self::post_delete($args, 'files/');
  	}
  
  	public static function prepare_delete_files($args) {
  		self::prepare_delete($args, 'files/');
31b7f2792   Kload   Upgrade to ownclo...
674
  	}
6d9380f96   Cédric Dupont   Update sources OC...
675
  	public static function prepare_delete($args, $prefix='') {
31b7f2792   Kload   Upgrade to ownclo...
676
  		$path = $args['path'];
6d9380f96   Cédric Dupont   Update sources OC...
677
  		if (substr($path, 0, 1) === '/') {
31b7f2792   Kload   Upgrade to ownclo...
678
679
  			$path = substr($path, 1);
  		}
6d9380f96   Cédric Dupont   Update sources OC...
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
  
  		$view = new \OC\Files\View('/' . \OC_User::getUser() . '/' . $prefix);
  		$info = $view->getFileInfo($path);
  
  		\OC\Preview::$deleteFileMapper = array_merge(
  			\OC\Preview::$deleteFileMapper,
  			array(
  				Files\Filesystem::normalizePath($view->getAbsolutePath($path)) => $info,
  			)
  		);
  	}
  
  	public static function post_delete_files($args) {
  		self::post_delete($args, 'files/');
  	}
  
  	public static function post_delete($args, $prefix='') {
  		$path = Files\Filesystem::normalizePath($args['path']);
  
  		$preview = new Preview(\OC_User::getUser(), $prefix, $path);
31b7f2792   Kload   Upgrade to ownclo...
700
701
  		$preview->deleteAllPreviews();
  	}
6d9380f96   Cédric Dupont   Update sources OC...
702
703
704
705
706
707
  	/**
  	 * @param string $mimeType
  	 * @return bool
  	 */
  	public static function isMimeSupported($mimeType) {
  		if (!\OC_Config::getValue('enable_previews', true)) {
31b7f2792   Kload   Upgrade to ownclo...
708
709
710
711
  			return false;
  		}
  
  		//check if there are preview backends
6d9380f96   Cédric Dupont   Update sources OC...
712
  		if (empty(self::$providers)) {
31b7f2792   Kload   Upgrade to ownclo...
713
714
715
716
717
  			self::initProviders();
  		}
  
  		//remove last element because it has the mimetype *
  		$providers = array_slice(self::$providers, 0, -1);
6d9380f96   Cédric Dupont   Update sources OC...
718
719
  		foreach ($providers as $supportedMimeType => $provider) {
  			if (preg_match($supportedMimeType, $mimeType)) {
31b7f2792   Kload   Upgrade to ownclo...
720
721
722
723
724
  				return true;
  			}
  		}
  		return false;
  	}
6d9380f96   Cédric Dupont   Update sources OC...
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
  
  	/**
  	 * @param int $fileId
  	 * @return string
  	 */
  	private function buildCachePath($fileId) {
  		$maxX = $this->getMaxX();
  		$maxY = $this->getMaxY();
  
  		$previewPath = $this->getThumbnailsFolder() . '/' . $fileId . '/';
  		$preview = $previewPath . $maxX . '-' . $maxY . '.png';
  		if ($this->keepAspect) {
  			$preview = $previewPath . $maxX . '-with-aspect.png';
  			return $preview;
  		}
  		return $preview;
  	}
31b7f2792   Kload   Upgrade to ownclo...
742
  }