card-mod-script 0.14.2 → 0.15.0

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