Issues (2010)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

wp-admin/includes/image.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * File contains all the administration image manipulation functions.
4
 *
5
 * @package WordPress
6
 * @subpackage Administration
7
 */
8
9
/**
10
 * Crop an Image to a given size.
11
 *
12
 * @since 2.1.0
13
 *
14
 * @param string|int $src The source file or Attachment ID.
15
 * @param int $src_x The start x position to crop from.
16
 * @param int $src_y The start y position to crop from.
17
 * @param int $src_w The width to crop.
18
 * @param int $src_h The height to crop.
19
 * @param int $dst_w The destination width.
20
 * @param int $dst_h The destination height.
21
 * @param int $src_abs Optional. If the source crop points are absolute.
22
 * @param string $dst_file Optional. The destination file to write to.
23
 * @return string|WP_Error New filepath on success, WP_Error on failure.
24
 */
25
function wp_crop_image( $src, $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h, $src_abs = false, $dst_file = false ) {
26
	$src_file = $src;
27
	if ( is_numeric( $src ) ) { // Handle int as attachment ID
28
		$src_file = get_attached_file( $src );
29
30
		if ( ! file_exists( $src_file ) ) {
31
			// If the file doesn't exist, attempt a URL fopen on the src link.
32
			// This can occur with certain file replication plugins.
33
			$src = _load_image_to_edit_path( $src, 'full' );
34
		} else {
35
			$src = $src_file;
36
		}
37
	}
38
39
	$editor = wp_get_image_editor( $src );
0 ignored issues
show
It seems like $src can also be of type false; however, wp_get_image_editor() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
40
	if ( is_wp_error( $editor ) )
41
		return $editor;
42
43
	$src = $editor->crop( $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h, $src_abs );
44
	if ( is_wp_error( $src ) )
45
		return $src;
46
47
	if ( ! $dst_file )
48
		$dst_file = str_replace( basename( $src_file ), 'cropped-' . basename( $src_file ), $src_file );
49
50
	/*
51
	 * The directory containing the original file may no longer exist when
52
	 * using a replication plugin.
53
	 */
54
	wp_mkdir_p( dirname( $dst_file ) );
55
56
	$dst_file = dirname( $dst_file ) . '/' . wp_unique_filename( dirname( $dst_file ), basename( $dst_file ) );
57
58
	$result = $editor->save( $dst_file );
59
	if ( is_wp_error( $result ) )
60
		return $result;
61
62
	return $dst_file;
63
}
64
65
/**
66
 * Generate post thumbnail attachment meta data.
67
 *
68
 * @since 2.1.0
69
 *
70
 * @param int $attachment_id Attachment Id to process.
71
 * @param string $file Filepath of the Attached image.
72
 * @return mixed Metadata for attachment.
73
 */
74
function wp_generate_attachment_metadata( $attachment_id, $file ) {
75
	$attachment = get_post( $attachment_id );
76
77
	$metadata = array();
78
	$support = false;
79
	if ( preg_match('!^image/!', get_post_mime_type( $attachment )) && file_is_displayable_image($file) ) {
80
		$imagesize = getimagesize( $file );
81
		$metadata['width'] = $imagesize[0];
82
		$metadata['height'] = $imagesize[1];
83
84
		// Make the file path relative to the upload dir.
85
		$metadata['file'] = _wp_relative_upload_path($file);
86
87
		// Make thumbnails and other intermediate sizes.
88
		$_wp_additional_image_sizes = wp_get_additional_image_sizes();
89
90
		$sizes = array();
91
		foreach ( get_intermediate_image_sizes() as $s ) {
92
			$sizes[$s] = array( 'width' => '', 'height' => '', 'crop' => false );
93 View Code Duplication
			if ( isset( $_wp_additional_image_sizes[$s]['width'] ) ) {
94
				// For theme-added sizes
95
				$sizes[$s]['width'] = intval( $_wp_additional_image_sizes[$s]['width'] );
96
			} else {
97
				// For default sizes set in options
98
				$sizes[$s]['width'] = get_option( "{$s}_size_w" );
99
			}
100
101 View Code Duplication
			if ( isset( $_wp_additional_image_sizes[$s]['height'] ) ) {
102
				// For theme-added sizes
103
				$sizes[$s]['height'] = intval( $_wp_additional_image_sizes[$s]['height'] );
104
			} else {
105
				// For default sizes set in options
106
				$sizes[$s]['height'] = get_option( "{$s}_size_h" );
107
			}
108
109
			if ( isset( $_wp_additional_image_sizes[$s]['crop'] ) ) {
110
				// For theme-added sizes
111
				$sizes[$s]['crop'] = $_wp_additional_image_sizes[$s]['crop'];
112
			} else {
113
				// For default sizes set in options
114
				$sizes[$s]['crop'] = get_option( "{$s}_crop" );
115
			}
116
		}
117
118
		/**
119
		 * Filters the image sizes automatically generated when uploading an image.
120
		 *
121
		 * @since 2.9.0
122
		 * @since 4.4.0 Added the `$metadata` argument.
123
		 *
124
		 * @param array $sizes    An associative array of image sizes.
125
		 * @param array $metadata An associative array of image metadata: width, height, file.
126
		 */
127
		$sizes = apply_filters( 'intermediate_image_sizes_advanced', $sizes, $metadata );
128
129
		if ( $sizes ) {
130
			$editor = wp_get_image_editor( $file );
131
132
			if ( ! is_wp_error( $editor ) )
133
				$metadata['sizes'] = $editor->multi_resize( $sizes );
134
		} else {
135
			$metadata['sizes'] = array();
136
		}
137
138
		// Fetch additional metadata from EXIF/IPTC.
139
		$image_meta = wp_read_image_metadata( $file );
140
		if ( $image_meta )
141
			$metadata['image_meta'] = $image_meta;
142
143
	} elseif ( wp_attachment_is( 'video', $attachment ) ) {
144
		$metadata = wp_read_video_metadata( $file );
145
		$support = current_theme_supports( 'post-thumbnails', 'attachment:video' ) || post_type_supports( 'attachment:video', 'thumbnail' );
146
	} elseif ( wp_attachment_is( 'audio', $attachment ) ) {
147
		$metadata = wp_read_audio_metadata( $file );
148
		$support = current_theme_supports( 'post-thumbnails', 'attachment:audio' ) || post_type_supports( 'attachment:audio', 'thumbnail' );
149
	}
150
151
	if ( $support && ! empty( $metadata['image']['data'] ) ) {
152
		// Check for existing cover.
153
		$hash = md5( $metadata['image']['data'] );
154
		$posts = get_posts( array(
155
			'fields' => 'ids',
156
			'post_type' => 'attachment',
157
			'post_mime_type' => $metadata['image']['mime'],
158
			'post_status' => 'inherit',
159
			'posts_per_page' => 1,
160
			'meta_key' => '_cover_hash',
161
			'meta_value' => $hash
162
		) );
163
		$exists = reset( $posts );
164
165
		if ( ! empty( $exists ) ) {
166
			update_post_meta( $attachment_id, '_thumbnail_id', $exists );
167
		} else {
168
			$ext = '.jpg';
169
			switch ( $metadata['image']['mime'] ) {
170
			case 'image/gif':
171
				$ext = '.gif';
172
				break;
173
			case 'image/png':
174
				$ext = '.png';
175
				break;
176
			}
177
			$basename = str_replace( '.', '-', basename( $file ) ) . '-image' . $ext;
178
			$uploaded = wp_upload_bits( $basename, '', $metadata['image']['data'] );
179
			if ( false === $uploaded['error'] ) {
180
				$image_attachment = array(
181
					'post_mime_type' => $metadata['image']['mime'],
182
					'post_type' => 'attachment',
183
					'post_content' => '',
184
				);
185
				/**
186
				 * Filters the parameters for the attachment thumbnail creation.
187
				 *
188
				 * @since 3.9.0
189
				 *
190
				 * @param array $image_attachment An array of parameters to create the thumbnail.
191
				 * @param array $metadata         Current attachment metadata.
192
				 * @param array $uploaded         An array containing the thumbnail path and url.
193
				 */
194
				$image_attachment = apply_filters( 'attachment_thumbnail_args', $image_attachment, $metadata, $uploaded );
195
196
				$sub_attachment_id = wp_insert_attachment( $image_attachment, $uploaded['file'] );
197
				add_post_meta( $sub_attachment_id, '_cover_hash', $hash );
198
				$attach_data = wp_generate_attachment_metadata( $sub_attachment_id, $uploaded['file'] );
199
				wp_update_attachment_metadata( $sub_attachment_id, $attach_data );
200
				update_post_meta( $attachment_id, '_thumbnail_id', $sub_attachment_id );
201
			}
202
		}
203
	}
204
205
	// Remove the blob of binary data from the array.
206
	if ( $metadata ) {
207
		unset( $metadata['image']['data'] );
208
	}
209
210
	/**
211
	 * Filters the generated attachment meta data.
212
	 *
213
	 * @since 2.1.0
214
	 *
215
	 * @param array $metadata      An array of attachment meta data.
216
	 * @param int   $attachment_id Current attachment ID.
217
	 */
218
	return apply_filters( 'wp_generate_attachment_metadata', $metadata, $attachment_id );
219
}
220
221
/**
222
 * Convert a fraction string to a decimal.
223
 *
224
 * @since 2.5.0
225
 *
226
 * @param string $str
227
 * @return int|float
228
 */
229
function wp_exif_frac2dec($str) {
230
	@list( $n, $d ) = explode( '/', $str );
231
	if ( !empty($d) )
232
		return $n / $d;
233
	return $str;
234
}
235
236
/**
237
 * Convert the exif date format to a unix timestamp.
238
 *
239
 * @since 2.5.0
240
 *
241
 * @param string $str
242
 * @return int
243
 */
244
function wp_exif_date2ts($str) {
245
	@list( $date, $time ) = explode( ' ', trim($str) );
246
	@list( $y, $m, $d ) = explode( ':', $date );
247
248
	return strtotime( "{$y}-{$m}-{$d} {$time}" );
249
}
250
251
/**
252
 * Get extended image metadata, exif or iptc as available.
253
 *
254
 * Retrieves the EXIF metadata aperture, credit, camera, caption, copyright, iso
255
 * created_timestamp, focal_length, shutter_speed, and title.
256
 *
257
 * The IPTC metadata that is retrieved is APP13, credit, byline, created date
258
 * and time, caption, copyright, and title. Also includes FNumber, Model,
259
 * DateTimeDigitized, FocalLength, ISOSpeedRatings, and ExposureTime.
260
 *
261
 * @todo Try other exif libraries if available.
262
 * @since 2.5.0
263
 *
264
 * @param string $file
265
 * @return bool|array False on failure. Image metadata array on success.
266
 */
267
function wp_read_image_metadata( $file ) {
268
	if ( ! file_exists( $file ) )
269
		return false;
270
271
	list( , , $sourceImageType ) = getimagesize( $file );
272
273
	/*
274
	 * EXIF contains a bunch of data we'll probably never need formatted in ways
275
	 * that are difficult to use. We'll normalize it and just extract the fields
276
	 * that are likely to be useful. Fractions and numbers are converted to
277
	 * floats, dates to unix timestamps, and everything else to strings.
278
	 */
279
	$meta = array(
280
		'aperture' => 0,
281
		'credit' => '',
282
		'camera' => '',
283
		'caption' => '',
284
		'created_timestamp' => 0,
285
		'copyright' => '',
286
		'focal_length' => 0,
287
		'iso' => 0,
288
		'shutter_speed' => 0,
289
		'title' => '',
290
		'orientation' => 0,
291
		'keywords' => array(),
292
	);
293
294
	$iptc = array();
295
	/*
296
	 * Read IPTC first, since it might contain data not available in exif such
297
	 * as caption, description etc.
298
	 */
299
	if ( is_callable( 'iptcparse' ) ) {
300
		getimagesize( $file, $info );
301
302
		if ( ! empty( $info['APP13'] ) ) {
303
			$iptc = iptcparse( $info['APP13'] );
304
305
			// Headline, "A brief synopsis of the caption."
306 View Code Duplication
			if ( ! empty( $iptc['2#105'][0] ) ) {
307
				$meta['title'] = trim( $iptc['2#105'][0] );
308
			/*
309
			 * Title, "Many use the Title field to store the filename of the image,
310
			 * though the field may be used in many ways."
311
			 */
312
			} elseif ( ! empty( $iptc['2#005'][0] ) ) {
313
				$meta['title'] = trim( $iptc['2#005'][0] );
314
			}
315
316
			if ( ! empty( $iptc['2#120'][0] ) ) { // description / legacy caption
317
				$caption = trim( $iptc['2#120'][0] );
318
319
				mbstring_binary_safe_encoding();
320
				$caption_length = strlen( $caption );
321
				reset_mbstring_encoding();
322
323
				if ( empty( $meta['title'] ) && $caption_length < 80 ) {
324
					// Assume the title is stored in 2:120 if it's short.
325
					$meta['title'] = $caption;
326
				}
327
328
				$meta['caption'] = $caption;
329
			}
330
331 View Code Duplication
			if ( ! empty( $iptc['2#110'][0] ) ) // credit
332
				$meta['credit'] = trim( $iptc['2#110'][0] );
333
			elseif ( ! empty( $iptc['2#080'][0] ) ) // creator / legacy byline
334
				$meta['credit'] = trim( $iptc['2#080'][0] );
335
336
			if ( ! empty( $iptc['2#055'][0] ) && ! empty( $iptc['2#060'][0] ) ) // created date and time
337
				$meta['created_timestamp'] = strtotime( $iptc['2#055'][0] . ' ' . $iptc['2#060'][0] );
338
339 View Code Duplication
			if ( ! empty( $iptc['2#116'][0] ) ) // copyright
340
				$meta['copyright'] = trim( $iptc['2#116'][0] );
341
342
			if ( ! empty( $iptc['2#025'][0] ) ) { // keywords array
343
				$meta['keywords'] = array_values( $iptc['2#025'] );
344
			}
345
		 }
346
	}
347
348
	/**
349
	 * Filters the image types to check for exif data.
350
	 *
351
	 * @since 2.5.0
352
	 *
353
	 * @param array $image_types Image types to check for exif data.
354
	 */
355
	if ( is_callable( 'exif_read_data' ) && in_array( $sourceImageType, apply_filters( 'wp_read_image_metadata_types', array( IMAGETYPE_JPEG, IMAGETYPE_TIFF_II, IMAGETYPE_TIFF_MM ) ) ) ) {
356
		$exif = @exif_read_data( $file );
357
358
		if ( ! empty( $exif['ImageDescription'] ) ) {
359
			mbstring_binary_safe_encoding();
360
			$description_length = strlen( $exif['ImageDescription'] );
361
			reset_mbstring_encoding();
362
363
			if ( empty( $meta['title'] ) && $description_length < 80 ) {
364
				// Assume the title is stored in ImageDescription
365
				$meta['title'] = trim( $exif['ImageDescription'] );
366
			}
367
368
			if ( empty( $meta['caption'] ) && ! empty( $exif['COMPUTED']['UserComment'] ) ) {
369
				$meta['caption'] = trim( $exif['COMPUTED']['UserComment'] );
370
			}
371
372
			if ( empty( $meta['caption'] ) ) {
373
				$meta['caption'] = trim( $exif['ImageDescription'] );
374
			}
375
		} elseif ( empty( $meta['caption'] ) && ! empty( $exif['Comments'] ) ) {
376
			$meta['caption'] = trim( $exif['Comments'] );
377
		}
378
379
		if ( empty( $meta['credit'] ) ) {
380
			if ( ! empty( $exif['Artist'] ) ) {
381
				$meta['credit'] = trim( $exif['Artist'] );
382
			} elseif ( ! empty($exif['Author'] ) ) {
383
				$meta['credit'] = trim( $exif['Author'] );
384
			}
385
		}
386
387 View Code Duplication
		if ( empty( $meta['copyright'] ) && ! empty( $exif['Copyright'] ) ) {
388
			$meta['copyright'] = trim( $exif['Copyright'] );
389
		}
390
		if ( ! empty( $exif['FNumber'] ) ) {
391
			$meta['aperture'] = round( wp_exif_frac2dec( $exif['FNumber'] ), 2 );
392
		}
393
		if ( ! empty( $exif['Model'] ) ) {
394
			$meta['camera'] = trim( $exif['Model'] );
395
		}
396
		if ( empty( $meta['created_timestamp'] ) && ! empty( $exif['DateTimeDigitized'] ) ) {
397
			$meta['created_timestamp'] = wp_exif_date2ts( $exif['DateTimeDigitized'] );
398
		}
399
		if ( ! empty( $exif['FocalLength'] ) ) {
400
			$meta['focal_length'] = (string) wp_exif_frac2dec( $exif['FocalLength'] );
401
		}
402
		if ( ! empty( $exif['ISOSpeedRatings'] ) ) {
403
			$meta['iso'] = is_array( $exif['ISOSpeedRatings'] ) ? reset( $exif['ISOSpeedRatings'] ) : $exif['ISOSpeedRatings'];
404
			$meta['iso'] = trim( $meta['iso'] );
405
		}
406
		if ( ! empty( $exif['ExposureTime'] ) ) {
407
			$meta['shutter_speed'] = (string) wp_exif_frac2dec( $exif['ExposureTime'] );
408
		}
409
		if ( ! empty( $exif['Orientation'] ) ) {
410
			$meta['orientation'] = $exif['Orientation'];
411
		}
412
	}
413
414
	foreach ( array( 'title', 'caption', 'credit', 'copyright', 'camera', 'iso' ) as $key ) {
415
		if ( $meta[ $key ] && ! seems_utf8( $meta[ $key ] ) ) {
416
			$meta[ $key ] = utf8_encode( $meta[ $key ] );
417
		}
418
	}
419
420
	foreach ( $meta['keywords'] as $key => $keyword ) {
421
		if ( ! seems_utf8( $keyword ) ) {
422
			$meta['keywords'][ $key ] = utf8_encode( $keyword );
423
		}
424
	}
425
426
	$meta = wp_kses_post_deep( $meta );
427
428
	/**
429
	 * Filters the array of meta data read from an image's exif data.
430
	 *
431
	 * @since 2.5.0
432
	 * @since 4.4.0 The `$iptc` parameter was added.
433
	 *
434
	 * @param array  $meta            Image meta data.
435
	 * @param string $file            Path to image file.
436
	 * @param int    $sourceImageType Type of image.
437
	 * @param array  $iptc            IPTC data.
438
	 */
439
	return apply_filters( 'wp_read_image_metadata', $meta, $file, $sourceImageType, $iptc );
440
441
}
442
443
/**
444
 * Validate that file is an image.
445
 *
446
 * @since 2.5.0
447
 *
448
 * @param string $path File path to test if valid image.
449
 * @return bool True if valid image, false if not valid image.
450
 */
451
function file_is_valid_image($path) {
452
	$size = @getimagesize($path);
453
	return !empty($size);
454
}
455
456
/**
457
 * Validate that file is suitable for displaying within a web page.
458
 *
459
 * @since 2.5.0
460
 *
461
 * @param string $path File path to test.
462
 * @return bool True if suitable, false if not suitable.
463
 */
464
function file_is_displayable_image($path) {
465
	$displayable_image_types = array( IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG, IMAGETYPE_BMP );
466
467
	$info = @getimagesize( $path );
468
	if ( empty( $info ) ) {
469
		$result = false;
470
	} elseif ( ! in_array( $info[2], $displayable_image_types ) ) {
471
		$result = false;
472
	} else {
473
		$result = true;
474
	}
475
476
	/**
477
	 * Filters whether the current image is displayable in the browser.
478
	 *
479
	 * @since 2.5.0
480
	 *
481
	 * @param bool   $result Whether the image can be displayed. Default true.
482
	 * @param string $path   Path to the image.
483
	 */
484
	return apply_filters( 'file_is_displayable_image', $result, $path );
485
}
486
487
/**
488
 * Load an image resource for editing.
489
 *
490
 * @since 2.9.0
491
 *
492
 * @param string $attachment_id Attachment ID.
493
 * @param string $mime_type Image mime type.
494
 * @param string $size Optional. Image size, defaults to 'full'.
495
 * @return resource|false The resulting image resource on success, false on failure.
496
 */
497
function load_image_to_edit( $attachment_id, $mime_type, $size = 'full' ) {
498
	$filepath = _load_image_to_edit_path( $attachment_id, $size );
499
	if ( empty( $filepath ) )
500
		return false;
501
502
	switch ( $mime_type ) {
503
		case 'image/jpeg':
504
			$image = imagecreatefromjpeg($filepath);
505
			break;
506
		case 'image/png':
507
			$image = imagecreatefrompng($filepath);
508
			break;
509
		case 'image/gif':
510
			$image = imagecreatefromgif($filepath);
511
			break;
512
		default:
513
			$image = false;
514
			break;
515
	}
516
	if ( is_resource($image) ) {
517
		/**
518
		 * Filters the current image being loaded for editing.
519
		 *
520
		 * @since 2.9.0
521
		 *
522
		 * @param resource $image         Current image.
523
		 * @param string   $attachment_id Attachment ID.
524
		 * @param string   $size          Image size.
525
		 */
526
		$image = apply_filters( 'load_image_to_edit', $image, $attachment_id, $size );
527
		if ( function_exists('imagealphablending') && function_exists('imagesavealpha') ) {
528
			imagealphablending($image, false);
529
			imagesavealpha($image, true);
530
		}
531
	}
532
	return $image;
533
}
534
535
/**
536
 * Retrieve the path or url of an attachment's attached file.
537
 *
538
 * If the attached file is not present on the local filesystem (usually due to replication plugins),
539
 * then the url of the file is returned if url fopen is supported.
540
 *
541
 * @since 3.4.0
542
 * @access private
543
 *
544
 * @param string $attachment_id Attachment ID.
545
 * @param string $size Optional. Image size, defaults to 'full'.
546
 * @return string|false File path or url on success, false on failure.
547
 */
548
function _load_image_to_edit_path( $attachment_id, $size = 'full' ) {
549
	$filepath = get_attached_file( $attachment_id );
550
551
	if ( $filepath && file_exists( $filepath ) ) {
552
		if ( 'full' != $size && ( $data = image_get_intermediate_size( $attachment_id, $size ) ) ) {
553
			/**
554
			 * Filters the path to the current image.
555
			 *
556
			 * The filter is evaluated for all image sizes except 'full'.
557
			 *
558
			 * @since 3.1.0
559
			 *
560
			 * @param string $path          Path to the current image.
561
			 * @param string $attachment_id Attachment ID.
562
			 * @param string $size          Size of the image.
563
			 */
564
			$filepath = apply_filters( 'load_image_to_edit_filesystempath', path_join( dirname( $filepath ), $data['file'] ), $attachment_id, $size );
565
		}
566
	} elseif ( function_exists( 'fopen' ) && function_exists( 'ini_get' ) && true == ini_get( 'allow_url_fopen' ) ) {
567
		/**
568
		 * Filters the image URL if not in the local filesystem.
569
		 *
570
		 * The filter is only evaluated if fopen is enabled on the server.
571
		 *
572
		 * @since 3.1.0
573
		 *
574
		 * @param string $image_url     Current image URL.
575
		 * @param string $attachment_id Attachment ID.
576
		 * @param string $size          Size of the image.
577
		 */
578
		$filepath = apply_filters( 'load_image_to_edit_attachmenturl', wp_get_attachment_url( $attachment_id ), $attachment_id, $size );
579
	}
580
581
	/**
582
	 * Filters the returned path or URL of the current image.
583
	 *
584
	 * @since 2.9.0
585
	 *
586
	 * @param string|bool $filepath      File path or URL to current image, or false.
587
	 * @param string      $attachment_id Attachment ID.
588
	 * @param string      $size          Size of the image.
589
	 */
590
	return apply_filters( 'load_image_to_edit_path', $filepath, $attachment_id, $size );
591
}
592
593
/**
594
 * Copy an existing image file.
595
 *
596
 * @since 3.4.0
597
 * @access private
598
 *
599
 * @param string $attachment_id Attachment ID.
600
 * @return string|false New file path on success, false on failure.
601
 */
602
function _copy_image_file( $attachment_id ) {
603
	$dst_file = $src_file = get_attached_file( $attachment_id );
604
	if ( ! file_exists( $src_file ) )
605
		$src_file = _load_image_to_edit_path( $attachment_id );
606
607
	if ( $src_file ) {
608
		$dst_file = str_replace( basename( $dst_file ), 'copy-' . basename( $dst_file ), $dst_file );
609
		$dst_file = dirname( $dst_file ) . '/' . wp_unique_filename( dirname( $dst_file ), basename( $dst_file ) );
610
611
		/*
612
		 * The directory containing the original file may no longer
613
		 * exist when using a replication plugin.
614
		 */
615
		wp_mkdir_p( dirname( $dst_file ) );
616
617
		if ( ! @copy( $src_file, $dst_file ) )
618
			$dst_file = false;
619
	} else {
620
		$dst_file = false;
621
	}
622
623
	return $dst_file;
624
}
625