Passed
Push — master ( ef3387...d0a4bc )
by Anthony
07:14
created

CKFinder_Connector_CommandHandler_Thumbnail::sendResponse()   F

Complexity

Conditions 16
Paths 2304

Size

Total Lines 81
Code Lines 46

Duplication

Lines 81
Ratio 100 %

Importance

Changes 0
Metric Value
cc 16
eloc 46
nc 2304
nop 0
dl 81
loc 81
rs 2.0759
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/*
3
* CKFinder
4
* ========
5
* http://ckfinder.com
6
* Copyright (C) 2007-2010, CKSource - Frederico Knabben. All rights reserved.
7
*
8
* The software, this file and its contents are subject to the CKFinder
9
* License. Please read the license.txt file before using, installing, copying,
10
* modifying or distribute this file or part of its contents. The contents of
11
* this file is part of the Source Code of CKFinder.
12
*/
13
if (!defined('IN_CKFINDER')) exit;
14
15
/**
16
 * @package CKFinder
17
 * @subpackage CommandHandlers
18
 * @copyright CKSource - Frederico Knabben
19
 */
20
21
/**
22
 * Handle Thumbnail command (create thumbnail if doesn't exist)
23
 *
24
 * @package CKFinder
25
 * @subpackage CommandHandlers
26
 * @copyright CKSource - Frederico Knabben
27
 */
28
class CKFinder_Connector_CommandHandler_Thumbnail extends CKFinder_Connector_CommandHandler_CommandHandlerBase
29
{
30
    /**
31
     * Command name
32
     *
33
     * @access private
34
     * @var string
35
     */
36
    var $command = "Thumbnail";
37
38
    /**
39
     * Send response
40
     * @access public
41
     *
42
     */
43
    function sendResponse()
44
    {
45
        if (!function_exists('ob_list_handlers') || ob_list_handlers()) {
46
            @ob_end_clean();
47
        }
48
        header("Content-Encoding: none");
49
50
        $this->checkConnector();
51
        $this->checkRequest();
52
53
        $_config =& CKFinder_Connector_Core_Factory::getInstance("Core_Config");
54
55
        $_thumbnails = $_config->getThumbnailsConfig();
56
        if (!$_thumbnails->getIsEnabled()) {
57
            $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_THUMBNAILS_DISABLED);
58
        }
59
60
        if (!$this->_currentFolder->checkAcl(CKFINDER_CONNECTOR_ACL_FILE_VIEW)) {
61
            $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_UNAUTHORIZED);
62
        }
63
64
        if (!isset($_GET["FileName"])) {
65
            $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_REQUEST);
66
        }
67
68
        $fileName = CKFinder_Connector_Utils_FileSystem::convertToFilesystemEncoding($_GET["FileName"]);
69
        $_resourceTypeInfo = $this->_currentFolder->getResourceTypeConfig();
70
71
        if (!CKFinder_Connector_Utils_FileSystem::checkFileName($fileName)) {
72
            $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_REQUEST);
73
        }
74
        $sourceFilePath = CKFinder_Connector_Utils_FileSystem::combinePaths($this->_currentFolder->getServerPath(), $fileName);
75
76
        if ($_resourceTypeInfo->checkIsHiddenFile($fileName) || !file_exists($sourceFilePath)) {
77
            $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_FILE_NOT_FOUND);
78
        }
79
80
        $thumbFilePath = CKFinder_Connector_Utils_FileSystem::combinePaths($this->_currentFolder->getThumbsServerPath(), $fileName);
81
82
        // If the thumbnail file doesn't exists, create it now.
83
        if (!file_exists($thumbFilePath)) {
84
            if(!$this->createThumb($sourceFilePath, $thumbFilePath, $_thumbnails->getMaxWidth(), $_thumbnails->getMaxHeight(), $_thumbnails->getQuality(), true, $_thumbnails->getBmpSupported())) {
85
                $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_ACCESS_DENIED);
86
            }
87
        }
88
89
        $size = filesize($thumbFilePath);
90
        $sourceImageAttr = getimagesize($thumbFilePath);
91
        $mime = $sourceImageAttr["mime"];
92
93
        $rtime = isset($_SERVER["HTTP_IF_MODIFIED_SINCE"])?strtotime($_SERVER["HTTP_IF_MODIFIED_SINCE"]):0;
94
        $mtime =  filemtime($thumbFilePath);
95
        $etag = dechex($mtime) . "-" . dechex($size);
96
97
        $is304 = false;
98
99
        if (isset($_SERVER["HTTP_IF_NONE_MATCH"]) && $_SERVER["HTTP_IF_NONE_MATCH"] === $etag) {
100
            $is304 = true;
101
        }
102
        else if($rtime == $mtime) {
103
            $is304 = true;
104
        }
105
106
        if ($is304) {
107
            header("HTTP/1.0 304 Not Modified");
108
            exit();
109
        }
110
111
        //header("Cache-Control: cache, must-revalidate");
112
        //header("Pragma: public");
113
        //header("Expires: 0");
114
        header('Cache-control: public');
115
        header('Etag: ' . $etag);
116
        header("Content-type: " . $mime . "; name=\"" . CKFinder_Connector_Utils_Misc::mbBasename($thumbFilePath) . "\"");
117
        header("Last-Modified: ".gmdate('D, d M Y H:i:s', $mtime) . " GMT");
118
        //header("Content-type: application/octet-stream; name=\"{$file}\"");
119
        //header("Content-Disposition: attachment; filename=\"{$file}\"");
120
        header("Content-Length: ".$size);
121
        readfile($thumbFilePath);
122
        exit;
123
    }
124
125
    /**
126
     * Create thumbnail
127
     *
128
     * @param string $sourceFile
129
     * @param string $targetFile
130
     * @param int $maxWidth
131
     * @param int $maxHeight
132
     * @param boolean $preserverAspectRatio
133
     * @param boolean $bmpSupported
134
     * @return boolean
135
     * @static
136
     * @access public
137
     */
138
    function createThumb($sourceFile, $targetFile, $maxWidth, $maxHeight, $quality, $preserverAspectRatio, $bmpSupported = false)
139
    {
140
        $sourceImageAttr = @getimagesize($sourceFile);
141
        if ($sourceImageAttr === false) {
142
            return false;
143
        }
144
        $sourceImageWidth = isset($sourceImageAttr[0]) ? $sourceImageAttr[0] : 0;
145
        $sourceImageHeight = isset($sourceImageAttr[1]) ? $sourceImageAttr[1] : 0;
146
        $sourceImageMime = isset($sourceImageAttr["mime"]) ? $sourceImageAttr["mime"] : "";
147
        $sourceImageBits = isset($sourceImageAttr["bits"]) ? $sourceImageAttr["bits"] : 8;
148
        $sourceImageChannels = isset($sourceImageAttr["channels"]) ? $sourceImageAttr["channels"] : 3;
149
150
        if (!$sourceImageWidth || !$sourceImageHeight || !$sourceImageMime) {
151
            return false;
152
        }
153
154
        $iFinalWidth = $maxWidth == 0 ? $sourceImageWidth : $maxWidth;
155
        $iFinalHeight = $maxHeight == 0 ? $sourceImageHeight : $maxHeight;
156
157
        if ($sourceImageWidth <= $iFinalWidth && $sourceImageHeight <= $iFinalHeight) {
158
            if ($sourceFile != $targetFile) {
159
                copy($sourceFile, $targetFile);
160
            }
161
            return true;
162
        }
163
164
        if ($preserverAspectRatio)
165
        {
166
            // Gets the best size for aspect ratio resampling
167
            $oSize = CKFinder_Connector_CommandHandler_Thumbnail::GetAspectRatioSize($iFinalWidth, $iFinalHeight, $sourceImageWidth, $sourceImageHeight );
168
        }
169
        else {
170
            $oSize = array('Width' => $iFinalWidth, 'Height' => $iFinalHeight);
171
        }
172
173
        CKFinder_Connector_Utils_Misc::setMemoryForImage($sourceImageWidth, $sourceImageHeight, $sourceImageBits, $sourceImageChannels);
174
175
        switch ($sourceImageAttr['mime'])
176
        {
177
            case 'image/gif':
178
                {
179
                    if (@imagetypes() & IMG_GIF) {
180
                        $oImage = @imagecreatefromgif($sourceFile);
181
                    } else {
182
                        $ermsg = 'GIF images are not supported';
183
                    }
184
                }
185
                break;
186
            case 'image/jpeg':
187
                {
188
                    if (@imagetypes() & IMG_JPG) {
189
                        $oImage = @imagecreatefromjpeg($sourceFile) ;
190
                    } else {
191
                        $ermsg = 'JPEG images are not supported';
192
                    }
193
                }
194
                break;
195
            case 'image/png':
196
                {
197
                    if (@imagetypes() & IMG_PNG) {
198
                        $oImage = @imagecreatefrompng($sourceFile) ;
199
                    } else {
200
                        $ermsg = 'PNG images are not supported';
201
                    }
202
                }
203
                break;
204
            case 'image/wbmp':
205
                {
206
                    if (@imagetypes() & IMG_WBMP) {
207
                        $oImage = @imagecreatefromwbmp($sourceFile);
208
                    } else {
209
                        $ermsg = 'WBMP images are not supported';
210
                    }
211
                }
212
                break;
213
            case 'image/bmp':
214
                {
215
                    /*
216
                    * This is sad that PHP doesn't support bitmaps.
217
                    * Anyway, we will use our custom function at least to display thumbnails.
218
                    * We'll not resize images this way (if $sourceFile === $targetFile),
219
                    * because user defined imagecreatefrombmp and imagecreatebmp are horribly slow
220
                    */
221
                    if ($bmpSupported && (@imagetypes() & IMG_JPG) && $sourceFile != $targetFile) {
222
                        $oImage = CKFinder_Connector_Utils_Misc::imageCreateFromBmp($sourceFile);
223
                    } else {
224
                        $ermsg = 'BMP/JPG images are not supported';
225
                    }
226
                }
227
                break;
228
            default:
229
                $ermsg = $sourceImageAttr['mime'].' images are not supported';
230
                break;
231
        }
232
233
        if (isset($ermsg) || false === $oImage) {
234
            return false;
235
        }
236
237
238
        $oThumbImage = imagecreatetruecolor($oSize["Width"], $oSize["Height"]);
239
        //imagecopyresampled($oThumbImage, $oImage, 0, 0, 0, 0, $oSize["Width"], $oSize["Height"], $sourceImageWidth, $sourceImageHeight);
240
        CKFinder_Connector_Utils_Misc::fastImageCopyResampled($oThumbImage, $oImage, 0, 0, 0, 0, $oSize["Width"], $oSize["Height"], $sourceImageWidth, $sourceImageHeight, (int)max(floor($quality/20), 1));
241
242
        switch ($sourceImageAttr['mime'])
243
        {
244
            case 'image/gif':
245
                imagegif($oThumbImage, $targetFile);
246
                break;
247
            case 'image/jpeg':
248
            case 'image/bmp':
249
                imagejpeg($oThumbImage, $targetFile, $quality);
250
                break;
251
            case 'image/png':
252
                imagepng($oThumbImage, $targetFile);
253
                break;
254
            case 'image/wbmp':
255
                imagewbmp($oThumbImage, $targetFile);
256
                break;
257
        }
258
259
        $_config =& CKFinder_Connector_Core_Factory::getInstance("Core_Config");
260
        if (file_exists($targetFile) && ($perms = $_config->getChmodFiles())) {
261
            $oldUmask = umask(0);
262
            chmod($targetFile, $perms);
263
            umask($oldUmask);
264
        }
265
266
        imageDestroy($oImage);
267
        imageDestroy($oThumbImage);
268
269
        return true;
270
    }
271
272
273
274
    /**
275
     * Return aspect ratio size, returns associative array:
276
     * <pre>
277
     * Array
278
     * (
279
     *      [Width] => 80
280
     *      [Heigth] => 120
281
     * )
282
     * </pre>
283
     *
284
     * @param int $maxWidth
285
     * @param int $maxHeight
286
     * @param int $actualWidth
287
     * @param int $actualHeight
288
     * @return array
289
     * @static
290
     * @access public
291
     */
292
    function getAspectRatioSize($maxWidth, $maxHeight, $actualWidth, $actualHeight)
293
    {
294
        $oSize = array("Width"=>$maxWidth, "Height"=>$maxHeight);
295
296
        // Calculates the X and Y resize factors
297
        $iFactorX = (float)$maxWidth / (float)$actualWidth;
298
        $iFactorY = (float)$maxHeight / (float)$actualHeight;
299
300
        // If some dimension have to be scaled
301
        if ($iFactorX != 1 || $iFactorY != 1)
302
        {
303
            // Uses the lower Factor to scale the oposite size
304
            if ($iFactorX < $iFactorY) {
305
                $oSize["Height"] = (int)round($actualHeight * $iFactorX);
306
            }
307
            else if ($iFactorX > $iFactorY) {
308
                $oSize["Width"] = (int)round($actualWidth * $iFactorY);
309
            }
310
        }
311
312
        if ($oSize["Height"] <= 0) {
313
            $oSize["Height"] = 1;
314
        }
315
        if ($oSize["Width"] <= 0) {
316
            $oSize["Width"] = 1;
317
        }
318
319
        // Returns the Size
320
        return $oSize;
321
    }
322
}
323