Subversion-Projekte lars-tiefland.laravel_shop

Revision

Revision 728 | Revision 1558 | Zur aktuellen Revision | Ganze Datei anzeigen | Leerzeichen ignorieren | Details | Blame | Letzte Änderung | Log anzeigen | RSS feed

Revision 728 Revision 1549
Zeile 1... Zeile 1...
1
<?php
1
<?php
Zeile 2... Zeile 2...
2
 
2
 
Zeile 3... Zeile 3...
3
namespace App\Http\Controllers;
3
    namespace App\Http\Controllers;
Zeile 4... Zeile 4...
4
 
4
 
-
 
5
    use Illuminate\Http\Request;
-
 
6
 
-
 
7
    class MediumController extends Controller
-
 
8
    {
-
 
9
 
-
 
10
        protected $options;
-
 
11
 
-
 
12
        // PHP File Upload error message codes:
-
 
13
        // https://php.net/manual/en/features.file-upload.errors.php
-
 
14
        protected $error_messages = array(
-
 
15
            1                     => 'The uploaded file exceeds the upload_max_filesize directive in php.ini',
-
 
16
            2                     => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form',
-
 
17
            3                     => 'The uploaded file was only partially uploaded',
-
 
18
            4                     => 'No file was uploaded',
-
 
19
            6                     => 'Missing a temporary folder',
-
 
20
            7                     => 'Failed to write file to disk',
-
 
21
            8                     => 'A PHP extension stopped the file upload',
-
 
22
            'post_max_size'       => 'The uploaded file exceeds the post_max_size directive in php.ini',
-
 
23
            'max_file_size'       => 'File is too big',
-
 
24
            'min_file_size'       => 'File is too small',
-
 
25
            'accept_file_types'   => 'Filetype not allowed',
-
 
26
            'max_number_of_files' => 'Maximum number of files exceeded',
-
 
27
            'invalid_file_type'   => 'Invalid file type',
-
 
28
            'max_width'           => 'Image exceeds maximum width',
-
 
29
            'min_width'           => 'Image requires a minimum width',
-
 
30
            'max_height'          => 'Image exceeds maximum height',
-
 
31
            'min_height'          => 'Image requires a minimum height',
-
 
32
            'abort'               => 'File upload aborted',
-
 
33
            'image_resize'        => 'Failed to resize image'
-
 
34
        );
-
 
35
 
-
 
36
        const IMAGETYPE_GIF  = 'image/gif';
-
 
37
        const IMAGETYPE_JPEG = 'image/jpeg';
-
 
38
        const IMAGETYPE_PNG  = 'image/png';
5
use Illuminate\Http\Request;
39
 
-
 
40
        protected $image_objects = array();
-
 
41
        protected $response      = array();
-
 
42
 
-
 
43
        public function __construct( $options = null, $initialize = true, $error_messages = null )
-
 
44
        {
-
 
45
            $this->options = array(
-
 
46
                'script_url'                       => $this->get_full_url() . '/' . $this->basename( $this->get_server_var( 'SCRIPT_NAME' ) ),
-
 
47
                'upload_dir'                       => dirname( $this->get_server_var( 'SCRIPT_FILENAME' ) ) . '/files/',
-
 
48
                'upload_url'                       => $this->get_full_url() . '/files/',
-
 
49
                'input_stream'                     => 'php://input',
-
 
50
                'user_dirs'                        => false,
-
 
51
                'mkdir_mode'                       => 0755,
-
 
52
                'param_name'                       => 'files',
-
 
53
                // Set the following option to 'POST', if your server does not support
-
 
54
                // DELETE requests. This is a parameter sent to the client:
-
 
55
                'delete_type'                      => 'DELETE',
-
 
56
                'access_control_allow_origin'      => '*',
-
 
57
                'access_control_allow_credentials' => false,
-
 
58
                'access_control_allow_methods'     => array(
-
 
59
                    'OPTIONS',
-
 
60
                    'HEAD',
-
 
61
                    'GET',
-
 
62
                    'POST',
-
 
63
                    'PUT',
-
 
64
                    'PATCH',
-
 
65
                    'DELETE'
-
 
66
                ),
-
 
67
                'access_control_allow_headers'     => array(
-
 
68
                    'Content-Type',
-
 
69
                    'Content-Range',
-
 
70
                    'Content-Disposition'
-
 
71
                ),
-
 
72
                // By default, allow redirects to the referer protocol+host:
-
 
73
                'redirect_allow_target'            => '/^' . preg_quote(
-
 
74
                        parse_url( $this->get_server_var( 'HTTP_REFERER' ), PHP_URL_SCHEME )
-
 
75
                        . '://'
-
 
76
                        . parse_url( $this->get_server_var( 'HTTP_REFERER' ), PHP_URL_HOST )
-
 
77
                        . '/', // Trailing slash to not match subdomains by mistake
-
 
78
                        '/' // preg_quote delimiter param
-
 
79
                    ) . '/',
-
 
80
                // Enable to provide file downloads via GET requests to the PHP script:
-
 
81
                //     1. Set to 1 to download files via readfile method through PHP
-
 
82
                //     2. Set to 2 to send a X-Sendfile header for lighttpd/Apache
-
 
83
                //     3. Set to 3 to send a X-Accel-Redirect header for nginx
-
 
84
                // If set to 2 or 3, adjust the upload_url option to the base path of
-
 
85
                // the redirect parameter, e.g. '/files/'.
-
 
86
                'download_via_php'                 => false,
-
 
87
                // Read files in chunks to avoid memory limits when download_via_php
-
 
88
                // is enabled, set to 0 to disable chunked reading of files:
-
 
89
                'readfile_chunk_size'              => 10 * 1024 * 1024, // 10 MiB
-
 
90
                // Defines which files can be displayed inline when downloaded:
-
 
91
                'inline_file_types'                => '/\.(gif|jpe?g|png)$/i',
-
 
92
                // Defines which files (based on their names) are accepted for upload.
-
 
93
                // By default, only allows file uploads with image file extensions.
-
 
94
                // Only change this setting after making sure that any allowed file
-
 
95
                // types cannot be executed by the webserver in the files directory,
-
 
96
                // e.g. PHP scripts, nor executed by the browser when downloaded,
-
 
97
                // e.g. HTML files with embedded JavaScript code.
-
 
98
                // Please also read the SECURITY.md document in this repository.
-
 
99
                'accept_file_types'                => '/\.(gif|jpe?g|png)$/i',
-
 
100
                // Replaces dots in filenames with the given string.
-
 
101
                // Can be disabled by setting it to false or an empty string.
-
 
102
                // Note that this is a security feature for servers that support
-
 
103
                // multiple file extensions, e.g. the Apache AddHandler Directive:
-
 
104
                // https://httpd.apache.org/docs/current/mod/mod_mime.html#addhandler
-
 
105
                // Before disabling it, make sure that files uploaded with multiple
-
 
106
                // extensions cannot be executed by the webserver, e.g.
-
 
107
                // "example.php.png" with embedded PHP code, nor executed by the
-
 
108
                // browser when downloaded, e.g. "example.html.gif" with embedded
-
 
109
                // JavaScript code.
-
 
110
                'replace_dots_in_filenames'        => '-',
-
 
111
                // The php.ini settings upload_max_filesize and post_max_size
-
 
112
                // take precedence over the following max_file_size setting:
-
 
113
                'max_file_size'                    => null,
-
 
114
                'min_file_size'                    => 1,
-
 
115
                // The maximum number of files for the upload directory:
-
 
116
                'max_number_of_files'              => null,
-
 
117
                // Reads first file bytes to identify and correct file extensions:
-
 
118
                'correct_image_extensions'         => false,
-
 
119
                // Image resolution restrictions:
-
 
120
                'max_width'                        => null,
-
 
121
                'max_height'                       => null,
-
 
122
                'min_width'                        => 1,
-
 
123
                'min_height'                       => 1,
-
 
124
                // Set the following option to false to enable resumable uploads:
-
 
125
                'discard_aborted_uploads'          => true,
-
 
126
                // Set to 0 to use the GD library to scale and orient images,
-
 
127
                // set to 1 to use imagick (if installed, falls back to GD),
-
 
128
                // set to 2 to use the ImageMagick convert binary directly:
-
 
129
                'image_library'                    => 1,
-
 
130
                // Uncomment the following to define an array of resource limits
-
 
131
                // for imagick:
-
 
132
                /*
-
 
133
            'imagick_resource_limits' => array(
-
 
134
                imagick::RESOURCETYPE_MAP => 32,
-
 
135
                imagick::RESOURCETYPE_MEMORY => 32
-
 
136
            ),
-
 
137
            */
-
 
138
                // Command or path for to the ImageMagick convert binary:
-
 
139
                'convert_bin'                      => 'convert',
-
 
140
                // Uncomment the following to add parameters in front of each
-
 
141
                // ImageMagick convert call (the limit constraints seem only
-
 
142
                // to have an effect if put in front):
-
 
143
                /*
-
 
144
            'convert_params' => '-limit memory 32MiB -limit map 32MiB',
-
 
145
            */
-
 
146
                // Command or path for to the ImageMagick identify binary:
-
 
147
                'identify_bin'                     => 'identify',
-
 
148
                'image_versions'                   => array(
-
 
149
                    // The empty image version key defines options for the original image.
-
 
150
                    // Keep in mind: these image manipulations are inherited by all other image versions from this point onwards.
-
 
151
                    // Also note that the property 'no_cache' is not inherited, since it's not a manipulation.
-
 
152
                    ''          => array(
-
 
153
                        // Automatically rotate images based on EXIF meta data:
-
 
154
                        'auto_orient' => true
-
 
155
                    ),
-
 
156
                    // You can add arrays to generate different versions.
-
 
157
                    // The name of the key is the name of the version (example: 'medium').
-
 
158
                    // the array contains the options to apply.
-
 
159
                    /*
-
 
160
                'medium' => array(
-
 
161
                    'max_width' => 800,
-
 
162
                    'max_height' => 600
-
 
163
                ),
-
 
164
                */
-
 
165
                    'thumbnail' => array(
-
 
166
                        // Uncomment the following to use a defined directory for the thumbnails
-
 
167
                        // instead of a subdirectory based on the version identifier.
-
 
168
                        // Make sure that this directory doesn't allow execution of files if you
-
 
169
                        // don't pose any restrictions on the type of uploaded files, e.g. by
-
 
170
                        // copying the .htaccess file from the files directory for Apache:
-
 
171
                        //'upload_dir' => dirname($this->get_server_var('SCRIPT_FILENAME')).'/thumb/',
-
 
172
                        //'upload_url' => $this->get_full_url().'/thumb/',
-
 
173
                        // Uncomment the following to force the max
-
 
174
                        // dimensions and e.g. create square thumbnails:
-
 
175
                        // 'auto_orient' => true,
-
 
176
                        // 'crop' => true,
-
 
177
                        // 'jpeg_quality' => 70,
-
 
178
                        // 'no_cache' => true, (there's a caching option, but this remembers thumbnail sizes from a previous action!)
-
 
179
                        // 'strip' => true, (this strips EXIF tags, such as geolocation)
-
 
180
                        'max_width'  => 80, // either specify width, or set to 0. Then width is automatically adjusted - keeping aspect ratio to a specified max_height.
-
 
181
                        'max_height' => 80 // either specify height, or set to 0. Then height is automatically adjusted - keeping aspect ratio to a specified max_width.
-
 
182
                    )
-
 
183
                ),
-
 
184
                'print_response'                   => true
-
 
185
            );
-
 
186
            if ( $options )
-
 
187
            {
-
 
188
                $this->options = $options + $this->options;
-
 
189
            }
-
 
190
            if ( $error_messages )
-
 
191
            {
-
 
192
                $this->error_messages = $error_messages + $this->error_messages;
6
 
193
            }
-
 
194
        }
-
 
195
 
-
 
196
        //
-
 
197
        public function create()
-
 
198
        {
-
 
199
            $this->get( $this->options['print_response'] );
-
 
200
        }
-
 
201
 
-
 
202
        public function store()
-
 
203
        {
-
 
204
            $this->post( $this->options['print_response'] );
-
 
205
        }
-
 
206
 
-
 
207
        public function update()
-
 
208
        {
-
 
209
            $this->post( $this->options['print_response'] );
-
 
210
        }
-
 
211
 
-
 
212
        public function destroy()
-
 
213
        {
-
 
214
            $this->delete( $this->options['print_response'] );
-
 
215
        }
-
 
216
 
-
 
217
        protected function get_full_url(): string
-
 
218
        {
-
 
219
            $https = !empty( $_SERVER['HTTPS'] ) && strcasecmp( $_SERVER['HTTPS'], 'on' ) === 0 ||
-
 
220
                !empty( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) &&
-
 
221
                strcasecmp( $_SERVER['HTTP_X_FORWARDED_PROTO'], 'https' ) === 0;
-
 
222
            return
-
 
223
                ( $https ? 'https://' : 'http://' ) .
-
 
224
                ( !empty( $_SERVER['REMOTE_USER'] ) ? $_SERVER['REMOTE_USER'] . '@' : '' ) .
-
 
225
                ( $_SERVER['HTTP_HOST'] ?? ( $_SERVER['SERVER_NAME'] .
-
 
226
                    ( $https && $_SERVER['SERVER_PORT'] === 443 ||
-
 
227
                    $_SERVER['SERVER_PORT'] === 80 ? '' : ':' . $_SERVER['SERVER_PORT'] ) ) ) .
-
 
228
                substr( $_SERVER['SCRIPT_NAME'], 0, strrpos( $_SERVER['SCRIPT_NAME'], '/' ) );
-
 
229
        }
-
 
230
 
-
 
231
        protected function get_user_id()
-
 
232
        {
-
 
233
            @session_start();
-
 
234
            return session_id();
-
 
235
        }
-
 
236
 
-
 
237
        protected function get_user_path(): string
-
 
238
        {
-
 
239
            if ( $this->options['user_dirs'] )
-
 
240
            {
-
 
241
                return $this->get_user_id() . '/';
-
 
242
            }
-
 
243
            return '';
-
 
244
        }
-
 
245
 
-
 
246
        protected function get_upload_path( $file_name = null, $version = null ): string
-
 
247
        {
-
 
248
            $file_name = $file_name ? $file_name : '';
-
 
249
            if ( empty( $version ) )
-
 
250
            {
-
 
251
                $version_path = '';
-
 
252
            }
-
 
253
            else
-
 
254
            {
-
 
255
                $version_dir = @$this->options['image_versions'][$version]['upload_dir'];
-
 
256
                if ( $version_dir )
-
 
257
                {
-
 
258
                    return $version_dir . $this->get_user_path() . $file_name;
-
 
259
                }
-
 
260
                $version_path = $version . '/';
-
 
261
            }
-
 
262
            return $this->options['upload_dir'] . $this->get_user_path()
-
 
263
                . $version_path . $file_name;
-
 
264
        }
-
 
265
 
-
 
266
        protected function get_query_separator( $url ): string
-
 
267
        {
-
 
268
            return !str_contains( $url, '?' ) ? '?' : '&';
-
 
269
        }
-
 
270
 
-
 
271
        protected function get_download_url( $file_name, $version = null, $direct = false ): string
-
 
272
        {
-
 
273
            if ( !$direct && $this->options['download_via_php'] )
-
 
274
            {
-
 
275
                $url = $this->options['script_url']
-
 
276
                    . $this->get_query_separator( $this->options['script_url'] )
-
 
277
                    . $this->get_singular_param_name()
-
 
278
                    . '=' . rawurlencode( $file_name );
-
 
279
                if ( $version )
-
 
280
                {
-
 
281
                    $url .= '&version=' . rawurlencode( $version );
-
 
282
                }
-
 
283
                return $url . '&download=1';
-
 
284
            }
-
 
285
            if ( empty( $version ) )
-
 
286
            {
-
 
287
                $version_path = '';
-
 
288
            }
-
 
289
            else
-
 
290
            {
-
 
291
                $version_url = @$this->options['image_versions'][$version]['upload_url'];
-
 
292
                if ( $version_url )
-
 
293
                {
-
 
294
                    return $version_url . $this->get_user_path() . rawurlencode( $file_name );
-
 
295
                }
-
 
296
                $version_path = rawurlencode( $version ) . '/';
-
 
297
            }
-
 
298
            return $this->options['upload_url'] . $this->get_user_path()
-
 
299
                . $version_path . rawurlencode( $file_name );
-
 
300
        }
-
 
301
 
-
 
302
        protected function set_additional_file_properties( $file ): void
-
 
303
        {
-
 
304
            $file->deleteUrl = $this->options['script_url']
-
 
305
                . $this->get_query_separator( $this->options['script_url'] )
-
 
306
                . $this->get_singular_param_name()
-
 
307
                . '=' . rawurlencode( $file->name );
-
 
308
            $file->deleteType = $this->options['delete_type'];
-
 
309
            if ( $file->deleteType !== 'DELETE' )
-
 
310
            {
-
 
311
                $file->deleteUrl .= '&_method=DELETE';
-
 
312
            }
-
 
313
            if ( $this->options['access_control_allow_credentials'] )
-
 
314
            {
-
 
315
                $file->deleteWithCredentials = true;
-
 
316
            }
-
 
317
        }
-
 
318
 
-
 
319
        // Fix for overflowing signed 32 bit integers,
-
 
320
        // works for sizes up to 2^32-1 bytes (4 GiB - 1):
-
 
321
        protected function fix_integer_overflow( $size ): float
-
 
322
        {
-
 
323
            if ( $size < 0 )
-
 
324
            {
-
 
325
                $size += 2.0 * ( PHP_INT_MAX + 1 );
-
 
326
            }
-
 
327
            return $size;
-
 
328
        }
-
 
329
 
-
 
330
        protected function get_file_size( $file_path, $clear_stat_cache = false ): float
-
 
331
        {
-
 
332
            if ( $clear_stat_cache )
-
 
333
            {
-
 
334
                if ( version_compare( PHP_VERSION, '5.3.0' ) >= 0 )
-
 
335
                {
-
 
336
                    clearstatcache( true, $file_path );
-
 
337
                }
-
 
338
                else
-
 
339
                {
-
 
340
                    clearstatcache();
-
 
341
                }
-
 
342
            }
-
 
343
            return $this->fix_integer_overflow( filesize( $file_path ) );
-
 
344
        }
-
 
345
 
-
 
346
        protected function is_valid_file_object( $file_name ): bool
-
 
347
        {
-
 
348
            $file_path = $this->get_upload_path( $file_name );
-
 
349
            if ( strlen( $file_name ) > 0 && $file_name[0] !== '.' && is_file( $file_path ) )
-
 
350
            {
-
 
351
                return true;
-
 
352
            }
-
 
353
            return false;
-
 
354
        }
-
 
355
 
-
 
356
        protected function get_file_object( $file_name ): ?\stdClass
-
 
357
        {
-
 
358
            if ( $this->is_valid_file_object( $file_name ) )
-
 
359
            {
-
 
360
                $file = new \stdClass();
-
 
361
                $file->name = $file_name;
-
 
362
                $file->size = $this->get_file_size(
-
 
363
                    $this->get_upload_path( $file_name )
-
 
364
                );
-
 
365
                $file->url = $this->get_download_url( $file->name );
-
 
366
                foreach ( $this->options['image_versions'] as $version => $options )
-
 
367
                {
-
 
368
                    if ( !empty( $version ) )
-
 
369
                    {
-
 
370
                        if ( is_file( $this->get_upload_path( $file_name, $version ) ) )
-
 
371
                        {
-
 
372
                            $file->{$version . 'Url'} = $this->get_download_url(
-
 
373
                                $file->name,
-
 
374
                                $version
-
 
375
                            );
-
 
376
                        }
-
 
377
                    }
-
 
378
                }
-
 
379
                $this->set_additional_file_properties( $file );
-
 
380
                return $file;
-
 
381
            }
-
 
382
            return null;
-
 
383
        }
-
 
384
 
-
 
385
        protected function get_file_objects( $iteration_method = 'get_file_object' ): array
-
 
386
        {
-
 
387
            $upload_dir = $this->get_upload_path();
-
 
388
            if ( !is_dir( $upload_dir ) )
-
 
389
            {
-
 
390
                return array();
-
 
391
            }
-
 
392
            return array_values( array_filter( array_map(
-
 
393
                array( $this, $iteration_method ),
-
 
394
                scandir( $upload_dir )
-
 
395
            ) ) );
-
 
396
        }
-
 
397
 
-
 
398
        protected function count_file_objects(): int
-
 
399
        {
-
 
400
            return count( $this->get_file_objects( 'is_valid_file_object' ) );
-
 
401
        }
-
 
402
 
-
 
403
        protected function get_error_message( $error )
-
 
404
        {
-
 
405
            return $this->error_messages[$error] ?? $error;
-
 
406
        }
-
 
407
 
-
 
408
        public function get_config_bytes( $val ): float
-
 
409
        {
-
 
410
            $val = trim( $val );
-
 
411
            $last = strtolower( $val[strlen( $val ) - 1] );
-
 
412
            if ( is_numeric( $val ) )
-
 
413
            {
-
 
414
                $val = (int)$val;
-
 
415
            }
-
 
416
            else
-
 
417
            {
-
 
418
                $val = (int)substr( $val, 0, -1 );
-
 
419
            }
-
 
420
            switch ( $last )
-
 
421
            {
-
 
422
                case 'g':
-
 
423
                    $val *= 1024;
-
 
424
                case 'm':
-
 
425
                    $val *= 1024;
-
 
426
                case 'k':
-
 
427
                    $val *= 1024;
-
 
428
            }
-
 
429
            return $this->fix_integer_overflow( $val );
-
 
430
        }
-
 
431
 
-
 
432
        protected function validate_image_file( $uploaded_file, $file, $error, $index ): bool
-
 
433
        {
-
 
434
            if ( $this->imagetype( $uploaded_file ) !== $this->get_file_type( $file->name ) )
-
 
435
            {
-
 
436
                $file->error = $this->get_error_message( 'invalid_file_type' );
-
 
437
                return false;
-
 
438
            }
-
 
439
            $max_width = @$this->options['max_width'];
-
 
440
            $max_height = @$this->options['max_height'];
-
 
441
            $min_width = @$this->options['min_width'];
-
 
442
            $min_height = @$this->options['min_height'];
-
 
443
            if ( $max_width || $max_height || $min_width || $min_height )
-
 
444
            {
-
 
445
                list( $img_width, $img_height ) = $this->get_image_size( $uploaded_file );
-
 
446
                // If we are auto rotating the image by default, do the checks on
-
 
447
                // the correct orientation
-
 
448
                if (
-
 
449
                    @$this->options['image_versions']['']['auto_orient'] &&
-
 
450
                    function_exists( 'exif_read_data' ) &&
-
 
451
                    ( $exif = @exif_read_data( $uploaded_file ) ) &&
-
 
452
                    ( ( (int)@$exif['Orientation'] ) >= 5 )
-
 
453
                )
-
 
454
                {
-
 
455
                    $tmp = $img_width;
-
 
456
                    $img_width = $img_height;
-
 
457
                    $img_height = $tmp;
-
 
458
                    unset( $tmp );
-
 
459
                }
-
 
460
                if ( !empty( $img_width ) && !empty( $img_height ) )
-
 
461
                {
-
 
462
                    if ( $max_width && $img_width > $max_width )
-
 
463
                    {
-
 
464
                        $file->error = $this->get_error_message( 'max_width' );
-
 
465
                        return false;
-
 
466
                    }
-
 
467
                    if ( $max_height && $img_height > $max_height )
-
 
468
                    {
-
 
469
                        $file->error = $this->get_error_message( 'max_height' );
-
 
470
                        return false;
-
 
471
                    }
-
 
472
                    if ( $min_width && $img_width < $min_width )
-
 
473
                    {
-
 
474
                        $file->error = $this->get_error_message( 'min_width' );
-
 
475
                        return false;
-
 
476
                    }
-
 
477
                    if ( $min_height && $img_height < $min_height )
-
 
478
                    {
-
 
479
                        $file->error = $this->get_error_message( 'min_height' );
-
 
480
                        return false;
-
 
481
                    }
-
 
482
                }
-
 
483
            }
-
 
484
            return true;
-
 
485
        }
-
 
486
 
-
 
487
        protected function validate( $uploaded_file, $file, $error, $index, $content_range ): bool
-
 
488
        {
-
 
489
            if ( $error )
-
 
490
            {
-
 
491
                $file->error = $this->get_error_message( $error );
-
 
492
                return false;
-
 
493
            }
-
 
494
            $content_length = $this->fix_integer_overflow(
-
 
495
                (int)$this->get_server_var( 'CONTENT_LENGTH' )
-
 
496
            );
-
 
497
            $post_max_size = $this->get_config_bytes( ini_get( 'post_max_size' ) );
-
 
498
            if ( $post_max_size && ( $content_length > $post_max_size ) )
-
 
499
            {
-
 
500
                $file->error = $this->get_error_message( 'post_max_size' );
-
 
501
                return false;
-
 
502
            }
-
 
503
            if ( !preg_match( $this->options['accept_file_types'], $file->name ) )
-
 
504
            {
-
 
505
                $file->error = $this->get_error_message( 'accept_file_types' );
-
 
506
                return false;
-
 
507
            }
-
 
508
            if ( $uploaded_file && is_uploaded_file( $uploaded_file ) )
-
 
509
            {
-
 
510
                $file_size = $this->get_file_size( $uploaded_file );
-
 
511
            }
-
 
512
            else
-
 
513
            {
-
 
514
                $file_size = $content_length;
-
 
515
            }
-
 
516
            if (
-
 
517
                $this->options['max_file_size'] && (
-
 
518
                    $file_size > $this->options['max_file_size'] ||
-
 
519
                    $file->size > $this->options['max_file_size'] )
-
 
520
            )
-
 
521
            {
-
 
522
                $file->error = $this->get_error_message( 'max_file_size' );
-
 
523
                return false;
-
 
524
            }
-
 
525
            if (
-
 
526
                $this->options['min_file_size'] &&
-
 
527
                $file_size < $this->options['min_file_size']
-
 
528
            )
-
 
529
            {
-
 
530
                $file->error = $this->get_error_message( 'min_file_size' );
-
 
531
                return false;
-
 
532
            }
-
 
533
            if (
-
 
534
                is_int( $this->options['max_number_of_files'] ) &&
-
 
535
                ( $this->count_file_objects() >= $this->options['max_number_of_files'] ) &&
-
 
536
                // Ignore additional chunks of existing files:
-
 
537
                !is_file( $this->get_upload_path( $file->name ) )
-
 
538
            )
-
 
539
            {
-
 
540
                $file->error = $this->get_error_message( 'max_number_of_files' );
-
 
541
                return false;
-
 
542
            }
-
 
543
            if ( !$content_range && $this->has_image_file_extension( $file->name ) )
-
 
544
            {
-
 
545
                return $this->validate_image_file( $uploaded_file, $file, $error, $index );
-
 
546
            }
-
 
547
            return true;
-
 
548
        }
-
 
549
 
-
 
550
        protected function upcount_name_callback( $matches ): string
-
 
551
        {
-
 
552
            $index = isset( $matches[1] ) ? ( (int)$matches[1] ) + 1 : 1;
-
 
553
            $ext = isset( $matches[2] ) ? $matches[2] : '';
-
 
554
            return ' (' . $index . ')' . $ext;
-
 
555
        }
-
 
556
 
-
 
557
        protected function upcount_name( $name )
-
 
558
        {
-
 
559
            return preg_replace_callback(
-
 
560
                '/(?:(?: \(([\d]+)\))?(\.[^.]+))?$/',
-
 
561
                array( $this, 'upcount_name_callback' ),
-
 
562
                $name,
-
 
563
                1
-
 
564
            );
-
 
565
        }
-
 
566
 
-
 
567
        protected function get_unique_filename( $file_path, $name, $size, $type, $error,
-
 
568
                                                $index, $content_range )
-
 
569
        {
-
 
570
            while ( is_dir( $this->get_upload_path( $name ) ) )
-
 
571
            {
-
 
572
                $name = $this->upcount_name( $name );
-
 
573
            }
-
 
574
            // Keep an existing filename if this is part of a chunked upload:
-
 
575
            $uploaded_bytes = $this->fix_integer_overflow( (int)@$content_range[1] );
-
 
576
            while ( is_file( $this->get_upload_path( $name ) ) )
-
 
577
            {
-
 
578
                if (
-
 
579
                    $uploaded_bytes === $this->get_file_size(
-
 
580
                        $this->get_upload_path( $name ) )
-
 
581
                )
-
 
582
                {
-
 
583
                    break;
-
 
584
                }
-
 
585
                $name = $this->upcount_name( $name );
-
 
586
            }
-
 
587
            return $name;
-
 
588
        }
-
 
589
 
-
 
590
        protected function get_valid_image_extensions( $file_path )
-
 
591
        {
-
 
592
            switch ( $this->imagetype( $file_path ) )
-
 
593
            {
-
 
594
                case self::IMAGETYPE_JPEG:
-
 
595
                    return array( 'jpg', 'jpeg' );
-
 
596
                case self::IMAGETYPE_PNG:
-
 
597
                    return array( 'png' );
-
 
598
                case self::IMAGETYPE_GIF:
-
 
599
                    return array( 'gif' );
-
 
600
            }
-
 
601
        }
-
 
602
 
-
 
603
        protected function fix_file_extension( $file_path, $name, $size, $type, $error,
-
 
604
                                               $index, $content_range )
-
 
605
        {
-
 
606
            // Add missing file extension for known image types:
-
 
607
            if (
-
 
608
                strpos( $name, '.' ) === false &&
-
 
609
                preg_match( '/^image\/(gif|jpe?g|png)/', $type, $matches )
-
 
610
            )
-
 
611
            {
-
 
612
                $name .= '.' . $matches[1];
-
 
613
            }
-
 
614
            if ( $this->options['correct_image_extensions'] )
-
 
615
            {
-
 
616
                $extensions = $this->get_valid_image_extensions( $file_path );
-
 
617
                // Adjust incorrect image file extensions:
-
 
618
                if ( !empty( $extensions ) )
-
 
619
                {
-
 
620
                    $parts = explode( '.', $name );
-
 
621
                    $extIndex = count( $parts ) - 1;
-
 
622
                    $ext = strtolower( @$parts[$extIndex] );
-
 
623
                    if ( !in_array( $ext, $extensions ) )
-
 
624
                    {
-
 
625
                        $parts[$extIndex] = $extensions[0];
-
 
626
                        $name = implode( '.', $parts );
-
 
627
                    }
-
 
628
                }
-
 
629
            }
-
 
630
            return $name;
-
 
631
        }
-
 
632
 
-
 
633
        protected function trim_file_name( $file_path, $name, $size, $type, $error,
-
 
634
                                           $index, $content_range ): array|string
-
 
635
        {
-
 
636
            // Remove path information and dots around the filename, to prevent uploading
-
 
637
            // into different directories or replacing hidden system files.
-
 
638
            // Also remove control characters and spaces (\x00..\x20) around the filename:
-
 
639
            $name = trim( $this->basename( stripslashes( $name ) ), ".\x00..\x20" );
-
 
640
            // Replace dots in filenames to avoid security issues with servers
-
 
641
            // that interpret multiple file extensions, e.g. "example.php.png":
-
 
642
            $replacement = $this->options['replace_dots_in_filenames'];
-
 
643
            if ( !empty( $replacement ) )
-
 
644
            {
-
 
645
                $parts = explode( '.', $name );
-
 
646
                if ( count( $parts ) > 2 )
-
 
647
                {
-
 
648
                    $ext = array_pop( $parts );
-
 
649
                    $name = implode( $replacement, $parts ) . '.' . $ext;
-
 
650
                }
-
 
651
            }
-
 
652
            // Use a timestamp for empty filenames:
-
 
653
            if ( !$name )
-
 
654
            {
-
 
655
                $name = str_replace( '.', '-', microtime( true ) );
-
 
656
            }
-
 
657
            return $name;
-
 
658
        }
-
 
659
 
-
 
660
        protected function get_file_name( $file_path, $name, $size, $type, $error,
-
 
661
                                          $index, $content_range )
-
 
662
        {
-
 
663
            $name = $this->trim_file_name( $file_path, $name, $size, $type, $error,
-
 
664
                $index, $content_range );
-
 
665
            return $this->get_unique_filename(
-
 
666
                $file_path,
-
 
667
                $this->fix_file_extension( $file_path, $name, $size, $type, $error,
-
 
668
                    $index, $content_range ),
-
 
669
                $size,
-
 
670
                $type,
-
 
671
                $error,
-
 
672
                $index,
-
 
673
                $content_range
-
 
674
            );
-
 
675
        }
-
 
676
 
-
 
677
        protected function get_scaled_image_file_paths( $file_name, $version )
-
 
678
        {
-
 
679
            $file_path = $this->get_upload_path( $file_name );
-
 
680
            if ( !empty( $version ) )
-
 
681
            {
-
 
682
                $version_dir = $this->get_upload_path( null, $version );
-
 
683
                if ( !is_dir( $version_dir ) )
-
 
684
                {
-
 
685
                    mkdir( $version_dir, $this->options['mkdir_mode'], true );
-
 
686
                }
-
 
687
                $new_file_path = $version_dir . '/' . $file_name;
-
 
688
            }
-
 
689
            else
-
 
690
            {
-
 
691
                $new_file_path = $file_path;
-
 
692
            }
-
 
693
            return array( $file_path, $new_file_path );
-
 
694
        }
-
 
695
 
-
 
696
        protected function gd_get_image_object( $file_path, $func, $no_cache = false )
-
 
697
        {
-
 
698
            if ( empty( $this->image_objects[$file_path] ) || $no_cache )
-
 
699
            {
-
 
700
                $this->gd_destroy_image_object( $file_path );
-
 
701
                $this->image_objects[$file_path] = $func( $file_path );
-
 
702
            }
-
 
703
            return $this->image_objects[$file_path];
-
 
704
        }
-
 
705
 
-
 
706
        protected function gd_set_image_object( $file_path, $image )
-
 
707
        {
-
 
708
            $this->gd_destroy_image_object( $file_path );
-
 
709
            $this->image_objects[$file_path] = $image;
-
 
710
        }
-
 
711
 
-
 
712
        protected function gd_destroy_image_object( $file_path )
-
 
713
        {
-
 
714
            $image = ( isset( $this->image_objects[$file_path] ) ) ? $this->image_objects[$file_path] : null;
-
 
715
            return $image && imagedestroy( $image );
-
 
716
        }
-
 
717
 
-
 
718
        protected function gd_imageflip( $image, $mode )
-
 
719
        {
-
 
720
            if ( function_exists( 'imageflip' ) )
-
 
721
            {
-
 
722
                return imageflip( $image, $mode );
-
 
723
            }
-
 
724
            $new_width = $src_width = imagesx( $image );
-
 
725
            $new_height = $src_height = imagesy( $image );
-
 
726
            $new_img = imagecreatetruecolor( $new_width, $new_height );
-
 
727
            $src_x = 0;
-
 
728
            $src_y = 0;
-
 
729
            switch ( $mode )
-
 
730
            {
-
 
731
                case '1': // flip on the horizontal axis
-
 
732
                    $src_y = $new_height - 1;
-
 
733
                    $src_height = -$new_height;
-
 
734
                    break;
-
 
735
                case '2': // flip on the vertical axis
-
 
736
                    $src_x = $new_width - 1;
-
 
737
                    $src_width = -$new_width;
-
 
738
                    break;
-
 
739
                case '3': // flip on both axes
-
 
740
                    $src_y = $new_height - 1;
-
 
741
                    $src_height = -$new_height;
-
 
742
                    $src_x = $new_width - 1;
-
 
743
                    $src_width = -$new_width;
-
 
744
                    break;
-
 
745
                default:
-
 
746
                    return $image;
-
 
747
            }
-
 
748
            imagecopyresampled(
-
 
749
                $new_img,
-
 
750
                $image,
-
 
751
                0,
-
 
752
                0,
-
 
753
                $src_x,
-
 
754
                $src_y,
-
 
755
                $new_width,
-
 
756
                $new_height,
-
 
757
                $src_width,
-
 
758
                $src_height
-
 
759
            );
-
 
760
            return $new_img;
-
 
761
        }
-
 
762
 
-
 
763
        protected function gd_orient_image( $file_path, $src_img )
-
 
764
        {
-
 
765
            if ( !function_exists( 'exif_read_data' ) )
-
 
766
            {
-
 
767
                return false;
-
 
768
            }
-
 
769
            $exif = @exif_read_data( $file_path );
-
 
770
            if ( $exif === false )
-
 
771
            {
-
 
772
                return false;
-
 
773
            }
-
 
774
            $orientation = (int)@$exif['Orientation'];
-
 
775
            if ( $orientation < 2 || $orientation > 8 )
-
 
776
            {
-
 
777
                return false;
-
 
778
            }
-
 
779
            switch ( $orientation )
-
 
780
            {
-
 
781
                case 2:
-
 
782
                    $new_img = $this->gd_imageflip(
-
 
783
                        $src_img,
-
 
784
                        defined( 'IMG_FLIP_VERTICAL' ) ? IMG_FLIP_VERTICAL : 2
-
 
785
                    );
-
 
786
                    break;
-
 
787
                case 3:
-
 
788
                    $new_img = imagerotate( $src_img, 180, 0 );
-
 
789
                    break;
-
 
790
                case 4:
-
 
791
                    $new_img = $this->gd_imageflip(
-
 
792
                        $src_img,
-
 
793
                        defined( 'IMG_FLIP_HORIZONTAL' ) ? IMG_FLIP_HORIZONTAL : 1
-
 
794
                    );
-
 
795
                    break;
-
 
796
                case 5:
-
 
797
                    $tmp_img = $this->gd_imageflip(
-
 
798
                        $src_img,
-
 
799
                        defined( 'IMG_FLIP_HORIZONTAL' ) ? IMG_FLIP_HORIZONTAL : 1
-
 
800
                    );
-
 
801
                    $new_img = imagerotate( $tmp_img, 270, 0 );
-
 
802
                    imagedestroy( $tmp_img );
-
 
803
                    break;
-
 
804
                case 6:
-
 
805
                    $new_img = imagerotate( $src_img, 270, 0 );
-
 
806
                    break;
-
 
807
                case 7:
-
 
808
                    $tmp_img = $this->gd_imageflip(
-
 
809
                        $src_img,
-
 
810
                        defined( 'IMG_FLIP_VERTICAL' ) ? IMG_FLIP_VERTICAL : 2
-
 
811
                    );
-
 
812
                    $new_img = imagerotate( $tmp_img, 270, 0 );
-
 
813
                    imagedestroy( $tmp_img );
-
 
814
                    break;
-
 
815
                case 8:
-
 
816
                    $new_img = imagerotate( $src_img, 90, 0 );
-
 
817
                    break;
-
 
818
                default:
-
 
819
                    return false;
-
 
820
            }
-
 
821
            $this->gd_set_image_object( $file_path, $new_img );
-
 
822
            return true;
-
 
823
        }
-
 
824
 
-
 
825
        protected function gd_create_scaled_image( $file_name, $version, $options )
-
 
826
        {
-
 
827
            if ( !function_exists( 'imagecreatetruecolor' ) )
-
 
828
            {
-
 
829
                error_log( 'Function not found: imagecreatetruecolor' );
-
 
830
                return false;
-
 
831
            }
-
 
832
            list( $file_path, $new_file_path ) =
-
 
833
                $this->get_scaled_image_file_paths( $file_name, $version );
-
 
834
            $type = strtolower( substr( strrchr( $file_name, '.' ), 1 ) );
-
 
835
            switch ( $type )
-
 
836
            {
-
 
837
                case 'jpg':
-
 
838
                case 'jpeg':
-
 
839
                    $src_func = 'imagecreatefromjpeg';
-
 
840
                    $write_func = 'imagejpeg';
-
 
841
                    $image_quality = $options['jpeg_quality'] ?? 75;
-
 
842
                    break;
-
 
843
                case 'gif':
-
 
844
                    $src_func = 'imagecreatefromgif';
-
 
845
                    $write_func = 'imagegif';
-
 
846
                    $image_quality = null;
-
 
847
                    break;
-
 
848
                case 'png':
-
 
849
                    $src_func = 'imagecreatefrompng';
-
 
850
                    $write_func = 'imagepng';
-
 
851
                    $image_quality = $options['png_quality'] ?? 9;
-
 
852
                    break;
-
 
853
                default:
-
 
854
                    return false;
-
 
855
            }
-
 
856
            $src_img = $this->gd_get_image_object(
-
 
857
                $file_path,
-
 
858
                $src_func,
-
 
859
                !empty( $options['no_cache'] )
-
 
860
            );
-
 
861
            $image_oriented = false;
-
 
862
            if (
-
 
863
                !empty( $options['auto_orient'] ) && $this->gd_orient_image(
-
 
864
                    $file_path,
-
 
865
                    $src_img
-
 
866
                )
-
 
867
            )
-
 
868
            {
-
 
869
                $image_oriented = true;
-
 
870
                $src_img = $this->gd_get_image_object(
-
 
871
                    $file_path,
-
 
872
                    $src_func
-
 
873
                );
-
 
874
            }
-
 
875
            $max_width = $img_width = imagesx( $src_img );
-
 
876
            $max_height = $img_height = imagesy( $src_img );
-
 
877
            if ( !empty( $options['max_width'] ) )
-
 
878
            {
-
 
879
                $max_width = $options['max_width'];
-
 
880
            }
-
 
881
            if ( !empty( $options['max_height'] ) )
-
 
882
            {
-
 
883
                $max_height = $options['max_height'];
-
 
884
            }
-
 
885
            $scale = min(
-
 
886
                $max_width / $img_width,
-
 
887
                $max_height / $img_height
-
 
888
            );
-
 
889
            if ( $scale >= 1 )
-
 
890
            {
-
 
891
                if ( $image_oriented )
-
 
892
                {
-
 
893
                    return $write_func( $src_img, $new_file_path, $image_quality );
-
 
894
                }
-
 
895
                if ( $file_path !== $new_file_path )
-
 
896
                {
-
 
897
                    return copy( $file_path, $new_file_path );
-
 
898
                }
-
 
899
                return true;
-
 
900
            }
-
 
901
            if ( empty( $options['crop'] ) )
-
 
902
            {
-
 
903
                $new_width = $img_width * $scale;
-
 
904
                $new_height = $img_height * $scale;
-
 
905
                $dst_x = 0;
-
 
906
                $dst_y = 0;
-
 
907
                $new_img = imagecreatetruecolor( $new_width, $new_height );
-
 
908
            }
-
 
909
            else
-
 
910
            {
-
 
911
                if ( ( $img_width / $img_height ) >= ( $max_width / $max_height ) )
-
 
912
                {
-
 
913
                    $new_width = $img_width / ( $img_height / $max_height );
-
 
914
                    $new_height = $max_height;
-
 
915
                }
-
 
916
                else
-
 
917
                {
-
 
918
                    $new_width = $max_width;
-
 
919
                    $new_height = $img_height / ( $img_width / $max_width );
-
 
920
                }
-
 
921
                $dst_x = 0 - ( $new_width - $max_width ) / 2;
-
 
922
                $dst_y = 0 - ( $new_height - $max_height ) / 2;
-
 
923
                $new_img = imagecreatetruecolor( $max_width, $max_height );
-
 
924
            }
-
 
925
            // Handle transparency in GIF and PNG images:
-
 
926
            switch ( $type )
-
 
927
            {
-
 
928
                case 'gif':
-
 
929
                    imagecolortransparent( $new_img, imagecolorallocate( $new_img, 0, 0, 0 ) );
-
 
930
                    break;
-
 
931
                case 'png':
-
 
932
                    imagecolortransparent( $new_img, imagecolorallocate( $new_img, 0, 0, 0 ) );
-
 
933
                    imagealphablending( $new_img, false );
-
 
934
                    imagesavealpha( $new_img, true );
-
 
935
                    break;
-
 
936
            }
-
 
937
            $success = imagecopyresampled(
-
 
938
                    $new_img,
-
 
939
                    $src_img,
-
 
940
                    $dst_x,
-
 
941
                    $dst_y,
-
 
942
                    0,
-
 
943
                    0,
-
 
944
                    $new_width,
-
 
945
                    $new_height,
-
 
946
                    $img_width,
-
 
947
                    $img_height
-
 
948
                ) && $write_func( $new_img, $new_file_path, $image_quality );
-
 
949
            $this->gd_set_image_object( $file_path, $new_img );
-
 
950
            return $success;
-
 
951
        }
-
 
952
 
-
 
953
        protected function imagick_get_image_object( $file_path, $no_cache = false )
-
 
954
        {
-
 
955
            if ( empty( $this->image_objects[$file_path] ) || $no_cache )
-
 
956
            {
-
 
957
                $this->imagick_destroy_image_object( $file_path );
-
 
958
                $image = new \Imagick();
-
 
959
                if ( !empty( $this->options['imagick_resource_limits'] ) )
-
 
960
                {
-
 
961
                    foreach ( $this->options['imagick_resource_limits'] as $type => $limit )
-
 
962
                    {
-
 
963
                        $image->setResourceLimit( $type, $limit );
-
 
964
                    }
-
 
965
                }
-
 
966
                try
-
 
967
                {
-
 
968
                    $image->readImage( $file_path );
-
 
969
                }
-
 
970
                catch ( ImagickException $e )
-
 
971
                {
-
 
972
                    error_log( $e->getMessage() );
-
 
973
                    return null;
-
 
974
                }
-
 
975
                $this->image_objects[$file_path] = $image;
-
 
976
            }
-
 
977
            return $this->image_objects[$file_path];
-
 
978
        }
-
 
979
 
-
 
980
        protected function imagick_set_image_object( $file_path, $image )
-
 
981
        {
-
 
982
            $this->imagick_destroy_image_object( $file_path );
-
 
983
            $this->image_objects[$file_path] = $image;
-
 
984
        }
-
 
985
 
-
 
986
        protected function imagick_destroy_image_object( $file_path )
-
 
987
        {
-
 
988
            $image = ( isset( $this->image_objects[$file_path] ) ) ? $this->image_objects[$file_path] : null;
-
 
989
            return $image && $image->destroy();
-
 
990
        }
-
 
991
 
-
 
992
        protected function imagick_orient_image( $image ): bool
-
 
993
        {
-
 
994
            $orientation = $image->getImageOrientation();
-
 
995
            $background = new \ImagickPixel( 'none' );
-
 
996
            switch ( $orientation )
-
 
997
            {
-
 
998
                case \imagick::ORIENTATION_TOPRIGHT: // 2
-
 
999
                    $image->flopImage(); // horizontal flop around y-axis
-
 
1000
                    break;
-
 
1001
                case \imagick::ORIENTATION_BOTTOMRIGHT: // 3
-
 
1002
                    $image->rotateImage( $background, 180 );
-
 
1003
                    break;
-
 
1004
                case \imagick::ORIENTATION_BOTTOMLEFT: // 4
-
 
1005
                    $image->flipImage(); // vertical flip around x-axis
-
 
1006
                    break;
-
 
1007
                case \imagick::ORIENTATION_LEFTTOP: // 5
-
 
1008
                    $image->flopImage(); // horizontal flop around y-axis
-
 
1009
                    $image->rotateImage( $background, 270 );
-
 
1010
                    break;
-
 
1011
                case \imagick::ORIENTATION_RIGHTTOP: // 6
-
 
1012
                    $image->rotateImage( $background, 90 );
-
 
1013
                    break;
-
 
1014
                case \imagick::ORIENTATION_RIGHTBOTTOM: // 7
-
 
1015
                    $image->flipImage(); // vertical flip around x-axis
-
 
1016
                    $image->rotateImage( $background, 270 );
-
 
1017
                    break;
-
 
1018
                case \imagick::ORIENTATION_LEFTBOTTOM: // 8
-
 
1019
                    $image->rotateImage( $background, 270 );
-
 
1020
                    break;
-
 
1021
                default:
-
 
1022
                    return false;
-
 
1023
            }
-
 
1024
            $image->setImageOrientation( \imagick::ORIENTATION_TOPLEFT ); // 1
-
 
1025
            return true;
-
 
1026
        }
-
 
1027
 
-
 
1028
        protected function imagick_create_scaled_image( $file_name, $version, $options ): bool
-
 
1029
        {
-
 
1030
            list( $file_path, $new_file_path ) =
-
 
1031
                $this->get_scaled_image_file_paths( $file_name, $version );
-
 
1032
            $image = $this->imagick_get_image_object(
-
 
1033
                $file_path,
-
 
1034
                !empty( $options['crop'] ) || !empty( $options['no_cache'] )
-
 
1035
            );
-
 
1036
            if ( is_null( $image ) )
-
 
1037
            {
-
 
1038
                return false;
-
 
1039
            }
-
 
1040
            if ( $image->getImageFormat() === 'GIF' )
-
 
1041
            {
-
 
1042
                // Handle animated GIFs:
-
 
1043
                $images = $image->coalesceImages();
-
 
1044
                foreach ( $images as $frame )
-
 
1045
                {
-
 
1046
                    $image = $frame;
-
 
1047
                    $this->imagick_set_image_object( $file_name, $image );
-
 
1048
                    break;
-
 
1049
                }
-
 
1050
            }
-
 
1051
            $image_oriented = false;
-
 
1052
            if ( !empty( $options['auto_orient'] ) )
-
 
1053
            {
-
 
1054
                $image_oriented = $this->imagick_orient_image( $image );
-
 
1055
            }
-
 
1056
            $image_resize = false;
-
 
1057
            $new_width = $max_width = $img_width = $image->getImageWidth();
-
 
1058
            $new_height = $max_height = $img_height = $image->getImageHeight();
-
 
1059
            // use isset(). User might be setting max_width = 0 (auto in regular resizing). Value 0 would be considered empty when you use empty()
-
 
1060
            if ( isset( $options['max_width'] ) )
-
 
1061
            {
-
 
1062
                $image_resize = true;
-
 
1063
                $new_width = $max_width = $options['max_width'];
-
 
1064
            }
-
 
1065
            if ( isset( $options['max_height'] ) )
-
 
1066
            {
-
 
1067
                $image_resize = true;
-
 
1068
                $new_height = $max_height = $options['max_height'];
-
 
1069
            }
-
 
1070
            $image_strip = ( isset( $options['strip'] ) ? $options['strip'] : false );
-
 
1071
            if ( !$image_oriented && ( $max_width >= $img_width ) && ( $max_height >= $img_height ) && !$image_strip && empty( $options["jpeg_quality"] ) )
-
 
1072
            {
-
 
1073
                if ( $file_path !== $new_file_path )
-
 
1074
                {
-
 
1075
                    return copy( $file_path, $new_file_path );
-
 
1076
                }
-
 
1077
                return true;
-
 
1078
            }
-
 
1079
            $crop = ( isset( $options['crop'] ) ? $options['crop'] : false );
-
 
1080
 
-
 
1081
            if ( $crop )
-
 
1082
            {
-
 
1083
                $x = 0;
-
 
1084
                $y = 0;
-
 
1085
                if ( ( $img_width / $img_height ) >= ( $max_width / $max_height ) )
-
 
1086
                {
-
 
1087
                    $new_width = 0; // Enables proportional scaling based on max_height
-
 
1088
                    $x = ( $img_width / ( $img_height / $max_height ) - $max_width ) / 2;
-
 
1089
                }
-
 
1090
                else
-
 
1091
                {
-
 
1092
                    $new_height = 0; // Enables proportional scaling based on max_width
-
 
1093
                    $y = ( $img_height / ( $img_width / $max_width ) - $max_height ) / 2;
-
 
1094
                }
-
 
1095
            }
-
 
1096
            $success = $image->resizeImage(
-
 
1097
                $new_width,
-
 
1098
                $new_height,
-
 
1099
                isset( $options['filter'] ) ? $options['filter'] : \imagick::FILTER_LANCZOS,
-
 
1100
                isset( $options['blur'] ) ? $options['blur'] : 1,
-
 
1101
                $new_width && $new_height // fit image into constraints if not to be cropped
-
 
1102
            );
-
 
1103
            if ( $success && $crop )
-
 
1104
            {
-
 
1105
                $success = $image->cropImage(
-
 
1106
                    $max_width,
-
 
1107
                    $max_height,
-
 
1108
                    $x,
-
 
1109
                    $y
-
 
1110
                );
-
 
1111
                if ( $success )
-
 
1112
                {
-
 
1113
                    $success = $image->setImagePage( $max_width, $max_height, 0, 0 );
-
 
1114
                }
-
 
1115
            }
-
 
1116
            $type = strtolower( substr( strrchr( $file_name, '.' ), 1 ) );
-
 
1117
            switch ( $type )
-
 
1118
            {
-
 
1119
                case 'jpg':
-
 
1120
                case 'jpeg':
-
 
1121
                    if ( !empty( $options['jpeg_quality'] ) )
-
 
1122
                    {
-
 
1123
                        $image->setImageCompression( \imagick::COMPRESSION_JPEG );
-
 
1124
                        $image->setImageCompressionQuality( $options['jpeg_quality'] );
-
 
1125
                    }
-
 
1126
                    break;
-
 
1127
            }
-
 
1128
            if ( $image_strip )
-
 
1129
            {
-
 
1130
                $image->stripImage();
-
 
1131
            }
-
 
1132
            return $success && $image->writeImage( $new_file_path );
-
 
1133
        }
-
 
1134
 
-
 
1135
        protected function imagemagick_create_scaled_image( $file_name, $version, $options ): bool
-
 
1136
        {
-
 
1137
            list( $file_path, $new_file_path ) =
-
 
1138
                $this->get_scaled_image_file_paths( $file_name, $version );
-
 
1139
            $resize = @$options['max_width']
-
 
1140
                . ( empty( $options['max_height'] ) ? '' : 'X' . $options['max_height'] );
-
 
1141
            if ( !$resize && empty( $options['auto_orient'] ) )
-
 
1142
            {
-
 
1143
                if ( $file_path !== $new_file_path )
-
 
1144
                {
-
 
1145
                    return copy( $file_path, $new_file_path );
-
 
1146
                }
-
 
1147
                return true;
-
 
1148
            }
-
 
1149
            $cmd = $this->options['convert_bin'];
-
 
1150
            if ( !empty( $this->options['convert_params'] ) )
-
 
1151
            {
-
 
1152
                $cmd .= ' ' . $this->options['convert_params'];
-
 
1153
            }
-
 
1154
            $cmd .= ' ' . escapeshellarg( $file_path );
-
 
1155
            if ( !empty( $options['auto_orient'] ) )
-
 
1156
            {
-
 
1157
                $cmd .= ' -auto-orient';
-
 
1158
            }
-
 
1159
            if ( $resize )
-
 
1160
            {
-
 
1161
                // Handle animated GIFs:
-
 
1162
                $cmd .= ' -coalesce';
-
 
1163
                if ( empty( $options['crop'] ) )
-
 
1164
                {
-
 
1165
                    $cmd .= ' -resize ' . escapeshellarg( $resize . '>' );
-
 
1166
                }
-
 
1167
                else
-
 
1168
                {
-
 
1169
                    $cmd .= ' -resize ' . escapeshellarg( $resize . '^' );
-
 
1170
                    $cmd .= ' -gravity center';
-
 
1171
                    $cmd .= ' -crop ' . escapeshellarg( $resize . '+0+0' );
-
 
1172
                }
-
 
1173
                // Make sure the page dimensions are correct (fixes offsets of animated GIFs):
-
 
1174
                $cmd .= ' +repage';
-
 
1175
            }
-
 
1176
            if ( !empty( $options['convert_params'] ) )
-
 
1177
            {
-
 
1178
                $cmd .= ' ' . $options['convert_params'];
-
 
1179
            }
-
 
1180
            $cmd .= ' ' . escapeshellarg( $new_file_path );
-
 
1181
            exec( $cmd, $output, $error );
-
 
1182
            if ( $error )
-
 
1183
            {
-
 
1184
                error_log( implode( '\n', $output ) );
-
 
1185
                return false;
-
 
1186
            }
-
 
1187
            return true;
-
 
1188
        }
-
 
1189
 
-
 
1190
        protected function get_image_size( $file_path ): array|bool
-
 
1191
        {
-
 
1192
            if ( $this->options['image_library'] )
-
 
1193
            {
-
 
1194
                if ( extension_loaded( 'imagick' ) )
-
 
1195
                {
-
 
1196
                    $image = new \Imagick();
-
 
1197
                    try
-
 
1198
                    {
-
 
1199
                        if ( @$image->pingImage( $file_path ) )
-
 
1200
                        {
-
 
1201
                            $dimensions = array( $image->getImageWidth(), $image->getImageHeight() );
-
 
1202
                            $image->destroy();
-
 
1203
                            return $dimensions;
-
 
1204
                        }
-
 
1205
                        return false;
-
 
1206
                    }
-
 
1207
                    catch ( \Exception $e )
-
 
1208
                    {
-
 
1209
                        error_log( $e->getMessage() );
-
 
1210
                    }
-
 
1211
                }
-
 
1212
                if ( $this->options['image_library'] === 2 )
-
 
1213
                {
-
 
1214
                    $cmd = $this->options['identify_bin'];
-
 
1215
                    $cmd .= ' -ping ' . escapeshellarg( $file_path );
-
 
1216
                    exec( $cmd, $output, $error );
-
 
1217
                    if ( !$error && !empty( $output ) )
-
 
1218
                    {
-
 
1219
                        // image.jpg JPEG 1920x1080 1920x1080+0+0 8-bit sRGB 465KB 0.000u 0:00.000
-
 
1220
                        $infos = preg_split( '/\s+/', substr( $output[0], strlen( $file_path ) ) );
-
 
1221
                        $dimensions = preg_split( '/x/', $infos[2] );
-
 
1222
                        return $dimensions;
-
 
1223
                    }
-
 
1224
                    return false;
-
 
1225
                }
-
 
1226
            }
-
 
1227
            if ( !function_exists( 'getimagesize' ) )
-
 
1228
            {
-
 
1229
                error_log( 'Function not found: getimagesize' );
-
 
1230
                return false;
-
 
1231
            }
-
 
1232
            return @getimagesize( $file_path );
-
 
1233
        }
-
 
1234
 
-
 
1235
        protected function create_scaled_image( $file_name, $version, $options )
-
 
1236
        {
-
 
1237
            try
-
 
1238
            {
-
 
1239
                if ( $this->options['image_library'] === 2 )
-
 
1240
                {
-
 
1241
                    return $this->imagemagick_create_scaled_image( $file_name, $version, $options );
-
 
1242
                }
-
 
1243
                if ( $this->options['image_library'] && extension_loaded( 'imagick' ) )
-
 
1244
                {
-
 
1245
                    return $this->imagick_create_scaled_image( $file_name, $version, $options );
-
 
1246
                }
-
 
1247
                return $this->gd_create_scaled_image( $file_name, $version, $options );
-
 
1248
            }
-
 
1249
            catch ( \Exception $e )
-
 
1250
            {
-
 
1251
                error_log( $e->getMessage() );
-
 
1252
                return false;
-
 
1253
            }
-
 
1254
        }
-
 
1255
 
-
 
1256
        protected function destroy_image_object( $file_path )
-
 
1257
        {
-
 
1258
            if ( $this->options['image_library'] && extension_loaded( 'imagick' ) )
-
 
1259
            {
-
 
1260
                return $this->imagick_destroy_image_object( $file_path );
-
 
1261
            }
-
 
1262
        }
-
 
1263
 
-
 
1264
        protected function imagetype( $file_path ): bool|string
-
 
1265
        {
-
 
1266
            $fp = fopen( $file_path, 'r' );
-
 
1267
            $data = fread( $fp, 4 );
-
 
1268
            fclose( $fp );
-
 
1269
            // GIF: 47 49 46 38
-
 
1270
            if ( $data === 'GIF8' )
-
 
1271
            {
-
 
1272
                return self::IMAGETYPE_GIF;
-
 
1273
            }
-
 
1274
            // JPG: FF D8 FF
-
 
1275
            if ( bin2hex( substr( $data, 0, 3 ) ) === 'ffd8ff' )
-
 
1276
            {
-
 
1277
                return self::IMAGETYPE_JPEG;
-
 
1278
            }
-
 
1279
            // PNG: 89 50 4E 47
-
 
1280
            if ( bin2hex( @$data[0] ) . substr( $data, 1, 4 ) === '89PNG' )
-
 
1281
            {
-
 
1282
                return self::IMAGETYPE_PNG;
-
 
1283
            }
-
 
1284
            return false;
-
 
1285
        }
-
 
1286
 
-
 
1287
        protected function is_valid_image_file( $file_path ): bool
-
 
1288
        {
-
 
1289
            return !!$this->imagetype( $file_path );
-
 
1290
        }
-
 
1291
 
-
 
1292
        protected function has_image_file_extension( $file_path ): bool
-
 
1293
        {
-
 
1294
            return !!preg_match( '/\.(gif|jpe?g|png)$/i', $file_path );
-
 
1295
        }
-
 
1296
 
-
 
1297
        protected function handle_image_file( $file_path, $file ): void
-
 
1298
        {
-
 
1299
            $failed_versions = array();
-
 
1300
            foreach ( $this->options['image_versions'] as $version => $options )
-
 
1301
            {
-
 
1302
                if ( $this->create_scaled_image( $file->name, $version, $options ) )
-
 
1303
                {
-
 
1304
                    if ( !empty( $version ) )
-
 
1305
                    {
-
 
1306
                        $file->{$version . 'Url'} = $this->get_download_url(
-
 
1307
                            $file->name,
-
 
1308
                            $version
-
 
1309
                        );
-
 
1310
                    }
-
 
1311
                    else
-
 
1312
                    {
-
 
1313
                        $file->size = $this->get_file_size( $file_path, true );
-
 
1314
                    }
-
 
1315
                }
-
 
1316
                else
-
 
1317
                {
-
 
1318
                    $failed_versions[] = $version ? $version : 'original';
-
 
1319
                }
-
 
1320
            }
-
 
1321
            if ( count( $failed_versions ) )
-
 
1322
            {
-
 
1323
                $file->error = $this->get_error_message( 'image_resize' )
-
 
1324
                    . ' (' . implode( ', ', $failed_versions ) . ')';
-
 
1325
            }
-
 
1326
            // Free memory:
-
 
1327
            $this->destroy_image_object( $file_path );
-
 
1328
        }
-
 
1329
 
-
 
1330
        protected function handle_file_upload( $uploaded_file, $name, $size, $type, $error,
-
 
1331
                                               $index = null, $content_range = null ): stdClass
-
 
1332
        {
-
 
1333
            $file = new \stdClass();
-
 
1334
            $file->name = $this->get_file_name( $uploaded_file, $name, $size, $type, $error,
-
 
1335
                $index, $content_range );
-
 
1336
            $file->size = $this->fix_integer_overflow( (int)$size );
-
 
1337
            $file->type = $type;
-
 
1338
            if ( $this->validate( $uploaded_file, $file, $error, $index, $content_range ) )
-
 
1339
            {
-
 
1340
                $this->handle_form_data( $file, $index );
-
 
1341
                $upload_dir = $this->get_upload_path();
-
 
1342
                if ( !is_dir( $upload_dir ) )
-
 
1343
                {
-
 
1344
                    mkdir( $upload_dir, $this->options['mkdir_mode'], true );
-
 
1345
                }
-
 
1346
                $file_path = $this->get_upload_path( $file->name );
-
 
1347
                $append_file = $content_range && is_file( $file_path ) &&
-
 
1348
                    $file->size > $this->get_file_size( $file_path );
-
 
1349
                if ( $uploaded_file && is_uploaded_file( $uploaded_file ) )
-
 
1350
                {
-
 
1351
                    // multipart/formdata uploads (POST method uploads)
-
 
1352
                    if ( $append_file )
-
 
1353
                    {
-
 
1354
                        file_put_contents(
-
 
1355
                            $file_path,
-
 
1356
                            fopen( $uploaded_file, 'r' ),
-
 
1357
                            FILE_APPEND
-
 
1358
                        );
-
 
1359
                    }
-
 
1360
                    else
-
 
1361
                    {
-
 
1362
                        move_uploaded_file( $uploaded_file, $file_path );
-
 
1363
                    }
-
 
1364
                }
-
 
1365
                else
-
 
1366
                {
-
 
1367
                    // Non-multipart uploads (PUT method support)
-
 
1368
                    file_put_contents(
-
 
1369
                        $file_path,
-
 
1370
                        fopen( $this->options['input_stream'], 'r' ),
-
 
1371
                        $append_file ? FILE_APPEND : 0
-
 
1372
                    );
-
 
1373
                }
-
 
1374
                $file_size = $this->get_file_size( $file_path, $append_file );
-
 
1375
                if ( $file_size === $file->size )
-
 
1376
                {
-
 
1377
                    $file->url = $this->get_download_url( $file->name );
-
 
1378
                    if ( $this->has_image_file_extension( $file->name ) )
-
 
1379
                    {
-
 
1380
                        if ( $content_range && !$this->validate_image_file( $file_path, $file, $error, $index ) )
-
 
1381
                        {
-
 
1382
                            unlink( $file_path );
-
 
1383
                        }
-
 
1384
                        else
-
 
1385
                        {
-
 
1386
                            $this->handle_image_file( $file_path, $file );
-
 
1387
                        }
-
 
1388
                    }
-
 
1389
                }
-
 
1390
                else
-
 
1391
                {
-
 
1392
                    $file->size = $file_size;
-
 
1393
                    if ( !$content_range && $this->options['discard_aborted_uploads'] )
-
 
1394
                    {
-
 
1395
                        unlink( $file_path );
-
 
1396
                        $file->error = $this->get_error_message( 'abort' );
-
 
1397
                    }
-
 
1398
                }
-
 
1399
                $this->set_additional_file_properties( $file );
-
 
1400
            }
-
 
1401
            return $file;
-
 
1402
        }
-
 
1403
 
-
 
1404
        protected function readfile( $file_path ): float|bool|int
-
 
1405
        {
-
 
1406
            $file_size = $this->get_file_size( $file_path );
-
 
1407
            $chunk_size = $this->options['readfile_chunk_size'];
-
 
1408
            if ( $chunk_size && $file_size > $chunk_size )
-
 
1409
            {
-
 
1410
                $handle = fopen( $file_path, 'rb' );
-
 
1411
                while ( !feof( $handle ) )
-
 
1412
                {
-
 
1413
                    echo fread( $handle, $chunk_size );
-
 
1414
                    @ob_flush();
-
 
1415
                    @flush();
-
 
1416
                }
-
 
1417
                fclose( $handle );
-
 
1418
                return $file_size;
-
 
1419
            }
-
 
1420
            return readfile( $file_path );
-
 
1421
        }
-
 
1422
 
-
 
1423
        protected function body( $str ): void
-
 
1424
        {
-
 
1425
            echo $str;
-
 
1426
        }
-
 
1427
 
-
 
1428
        protected function header( $str ): void
-
 
1429
        {
-
 
1430
            header( $str );
-
 
1431
        }
-
 
1432
 
-
 
1433
        protected function get_upload_data( $id )
-
 
1434
        {
-
 
1435
            return @$_FILES[$id];
-
 
1436
        }
-
 
1437
 
-
 
1438
        protected function get_post_param( $id )
-
 
1439
        {
-
 
1440
            return @$_POST[$id];
-
 
1441
        }
-
 
1442
 
-
 
1443
        protected function get_query_param( $id )
-
 
1444
        {
-
 
1445
            return @$_GET[$id];
-
 
1446
        }
-
 
1447
 
-
 
1448
        protected function get_server_var( $id )
-
 
1449
        {
-
 
1450
            return @$_SERVER[$id];
-
 
1451
        }
-
 
1452
 
-
 
1453
        protected function handle_form_data( $file, $index )
-
 
1454
        {
-
 
1455
            // Handle form data, e.g. $_POST['description'][$index]
-
 
1456
        }
-
 
1457
 
-
 
1458
        protected function get_version_param(): string
-
 
1459
        {
-
 
1460
            return $this->basename( stripslashes( $this->get_query_param( 'version' ) ) );
-
 
1461
        }
-
 
1462
 
-
 
1463
        protected function get_singular_param_name(): string
-
 
1464
        {
-
 
1465
            return substr( $this->options['param_name'], 0, -1 );
-
 
1466
        }
-
 
1467
 
-
 
1468
        protected function get_file_name_param(): string
-
 
1469
        {
-
 
1470
            $name = $this->get_singular_param_name();
-
 
1471
            return $this->basename( stripslashes( $this->get_query_param( $name ) ) );
-
 
1472
        }
-
 
1473
 
-
 
1474
        protected function get_file_names_params()
-
 
1475
        {
-
 
1476
            $params = $this->get_query_param( $this->options['param_name'] );
-
 
1477
            if ( !$params )
-
 
1478
            {
-
 
1479
                return null;
-
 
1480
            }
-
 
1481
            foreach ( $params as $key => $value )
-
 
1482
            {
-
 
1483
                $params[$key] = $this->basename( stripslashes( $value ) );
-
 
1484
            }
-
 
1485
            return $params;
-
 
1486
        }
-
 
1487
 
-
 
1488
        protected function get_file_type( $file_path ): string
-
 
1489
        {
-
 
1490
            return match ( strtolower( pathinfo( $file_path, PATHINFO_EXTENSION ) ) )
-
 
1491
            {
-
 
1492
                'jpeg', 'jpg' => self::IMAGETYPE_JPEG,
-
 
1493
                'png'         => self::IMAGETYPE_PNG,
-
 
1494
                'gif'         => self::IMAGETYPE_GIF,
-
 
1495
                default       => '',
-
 
1496
            };
-
 
1497
        }
-
 
1498
 
-
 
1499
        protected function download()
-
 
1500
        {
-
 
1501
            switch ( $this->options['download_via_php'] )
-
 
1502
            {
-
 
1503
                case 1:
-
 
1504
                    $redirect_header = null;
-
 
1505
                    break;
-
 
1506
                case 2:
-
 
1507
                    $redirect_header = 'X-Sendfile';
-
 
1508
                    break;
-
 
1509
                case 3:
-
 
1510
                    $redirect_header = 'X-Accel-Redirect';
-
 
1511
                    break;
-
 
1512
                default:
-
 
1513
                    return $this->header( 'HTTP/1.1 403 Forbidden' );
-
 
1514
            }
-
 
1515
            $file_name = $this->get_file_name_param();
-
 
1516
            if ( !$this->is_valid_file_object( $file_name ) )
-
 
1517
            {
-
 
1518
                return $this->header( 'HTTP/1.1 404 Not Found' );
-
 
1519
            }
-
 
1520
            if ( $redirect_header )
-
 
1521
            {
-
 
1522
                return $this->header(
-
 
1523
                    $redirect_header . ': ' . $this->get_download_url(
-
 
1524
                        $file_name,
-
 
1525
                        $this->get_version_param(),
-
 
1526
                        true
-
 
1527
                    )
-
 
1528
                );
-
 
1529
            }
-
 
1530
            $file_path = $this->get_upload_path( $file_name, $this->get_version_param() );
-
 
1531
            // Prevent browsers from MIME-sniffing the content-type:
-
 
1532
            $this->header( 'X-Content-Type-Options: nosniff' );
-
 
1533
            if ( !preg_match( $this->options['inline_file_types'], $file_name ) )
-
 
1534
            {
-
 
1535
                $this->header( 'Content-Type: application/octet-stream' );
-
 
1536
                $this->header( 'Content-Disposition: attachment; filename="' . $file_name . '"' );
-
 
1537
            }
-
 
1538
            else
-
 
1539
            {
-
 
1540
                $this->header( 'Content-Type: ' . $this->get_file_type( $file_path ) );
-
 
1541
                $this->header( 'Content-Disposition: inline; filename="' . $file_name . '"' );
-
 
1542
            }
-
 
1543
            $this->header( 'Content-Length: ' . $this->get_file_size( $file_path ) );
-
 
1544
            $this->header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s T', filemtime( $file_path ) ) );
-
 
1545
            $this->readfile( $file_path );
-
 
1546
        }
-
 
1547
 
-
 
1548
        protected function send_content_type_header(): void
-
 
1549
        {
-
 
1550
            $this->header( 'Vary: Accept' );
-
 
1551
            if ( str_contains( $this->get_server_var( 'HTTP_ACCEPT' ), 'application/json' ) )
-
 
1552
            {
-
 
1553
                $this->header( 'Content-type: application/json' );
-
 
1554
            }
-
 
1555
            else
-
 
1556
            {
-
 
1557
                $this->header( 'Content-type: text/plain' );
-
 
1558
            }
-
 
1559
        }
-
 
1560
 
-
 
1561
        protected function send_access_control_headers(): void
-
 
1562
        {
-
 
1563
            $this->header( 'Access-Control-Allow-Origin: ' . $this->options['access_control_allow_origin'] );
-
 
1564
            $this->header( 'Access-Control-Allow-Credentials: '
-
 
1565
                . ( $this->options['access_control_allow_credentials'] ? 'true' : 'false' ) );
-
 
1566
            $this->header( 'Access-Control-Allow-Methods: '
-
 
1567
                . implode( ', ', $this->options['access_control_allow_methods'] ) );
-
 
1568
            $this->header( 'Access-Control-Allow-Headers: '
-
 
1569
                . implode( ', ', $this->options['access_control_allow_headers'] ) );
-
 
1570
        }
-
 
1571
 
-
 
1572
        public function generate_response( $content, $print_response = true )
-
 
1573
        {
-
 
1574
            $this->response = $content;
-
 
1575
            if ( $print_response )
-
 
1576
            {
-
 
1577
                $json = json_encode( $content );
-
 
1578
                $redirect = stripslashes( $this->get_post_param( 'redirect' ) );
-
 
1579
                if ( $redirect && preg_match( $this->options['redirect_allow_target'], $redirect ) )
-
 
1580
                {
-
 
1581
                    return $this->header( 'Location: ' . sprintf( $redirect, rawurlencode( $json ) ) );
-
 
1582
                }
-
 
1583
                $this->head();
-
 
1584
                if ( $this->get_server_var( 'HTTP_CONTENT_RANGE' ) )
-
 
1585
                {
-
 
1586
                    $files = $content[$this->options['param_name']] ?? null;
-
 
1587
                    if ( $files && is_array( $files ) && is_object( $files[0] ) && $files[0]->size )
-
 
1588
                    {
-
 
1589
                        $this->header( 'Range: 0-' . (
-
 
1590
                                $this->fix_integer_overflow( (int)$files[0]->size ) - 1
-
 
1591
                            ) );
-
 
1592
                    }
-
 
1593
                }
-
 
1594
                $this->body( $json );
-
 
1595
            }
-
 
1596
            return $content;
-
 
1597
        }
-
 
1598
 
-
 
1599
        public function get_response()
-
 
1600
        {
-
 
1601
            return $this->response;
-
 
1602
        }
-
 
1603
 
-
 
1604
        public function head(): void
-
 
1605
        {
-
 
1606
            $this->header( 'Pragma: no-cache' );
-
 
1607
            $this->header( 'Cache-Control: no-store, no-cache, must-revalidate' );
-
 
1608
            $this->header( 'Content-Disposition: inline; filename="files.json"' );
-
 
1609
            // Prevent Internet Explorer from MIME-sniffing the content-type:
-
 
1610
            $this->header( 'X-Content-Type-Options: nosniff' );
-
 
1611
            if ( $this->options['access_control_allow_origin'] )
-
 
1612
            {
-
 
1613
                $this->send_access_control_headers();
-
 
1614
            }
-
 
1615
            $this->send_content_type_header();
-
 
1616
        }
-
 
1617
 
-
 
1618
        public function get( $print_response = true )
-
 
1619
        {
-
 
1620
            if ( $print_response && $this->get_query_param( 'download' ) )
-
 
1621
            {
-
 
1622
                return $this->download();
-
 
1623
            }
-
 
1624
            $file_name = $this->get_file_name_param();
-
 
1625
            if ( $file_name )
-
 
1626
            {
-
 
1627
                $response = array(
-
 
1628
                    $this->get_singular_param_name() => $this->get_file_object( $file_name )
-
 
1629
                );
-
 
1630
            }
-
 
1631
            else
-
 
1632
            {
-
 
1633
                $response = array(
-
 
1634
                    $this->options['param_name'] => $this->get_file_objects()
-
 
1635
                );
-
 
1636
            }
-
 
1637
            return $this->generate_response( $response, $print_response );
-
 
1638
        }
-
 
1639
 
-
 
1640
        public function post( $print_response = true )
-
 
1641
        {
-
 
1642
            if ( $this->get_query_param( '_method' ) === 'DELETE' )
-
 
1643
            {
-
 
1644
                return $this->delete( $print_response );
-
 
1645
            }
-
 
1646
            $upload = $this->get_upload_data( $this->options['param_name'] );
-
 
1647
            // Parse the Content-Disposition header, if available:
-
 
1648
            $content_disposition_header = $this->get_server_var( 'HTTP_CONTENT_DISPOSITION' );
-
 
1649
            $file_name = $content_disposition_header ?
-
 
1650
                rawurldecode( preg_replace(
-
 
1651
                    '/(^[^"]+")|("$)/',
-
 
1652
                    '',
-
 
1653
                    $content_disposition_header
-
 
1654
                ) ) : null;
-
 
1655
            // Parse the Content-Range header, which has the following form:
-
 
1656
            // Content-Range: bytes 0-524287/2000000
-
 
1657
            $content_range_header = $this->get_server_var( 'HTTP_CONTENT_RANGE' );
-
 
1658
            $content_range = $content_range_header ?
-
 
1659
                preg_split( '/[^0-9]+/', $content_range_header ) : null;
-
 
1660
            $size = @$content_range[3];
-
 
1661
            $files = array();
-
 
1662
            if ( $upload )
-
 
1663
            {
-
 
1664
                if ( is_array( $upload['tmp_name'] ) )
-
 
1665
                {
-
 
1666
                    // param_name is an array identifier like "files[]",
-
 
1667
                    // $upload is a multi-dimensional array:
-
 
1668
                    foreach ( $upload['tmp_name'] as $index => $value )
-
 
1669
                    {
-
 
1670
                        $files[] = $this->handle_file_upload(
-
 
1671
                            $upload['tmp_name'][$index],
-
 
1672
                            $file_name ? $file_name : $upload['name'][$index],
-
 
1673
                            $size ? $size : $upload['size'][$index],
-
 
1674
                            $upload['type'][$index],
-
 
1675
                            $upload['error'][$index],
-
 
1676
                            $index,
-
 
1677
                            $content_range
-
 
1678
                        );
-
 
1679
                    }
-
 
1680
                }
-
 
1681
                else
-
 
1682
                {
-
 
1683
                    // param_name is a single object identifier like "file",
-
 
1684
                    // $upload is a one-dimensional array:
-
 
1685
                    $files[] = $this->handle_file_upload(
-
 
1686
                        $upload['tmp_name'] ?? null,
-
 
1687
                        $file_name ? $file_name : ( $upload['name'] ?? null ),
-
 
1688
                        $size ? $size : ( $upload['size'] ?? $this->get_server_var( 'CONTENT_LENGTH' ) ),
-
 
1689
                        $upload['type'] ?? $this->get_server_var( 'CONTENT_TYPE' ),
-
 
1690
                        $upload['error'] ?? null,
-
 
1691
                        null,
-
 
1692
                        $content_range
-
 
1693
                    );
-
 
1694
                }
-
 
1695
            }
-
 
1696
            $response = array( $this->options['param_name'] => $files );
-
 
1697
            return $this->generate_response( $response, $print_response );
-
 
1698
        }
-
 
1699
 
-
 
1700
        public function delete( $print_response = true )
-
 
1701
        {
-
 
1702
            $file_names = $this->get_file_names_params();
-
 
1703
            if ( empty( $file_names ) )
-
 
1704
            {
-
 
1705
                $file_names = array( $this->get_file_name_param() );
-
 
1706
            }
-
 
1707
            $response = array();
-
 
1708
            foreach ( $file_names as $file_name )
-
 
1709
            {
-
 
1710
                $file_path = $this->get_upload_path( $file_name );
-
 
1711
                $success = strlen( $file_name ) > 0 && $file_name[0] !== '.' && is_file( $file_path ) && unlink( $file_path );
-
 
1712
                if ( $success )
-
 
1713
                {
-
 
1714
                    foreach ( $this->options['image_versions'] as $version => $options )
-
 
1715
                    {
-
 
1716
                        if ( !empty( $version ) )
-
 
1717
                        {
-
 
1718
                            $file = $this->get_upload_path( $file_name, $version );
-
 
1719
                            if ( is_file( $file ) )
-
 
1720
                            {
-
 
1721
                                unlink( $file );
-
 
1722
                            }
-
 
1723
                        }
-
 
1724
                    }
-
 
1725
                }
-
 
1726
                $response[$file_name] = $success;
7
class MediumController extends Controller
1727
            }
-
 
1728
            return $this->generate_response( $response, $print_response );
-
 
1729
        }
-
 
1730
 
-
 
1731
        protected function basename( $filepath, $suffix = null ): string
-
 
1732
        {
-
 
1733
            $splited = preg_split( '/\//', rtrim( $filepath, '/ ' ) );