1611 lines
		
	
	
		
			71 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			1611 lines
		
	
	
		
			71 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| /**
 | |
|  * Unique functions for Standard EWWW IO plugins.
 | |
|  *
 | |
|  * This file contains functions that are unique to the regular EWWW IO plugin.
 | |
|  *
 | |
|  * @link https://ewww.io
 | |
|  * @package EWWW_Image_Optimizer
 | |
|  */
 | |
| 
 | |
| if ( ! defined( 'ABSPATH' ) ) {
 | |
| 	exit;
 | |
| }
 | |
| 
 | |
| // Installation routine for PNGOUT.
 | |
| add_action( 'admin_action_ewww_image_optimizer_install_pngout', 'ewww_image_optimizer_install_pngout_wrapper' );
 | |
| // Installation routine for SVGCLEANER.
 | |
| add_action( 'admin_action_ewww_image_optimizer_install_svgcleaner', 'ewww_image_optimizer_install_svgcleaner_wrapper' );
 | |
| // Removes the binaries when the plugin is deactivated.
 | |
| register_deactivation_hook( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE, 'ewww_image_optimizer_remove_binaries' );
 | |
| 
 | |
| /**
 | |
|  * Resizes an image with gifsicle to preserve animations.
 | |
|  *
 | |
|  * @param string $file The file to resize.
 | |
|  * @param int    $dst_x X-coordinate of destination image (usually 0).
 | |
|  * @param int    $dst_y Y-coordinate of destination image (usually 0).
 | |
|  * @param int    $src_x X-coordinate of source image (usually 0 unless cropping).
 | |
|  * @param int    $src_y Y-coordinate of source image (usually 0 unless cropping).
 | |
|  * @param int    $dst_w Desired image width.
 | |
|  * @param int    $dst_h Desired image height.
 | |
|  * @param int    $src_w Source width.
 | |
|  * @param int    $src_h Source height.
 | |
|  * @return string|WP_Error The image contents or the error message.
 | |
|  */
 | |
| function ewww_image_optimizer_gifsicle_resize( $file, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ) {
 | |
| 	ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
 | |
| 	$tools = array(
 | |
| 		'gifsicle' => ewwwio()->local->get_path( 'gifsicle' ),
 | |
| 	);
 | |
| 	if ( empty( $tools['gifsicle'] ) ) {
 | |
| 		ewwwio_debug_message( 'no gifsicle found for resizing' );
 | |
| 		return new WP_Error(
 | |
| 			'image_resize_error',
 | |
| 			/* translators: %s: name of a tool like jpegtran */
 | |
| 			sprintf( __( '%s is missing', 'ewww-image-optimizer' ), '<em>gifsicle</em>' )
 | |
| 		);
 | |
| 	}
 | |
| 	ewwwio_debug_message( "file: $file " );
 | |
| 	ewwwio_debug_message( "width: $dst_w" );
 | |
| 	ewwwio_debug_message( "height: $dst_h" );
 | |
| 
 | |
| 	list( $orig_w, $orig_h ) = wp_getimagesize( $file );
 | |
| 
 | |
| 	$outfile = "$file.tmp";
 | |
| 	// Run gifsicle.
 | |
| 	if ( (int) $orig_w !== (int) $src_w || (int) $orig_h !== (int) $src_h ) {
 | |
| 		$dim_string  = $dst_w . 'x' . $dst_h;
 | |
| 		$crop_string = $src_x . ',' . $src_y . '+' . $src_w . 'x' . $src_h;
 | |
| 		ewwwio_debug_message( "resize to $dim_string" );
 | |
| 		ewwwio_debug_message( "crop to $crop_string" );
 | |
| 		$cmd = "{$tools['gifsicle']} --crop $crop_string  -o " . ewww_image_optimizer_escapeshellarg( $outfile ) . ' ' . ewww_image_optimizer_escapeshellarg( $file );
 | |
| 		ewwwio_debug_message( "running: $cmd" );
 | |
| 		exec( $cmd, $output, $exit );
 | |
| 		$cmd = "{$tools['gifsicle']} --resize-fit $dim_string  -b " . ewww_image_optimizer_escapeshellarg( $outfile );
 | |
| 		ewwwio_debug_message( "running: $cmd" );
 | |
| 		exec( $cmd, $output, $exit );
 | |
| 	} else {
 | |
| 		$dim_string = $dst_w . 'x' . $dst_h;
 | |
| 		$cmd        = "{$tools['gifsicle']} --resize-fit $dim_string  -o " . ewww_image_optimizer_escapeshellarg( $outfile ) . ' ' . ewww_image_optimizer_escapeshellarg( $file );
 | |
| 		ewwwio_debug_message( "running: $cmd" );
 | |
| 		exec( $cmd, $output, $exit );
 | |
| 	}
 | |
| 	ewwwio_debug_message( "$file resized to $outfile" );
 | |
| 
 | |
| 	if ( ewwwio_is_file( $outfile ) ) {
 | |
| 		$new_type = ewww_image_optimizer_mimetype( $outfile, 'i' );
 | |
| 		// Check the filesize of the new JPG.
 | |
| 		$new_size = ewww_image_optimizer_filesize( $outfile );
 | |
| 		ewwwio_debug_message( "$outfile exists, testing type and size" );
 | |
| 	} else {
 | |
| 		return new WP_Error( 'image_resize_error', 'file does not exist' );
 | |
| 	}
 | |
| 
 | |
| 	if ( ! $new_size || 'image/gif' !== $new_type ) {
 | |
| 		unlink( $outfile );
 | |
| 		return new WP_Error( 'image_resize_error', 'wrong type or zero bytes' );
 | |
| 	}
 | |
| 	ewwwio_debug_message( 'resize success' );
 | |
| 	$image = file_get_contents( $outfile );
 | |
| 	unlink( $outfile );
 | |
| 	return $image;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Automatically corrects JPG rotation using local jpegtran tool.
 | |
|  *
 | |
|  * @param string $file Name of the file to fix.
 | |
|  * @param string $type File type of the file.
 | |
|  * @param int    $orientation The EXIF orientation value.
 | |
|  *
 | |
|  * @return bool True if the rotation was successful.
 | |
|  */
 | |
| function ewww_image_optimizer_jpegtran_autorotate( $file, $type, $orientation ) {
 | |
| 	ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
 | |
| 	if ( 'image/jpeg' !== $type ) {
 | |
| 		ewwwio_debug_message( 'not a JPG, go away!' );
 | |
| 		return false;
 | |
| 	}
 | |
| 	if ( ! $orientation || 1 === (int) $orientation ) {
 | |
| 		return false;
 | |
| 	}
 | |
| 	$nice = '';
 | |
| 	if ( PHP_OS !== 'WINNT' && ! ewwwio()->cloud_mode && ewwwio()->local->exec_check() ) {
 | |
| 		// Check to see if 'nice' exists.
 | |
| 		$nice = ewwwio()->local->find_nix_binary( 'nice' );
 | |
| 	}
 | |
| 	$tools = array(
 | |
| 		'jpegtran' => ewwwio()->local->get_path( 'jpegtran' ),
 | |
| 	);
 | |
| 	if ( empty( $tools['jpegtran'] ) ) {
 | |
| 		return false;
 | |
| 	}
 | |
| 	switch ( $orientation ) {
 | |
| 		case 1:
 | |
| 			return false;
 | |
| 		case 2:
 | |
| 			$transform = '-flip horizontal';
 | |
| 			break;
 | |
| 		case 3:
 | |
| 			$transform = '-rotate 180';
 | |
| 			break;
 | |
| 		case 4:
 | |
| 			$transform = '-flip vertical';
 | |
| 			break;
 | |
| 		case 5:
 | |
| 			$transform = '-transpose';
 | |
| 			break;
 | |
| 		case 6:
 | |
| 			$transform = '-rotate 90';
 | |
| 			break;
 | |
| 		case 7:
 | |
| 			$transform = '-transverse';
 | |
| 			break;
 | |
| 		case 8:
 | |
| 			$transform = '-rotate 270';
 | |
| 			break;
 | |
| 		default:
 | |
| 			return false;
 | |
| 	}
 | |
| 	$outfile = "$file.rotate";
 | |
| 	// Run jpegtran.
 | |
| 	$cmd = "$nice {$tools['jpegtran']} -trim -copy all $transform -outfile " . ewww_image_optimizer_escapeshellarg( $outfile ) . ' ' . ewww_image_optimizer_escapeshellarg( $file );
 | |
| 	ewwwio_debug_message( "running: $cmd" );
 | |
| 	exec( $cmd, $output, $exit );
 | |
| 	ewwwio_debug_message( "$file rotated to $outfile" );
 | |
| 
 | |
| 	if ( ewwwio_is_file( $outfile ) ) {
 | |
| 		$new_type = ewww_image_optimizer_mimetype( $outfile, 'i' );
 | |
| 		// Check the filesize of the new JPG.
 | |
| 		$new_size = filesize( $outfile );
 | |
| 		ewwwio_debug_message( "$outfile exists, testing type and size" );
 | |
| 	} else {
 | |
| 		return false;
 | |
| 	}
 | |
| 
 | |
| 	if ( ! $new_size || 'image/jpeg' !== $new_type ) {
 | |
| 		unlink( $outfile );
 | |
| 		return false;
 | |
| 	}
 | |
| 	ewwwio_debug_message( 'rotation success' );
 | |
| 	rename( $outfile, $file );
 | |
| 	return true;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Process an image.
 | |
|  *
 | |
|  * @param string $file Full absolute path to the image file.
 | |
|  * @param int    $gallery_type 1=WordPress, 2=nextgen, 3=flagallery, 4=aux_images, 5=image editor,
 | |
|  *                             6=imagestore.
 | |
|  * @param bool   $converted True if this is a resize and the full image was converted to a
 | |
|  *                          new format. Deprecated, always false now.
 | |
|  * @param bool   $new_image True if this is a new image, so it should attempt conversion regardless of
 | |
|  *                    previous results.
 | |
|  * @param bool   $fullsize True if this is a full size (original) image.
 | |
|  * @return array {
 | |
|  *     Status of the optimization attempt.
 | |
|  *
 | |
|  *     @type string $file The filename or false on error.
 | |
|  *     @type string $results The results of the optimization.
 | |
|  *     @type bool $converted True if an image changes formats.
 | |
|  *     @type string The original filename if converted.
 | |
|  * }
 | |
|  */
 | |
| function ewww_image_optimizer( $file, $gallery_type = 4, $converted = false, $new_image = false, $fullsize = false ) {
 | |
| 	ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
 | |
| 	session_write_close();
 | |
| 	if ( function_exists( 'wp_raise_memory_limit' ) ) {
 | |
| 		wp_raise_memory_limit( 'image' );
 | |
| 	}
 | |
| 	if ( apply_filters( 'ewww_image_optimizer_bypass', false, $file ) ) {
 | |
| 		ewwwio_debug_message( "optimization bypassed: $file" );
 | |
| 		// Tell the user optimization was skipped.
 | |
| 		return array( false, __( 'Optimization skipped', 'ewww-image-optimizer' ), $converted, $file );
 | |
| 	}
 | |
| 	global $ewww_image;
 | |
| 	global $ewww_force;
 | |
| 	global $ewww_force_smart;
 | |
| 	global $ewww_convert;
 | |
| 	global $ewww_webp_only;
 | |
| 	// Initialize the original filename.
 | |
| 	$original = $file;
 | |
| 	$result   = '';
 | |
| 	if ( false !== strpos( $file, '../' ) || false !== strpos( $file, '..\\' ) ) {
 | |
| 		$msg = __( 'Path traversal in filename not allowed.', 'ewww-image-optimizer' );
 | |
| 		ewwwio_debug_message( "file is using ../ potential path traversal blocked: $file" );
 | |
| 		return array( false, $msg, $converted, $original );
 | |
| 	}
 | |
| 	if ( ! ewwwio_is_file( $file ) ) {
 | |
| 		/* translators: %s: Image filename */
 | |
| 		$msg = sprintf( __( 'Could not find %s', 'ewww-image-optimizer' ), $file );
 | |
| 		ewwwio_debug_message( "file doesn't appear to exist: $file" );
 | |
| 		return array( false, $msg, $converted, $original );
 | |
| 	}
 | |
| 	if ( ! is_writable( $file ) ) {
 | |
| 		/* translators: %s: Image filename */
 | |
| 		$msg = sprintf( __( '%s is not writable', 'ewww-image-optimizer' ), $file );
 | |
| 		ewwwio_debug_message( "couldn't write to the file $file" );
 | |
| 		return array( false, $msg, $converted, $original );
 | |
| 	}
 | |
| 	$type = ewww_image_optimizer_mimetype( $file, 'i' );
 | |
| 	if ( ! $type ) {
 | |
| 		ewwwio_debug_message( 'could not find mimetype' );
 | |
| 		// Otherwise we store an error message since we couldn't get the mime-type.
 | |
| 		return array( false, __( 'Unknown file type', 'ewww-image-optimizer' ), $converted, $original );
 | |
| 	}
 | |
| 	// Not an image or pdf.
 | |
| 	if ( strpos( $type, 'image' ) === false && strpos( $type, 'pdf' ) === false ) {
 | |
| 		ewwwio_debug_message( "unsupported mimetype: $type" );
 | |
| 		return array( false, __( 'Unsupported file type', 'ewww-image-optimizer' ) . ": $type", $converted, $original );
 | |
| 	}
 | |
| 	if ( ! is_object( $ewww_image ) || ! $ewww_image instanceof EWWW_Image || $ewww_image->file !== $file ) {
 | |
| 		$ewww_image = new EWWW_Image( 0, '', $file );
 | |
| 	}
 | |
| 	$nice = '';
 | |
| 	if ( PHP_OS !== 'WINNT' && ! ewwwio()->cloud_mode && ewwwio()->local->exec_check() ) {
 | |
| 		// Check to see if 'nice' exists.
 | |
| 		$nice = ewwwio()->local->find_nix_binary( 'nice' );
 | |
| 	}
 | |
| 	$tools = array();
 | |
| 	if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_skip_full' ) && $fullsize ) {
 | |
| 		$keep_metadata = true;
 | |
| 	} else {
 | |
| 		$keep_metadata = false;
 | |
| 	}
 | |
| 	if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_lossy_skip_full' ) && $fullsize ) {
 | |
| 		$skip_lossy = true;
 | |
| 	} else {
 | |
| 		$skip_lossy = false;
 | |
| 	}
 | |
| 	if ( ini_get( 'max_execution_time' ) && ini_get( 'max_execution_time' ) < 90 && ewww_image_optimizer_stl_check() ) {
 | |
| 		set_time_limit( 0 );
 | |
| 	}
 | |
| 	// Get the original image size.
 | |
| 	$orig_size = ewww_image_optimizer_filesize( $file );
 | |
| 	ewwwio_debug_message( "original filesize: $orig_size" );
 | |
| 	if ( $orig_size < ewww_image_optimizer_get_option( 'ewww_image_optimizer_skip_size' ) ) {
 | |
| 		ewwwio_debug_message( "optimization bypassed due to filesize: $file" );
 | |
| 		// Tell the user optimization was skipped.
 | |
| 		return array( false, __( 'Optimization skipped', 'ewww-image-optimizer' ), $converted, $file );
 | |
| 	}
 | |
| 	if ( 'image/png' === $type && ewww_image_optimizer_get_option( 'ewww_image_optimizer_skip_png_size' ) && $orig_size > ewww_image_optimizer_get_option( 'ewww_image_optimizer_skip_png_size' ) ) {
 | |
| 		ewwwio_debug_message( "optimization bypassed due to filesize: $file" );
 | |
| 		// Tell the user optimization was skipped.
 | |
| 		return array( false, __( 'Optimization skipped', 'ewww-image-optimizer' ), $converted, $file );
 | |
| 	}
 | |
| 	$backup_hash = '';
 | |
| 	$new_size    = 0;
 | |
| 	// Set the optimization process to OFF.
 | |
| 	$optimize = false;
 | |
| 	// Toggle the convert process to ON.
 | |
| 	$convert = true;
 | |
| 	// Allow other plugins to mangle the image however they like prior to optimization.
 | |
| 	do_action( 'ewww_image_optimizer_pre_optimization', $file, $type, $fullsize );
 | |
| 	// Run the appropriate optimization/conversion for the mime-type.
 | |
| 	switch ( $type ) {
 | |
| 		case 'image/jpeg':
 | |
| 			$png_size = 0;
 | |
| 			// If jpg2png conversion is enabled, and this image is in the WordPress media library.
 | |
| 			if (
 | |
| 				1 === (int) $gallery_type &&
 | |
| 				$fullsize &&
 | |
| 				( ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_to_png' ) || ! empty( $ewww_convert ) ) &&
 | |
| 				empty( $ewww_webp_only )
 | |
| 			) {
 | |
| 				// Generate the filename for a PNG:
 | |
| 				// If this is a resize version.
 | |
| 				if ( $converted ) {
 | |
| 					// just change the file extension.
 | |
| 					$pngfile = preg_replace( '/\.\w+$/', '.png', $file );
 | |
| 				} else {
 | |
| 					// If this is a full size image.
 | |
| 					// Get a unique filename for the png image.
 | |
| 					$pngfile = ewww_image_optimizer_unique_filename( $file, '.png' );
 | |
| 				}
 | |
| 			} else {
 | |
| 				// Otherwise, turn conversion OFF.
 | |
| 				$convert = false;
 | |
| 				$pngfile = '';
 | |
| 			}
 | |
| 			$compression_level = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' );
 | |
| 			// Check for previous optimization, so long as the force flag is not on and this isn't a new image that needs converting.
 | |
| 			if ( empty( $ewww_force ) && ! ( $new_image && $convert ) ) {
 | |
| 				$results_msg = ewww_image_optimizer_check_table( $file, $orig_size );
 | |
| 				$smart_reopt = ! empty( $ewww_force_smart ) && ewww_image_optimizer_level_mismatch( $ewww_image->level, $compression_level ) ? true : false;
 | |
| 				if ( $smart_reopt ) {
 | |
| 					ewwwio_debug_message( "smart re-opt found level mismatch for $file, db says " . $ewww_image->level . " vs. current $compression_level" );
 | |
| 					// If the current compression level is less than what was previously used, and the previous level was premium (or premium plus).
 | |
| 					if ( $compression_level && $compression_level < $ewww_image->level && $ewww_image->level > 20 ) {
 | |
| 						ewwwio_debug_message( "smart re-opt triggering restoration for $file" );
 | |
| 						ewww_image_optimizer_cloud_restore_single_image( $ewww_image->record );
 | |
| 					}
 | |
| 				} elseif ( $results_msg ) {
 | |
| 					return array( $file, $results_msg, $converted, $original );
 | |
| 				}
 | |
| 			}
 | |
| 			$ewww_image->level = $compression_level;
 | |
| 			if ( $compression_level > 10 && empty( $ewww_webp_only ) ) {
 | |
| 				list( $file, $converted, $result, $new_size, $backup_hash ) = ewww_image_optimizer_cloud_optimizer( $file, $type, $convert, $pngfile, 'image/png', $skip_lossy );
 | |
| 				if ( $converted ) {
 | |
| 					// Check to see if the user wants the originals deleted.
 | |
| 					if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_delete_originals' ) ) {
 | |
| 						// Delete the original JPG.
 | |
| 						ewwwio_delete_file( $original );
 | |
| 					}
 | |
| 					$converted   = true;
 | |
| 					$webp_result = ewww_image_optimizer_webp_create( $file, $new_size, 'image/png', null, $orig_size !== $new_size );
 | |
| 				} else {
 | |
| 					$webp_result = ewww_image_optimizer_webp_create( $file, $new_size, $type, null, $orig_size !== $new_size );
 | |
| 				}
 | |
| 				break;
 | |
| 			}
 | |
| 			$tools['jpegtran'] = ewwwio()->local->get_path( 'jpegtran' );
 | |
| 			$tools['cwebp']    = ewwwio()->local->get_path( 'cwebp' );
 | |
| 			if ( $convert ) {
 | |
| 				$tools['optipng']  = ewwwio()->local->get_path( 'optipng' );
 | |
| 				$tools['pngout']   = ewwwio()->local->get_path( 'pngout' );
 | |
| 				$tools['pngquant'] = ewwwio()->local->get_path( 'pngquant' );
 | |
| 			}
 | |
| 			// For exec-deprived servers, or those where jpegtran doesn't want to work.
 | |
| 			if ( 10 === (int) $compression_level && empty( $tools['jpegtran'] ) ) {
 | |
| 				if ( empty( $ewww_webp_only ) ) {
 | |
| 					list( $file, $converted, $result, $new_size, $backup_hash ) = ewww_image_optimizer_cloud_optimizer( $file, $type );
 | |
| 				}
 | |
| 				$webp_result = ewww_image_optimizer_webp_create( $file, $new_size, $type, null, $orig_size !== $new_size );
 | |
| 				break;
 | |
| 			}
 | |
| 			// If we get this far, we are using local (jpegtran) optimization, so do an autorotate on the image.
 | |
| 			ewww_image_optimizer_autorotate( $file );
 | |
| 			// Get the (possibly new) original image size.
 | |
| 			$orig_size = ewww_image_optimizer_filesize( $file );
 | |
| 			if ( ! empty( $ewww_webp_only ) ) {
 | |
| 				$optimize = false;
 | |
| 			} elseif ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) ) {
 | |
| 				// Store an appropriate message in $result.
 | |
| 				$result = __( 'JPG optimization is disabled', 'ewww-image-optimizer' );
 | |
| 				// Otherwise, if jpegtran doesn't exist.
 | |
| 			} elseif ( empty( $tools['jpegtran'] ) ) {
 | |
| 				/* translators: %s: name of a tool like jpegtran */
 | |
| 				$result = sprintf( __( '%s is missing', 'ewww-image-optimizer' ), '<em>jpegtran</em>' );
 | |
| 				// Otherwise, things should be good, so...
 | |
| 			} else {
 | |
| 				// Set the optimization process to ON.
 | |
| 				$optimize = true;
 | |
| 			}
 | |
| 			// If local optimization is turned ON.
 | |
| 			if ( $optimize ) {
 | |
| 				ewwwio_debug_message( 'attempting to optimize JPG...' );
 | |
| 				// Generate temporary file-name.
 | |
| 				$progfile = $file . '.prog';
 | |
| 				// Check to see if we are supposed to strip metadata.
 | |
| 				if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_remove' ) && ! $keep_metadata ) {
 | |
| 					// Don't copy metadata.
 | |
| 					$copy_opt = 'none';
 | |
| 				} else {
 | |
| 					// Copy all the metadata.
 | |
| 					$copy_opt = 'all';
 | |
| 				}
 | |
| 				if ( $orig_size > 10240 ) {
 | |
| 					$progressive = '-progressive';
 | |
| 				} else {
 | |
| 					$progressive = '';
 | |
| 				}
 | |
| 				// Run jpegtran.
 | |
| 				$cmd = "$nice " . $tools['jpegtran'] . " -copy $copy_opt -optimize $progressive -outfile " . ewww_image_optimizer_escapeshellarg( $progfile ) . ' ' . ewww_image_optimizer_escapeshellarg( $file );
 | |
| 				ewwwio_debug_message( "running: $cmd" );
 | |
| 				exec( $cmd, $output, $exit );
 | |
| 				// Check the filesize of the new JPG.
 | |
| 				$new_size = ewww_image_optimizer_filesize( $progfile );
 | |
| 				ewwwio_debug_message( "optimized JPG size: $new_size" );
 | |
| 				// If the best-optimized is smaller than the original JPG, and we didn't create an empty JPG.
 | |
| 				if ( $new_size && $orig_size > $new_size && ewww_image_optimizer_mimetype( $progfile, 'i' ) === $type ) {
 | |
| 					// Replace the original with the optimized file.
 | |
| 					rename( $progfile, $file );
 | |
| 					// Store the results of the optimization.
 | |
| 					$result = "$orig_size vs. $new_size";
 | |
| 					// If the optimization didn't produce a smaller JPG.
 | |
| 				} else {
 | |
| 					if ( ewwwio_is_file( $progfile ) ) {
 | |
| 						// Delete the optimized file.
 | |
| 						ewwwio_delete_file( $progfile );
 | |
| 					}
 | |
| 					// Store the results.
 | |
| 					$result   = 'unchanged';
 | |
| 					$new_size = $orig_size;
 | |
| 				}
 | |
| 			} elseif ( ! $convert ) {
 | |
| 				ewwwio_debug_message( 'calling webp, but neither convert or optimize' );
 | |
| 				// If conversion and optimization are both turned OFF, finish the JPG processing.
 | |
| 				$webp_result = ewww_image_optimizer_webp_create( $file, $orig_size, $type, $tools['cwebp'] );
 | |
| 				break;
 | |
| 			} // End if().
 | |
| 			// If the conversion process is turned ON, or if this is a resize and the full-size was converted.
 | |
| 			if ( $convert ) {
 | |
| 				ewwwio_debug_message( "attempting to convert JPG to PNG: $pngfile" );
 | |
| 				if ( empty( $new_size ) ) {
 | |
| 					$new_size = $orig_size;
 | |
| 				}
 | |
| 				// Convert the JPG to PNG.
 | |
| 				if ( ewwwio()->gmagick_support() ) {
 | |
| 					try {
 | |
| 						$gmagick = new Gmagick( $file );
 | |
| 						$gmagick->stripimage();
 | |
| 						$gmagick->setimageformat( 'PNG' );
 | |
| 						$gmagick->writeimage( $pngfile );
 | |
| 					} catch ( Exception $gmagick_error ) {
 | |
| 						ewwwio_debug_message( $gmagick_error->getMessage() );
 | |
| 					}
 | |
| 					$png_size = ewww_image_optimizer_filesize( $pngfile );
 | |
| 				}
 | |
| 				if ( ! $png_size && ewwwio()->imagick_support() ) {
 | |
| 					try {
 | |
| 						$imagick = new Imagick( $file );
 | |
| 						$imagick->stripImage();
 | |
| 						$imagick->setImageFormat( 'PNG' );
 | |
| 						$imagick->writeImage( $pngfile );
 | |
| 					} catch ( Exception $imagick_error ) {
 | |
| 						ewwwio_debug_message( $imagick_error->getMessage() );
 | |
| 					}
 | |
| 					$png_size = ewww_image_optimizer_filesize( $pngfile );
 | |
| 				}
 | |
| 				if ( ! $png_size && ewwwio()->gd_support() ) {
 | |
| 					ewwwio_debug_message( 'converting with GD' );
 | |
| 					imagepng( imagecreatefromjpeg( $file ), $pngfile );
 | |
| 					$png_size = ewww_image_optimizer_filesize( $pngfile );
 | |
| 				}
 | |
| 				// If lossy optimization is ON and full-size exclusion is not active.
 | |
| 				if ( $png_size && 40 === (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ) && $tools['pngquant'] && ! $skip_lossy ) {
 | |
| 					ewwwio_debug_message( 'attempting lossy reduction' );
 | |
| 					$cmd = "$nice " . $tools['pngquant'] . ' ' . ewww_image_optimizer_escapeshellarg( $pngfile );
 | |
| 					ewwwio_debug_message( "running: $cmd" );
 | |
| 					exec( $cmd, $output, $exit );
 | |
| 					$quantfile = preg_replace( '/\.\w+$/', '-fs8.png', $pngfile );
 | |
| 					if ( ewwwio_is_file( $quantfile ) && filesize( $pngfile ) > filesize( $quantfile ) ) {
 | |
| 						ewwwio_debug_message( 'lossy reduction is better: original - ' . filesize( $pngfile ) . ' vs. lossy - ' . filesize( $quantfile ) );
 | |
| 						rename( $quantfile, $pngfile );
 | |
| 					} elseif ( ewwwio_is_file( $quantfile ) ) {
 | |
| 						ewwwio_debug_message( 'lossy reduction is worse: original - ' . filesize( $pngfile ) . ' vs. lossy - ' . filesize( $quantfile ) );
 | |
| 						ewwwio_delete_file( $quantfile );
 | |
| 					} else {
 | |
| 						ewwwio_debug_message( 'pngquant did not produce any output' );
 | |
| 					}
 | |
| 				}
 | |
| 				// If optipng isn't disabled.
 | |
| 				if ( $png_size && $tools['optipng'] ) {
 | |
| 					// Retrieve the optipng optimization level.
 | |
| 					$optipng_level = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_optipng_level' );
 | |
| 					if (
 | |
| 						ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_remove' ) &&
 | |
| 						preg_match( '/0.7/', ewwwio()->local->test_binary( $tools['optipng'], 'optipng' ) ) &&
 | |
| 						! $keep_metadata
 | |
| 					) {
 | |
| 						$strip = '-strip all ';
 | |
| 					} else {
 | |
| 						$strip = '';
 | |
| 					}
 | |
| 					// If the PNG file was created.
 | |
| 					if ( ewwwio_is_file( $pngfile ) ) {
 | |
| 						ewwwio_debug_message( 'optimizing converted PNG with optipng' );
 | |
| 						// Run optipng on the new PNG.
 | |
| 						$cmd = "$nice " . $tools['optipng'] . " -o$optipng_level -quiet $strip " . ewww_image_optimizer_escapeshellarg( $pngfile );
 | |
| 						ewwwio_debug_message( "running: $cmd" );
 | |
| 						exec( $cmd, $output, $exit );
 | |
| 					}
 | |
| 				}
 | |
| 				// If pngout isn't disabled.
 | |
| 				if ( $png_size && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_pngout' ) ) {
 | |
| 					// Retrieve the pngout optimization level.
 | |
| 					$pngout_level = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_pngout_level' );
 | |
| 					// If the PNG file was created.
 | |
| 					if ( ewwwio_is_file( $pngfile ) ) {
 | |
| 						ewwwio_debug_message( 'optimizing converted PNG with pngout' );
 | |
| 						// Run pngout on the new PNG.
 | |
| 						$cmd = "$nice " . $tools['pngout'] . " -s$pngout_level -q " . ewww_image_optimizer_escapeshellarg( $pngfile );
 | |
| 						ewwwio_debug_message( "running: $cmd" );
 | |
| 						exec( $cmd, $output, $exit );
 | |
| 					}
 | |
| 				}
 | |
| 				$png_size = ewww_image_optimizer_filesize( $pngfile );
 | |
| 				ewwwio_debug_message( "converted PNG size: $png_size" );
 | |
| 				// If the PNG is smaller than the original JPG, and we didn't end up with an empty file.
 | |
| 				if ( $png_size && $new_size > $png_size && ewww_image_optimizer_mimetype( $pngfile, 'i' ) === 'image/png' ) {
 | |
| 					ewwwio_debug_message( "converted PNG is better: $png_size vs. $new_size" );
 | |
| 					// Store the size of the converted PNG.
 | |
| 					$new_size = $png_size;
 | |
| 					// Check to see if the user wants the originals deleted.
 | |
| 					if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_delete_originals' ) ) {
 | |
| 						// Delete the original JPG.
 | |
| 						ewwwio_delete_file( $file );
 | |
| 					}
 | |
| 					// Store the location of the PNG file.
 | |
| 					$file = $pngfile;
 | |
| 					// Let webp know what we're dealing with now.
 | |
| 					$type = 'image/png';
 | |
| 					// Successful conversion and we store the increment.
 | |
| 					$converted = true;
 | |
| 				} else {
 | |
| 					ewwwio_debug_message( 'converted PNG is no good' );
 | |
| 					// Otherwise delete the PNG.
 | |
| 					$converted = false;
 | |
| 					if ( ewwwio_is_file( $pngfile ) ) {
 | |
| 						ewwwio_delete_file( $pngfile );
 | |
| 					}
 | |
| 				}
 | |
| 			} // End if().
 | |
| 			$webp_result = ewww_image_optimizer_webp_create( $file, $new_size, $type, $tools['cwebp'], $orig_size !== $new_size );
 | |
| 			break;
 | |
| 		case 'image/png':
 | |
| 			$jpg_size = 0;
 | |
| 			// Png2jpg conversion is turned on, and the image is in the WordPress media library.
 | |
| 			// We check for transparency later, after optimization, because optipng might fix an empty alpha channel.
 | |
| 			$apng = ewww_image_optimizer_is_animated_png( $file );
 | |
| 			if ( $apng ) {
 | |
| 				$keep_metadata = true;
 | |
| 				$skip_lossy    = true;
 | |
| 			}
 | |
| 			if (
 | |
| 				1 === (int) $gallery_type &&
 | |
| 				$fullsize &&
 | |
| 				( ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_to_jpg' ) || ! empty( $ewww_convert ) ) &&
 | |
| 				! $skip_lossy &&
 | |
| 				empty( $ewww_webp_only )
 | |
| 			) {
 | |
| 				ewwwio_debug_message( 'PNG to JPG conversion turned on' );
 | |
| 				$cloud_background = '';
 | |
| 				$r                = '';
 | |
| 				$g                = '';
 | |
| 				$b                = '';
 | |
| 				// If the user set a fill background for transparency.
 | |
| 				$background = ewww_image_optimizer_jpg_background();
 | |
| 				if ( $background ) {
 | |
| 					$cloud_background = "#$background";
 | |
| 					// Set background color for GD.
 | |
| 					$r = hexdec( '0x' . strtoupper( substr( $background, 0, 2 ) ) );
 | |
| 					$g = hexdec( '0x' . strtoupper( substr( $background, 2, 2 ) ) );
 | |
| 					$b = hexdec( '0x' . strtoupper( substr( $background, 4, 2 ) ) );
 | |
| 					// Set the background flag for 'convert'.
 | |
| 					$background = '-background ' . '"' . "#$background" . '"';
 | |
| 				}
 | |
| 				$gquality = ewww_image_optimizer_jpg_quality();
 | |
| 				$gquality = $gquality ? $gquality : '82';
 | |
| 				// If this is a resize version.
 | |
| 				if ( $converted ) {
 | |
| 					// Just replace the file extension with a .jpg.
 | |
| 					$jpgfile = preg_replace( '/\.\w+$/', '.jpg', $file );
 | |
| 					// If this is a full version.
 | |
| 				} else {
 | |
| 					// Construct the filename for the new JPG.
 | |
| 					$jpgfile = ewww_image_optimizer_unique_filename( $file, '.jpg' );
 | |
| 				}
 | |
| 			} else {
 | |
| 				ewwwio_debug_message( 'PNG to JPG conversion turned off' );
 | |
| 				// Turn the conversion process OFF.
 | |
| 				$convert          = false;
 | |
| 				$jpgfile          = '';
 | |
| 				$r                = null;
 | |
| 				$g                = null;
 | |
| 				$b                = null;
 | |
| 				$cloud_background = '';
 | |
| 				$gquality         = null;
 | |
| 			} // End if().
 | |
| 			$compression_level = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' );
 | |
| 			// Check for previous optimization, so long as the force flag is not on and this isn't a new image that needs converting.
 | |
| 			if ( empty( $ewww_force ) && ! ( $new_image && $convert ) ) {
 | |
| 				$results_msg = ewww_image_optimizer_check_table( $file, $orig_size );
 | |
| 				$smart_reopt = ! empty( $ewww_force_smart ) && ewww_image_optimizer_level_mismatch( $ewww_image->level, $compression_level ) ? true : false;
 | |
| 				if ( $smart_reopt ) {
 | |
| 					ewwwio_debug_message( "smart re-opt found level mismatch for $file, db says " . $ewww_image->level . " vs. current $compression_level" );
 | |
| 					// If the current compression level is less than what was previously used, and the previous level was premium (or premium plus).
 | |
| 					if ( $compression_level && $compression_level < $ewww_image->level && $ewww_image->level > 20 ) {
 | |
| 						ewwwio_debug_message( "smart re-opt triggering restoration for $file" );
 | |
| 						ewww_image_optimizer_cloud_restore_single_image( $ewww_image->record );
 | |
| 					}
 | |
| 				} elseif ( $results_msg ) {
 | |
| 					return array( $file, $results_msg, $converted, $original );
 | |
| 				}
 | |
| 			}
 | |
| 			$ewww_image->level = $compression_level;
 | |
| 			if (
 | |
| 				$compression_level >= 20 &&
 | |
| 				ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) &&
 | |
| 				empty( $ewww_webp_only )
 | |
| 			) {
 | |
| 				list( $file, $converted, $result, $new_size, $backup_hash ) = ewww_image_optimizer_cloud_optimizer(
 | |
| 					$file,
 | |
| 					$type,
 | |
| 					$convert,
 | |
| 					$jpgfile,
 | |
| 					'image/jpeg',
 | |
| 					$skip_lossy,
 | |
| 					$cloud_background,
 | |
| 					$gquality
 | |
| 				);
 | |
| 				if ( $converted ) {
 | |
| 					// Check to see if the user wants the originals deleted.
 | |
| 					if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_delete_originals' ) ) {
 | |
| 						// Delete the original JPG.
 | |
| 						ewwwio_delete_file( $original );
 | |
| 					}
 | |
| 					$converted   = true;
 | |
| 					$webp_result = ewww_image_optimizer_webp_create( $file, $new_size, 'image/jpeg', null, $orig_size !== $new_size );
 | |
| 				} else {
 | |
| 					$webp_result = ewww_image_optimizer_webp_create( $file, $new_size, $type, null, $orig_size !== $new_size );
 | |
| 				}
 | |
| 				break;
 | |
| 			}
 | |
| 			// For exec-deprived servers, allow free WebP conversion.
 | |
| 			if ( 10 >= (int) $compression_level && ! ewwwio()->local->exec_check() ) {
 | |
| 				$webp_result = ewww_image_optimizer_webp_create( $file, $orig_size, $type, null, $orig_size !== $new_size );
 | |
| 				break;
 | |
| 			}
 | |
| 			$tools['optipng']  = ewwwio()->local->get_path( 'optipng' );
 | |
| 			$tools['pngout']   = ewwwio()->local->get_path( 'pngout' );
 | |
| 			$tools['pngquant'] = ewwwio()->local->get_path( 'pngquant' );
 | |
| 			$tools['cwebp']    = ewwwio()->local->get_path( 'cwebp' );
 | |
| 			if ( $convert ) {
 | |
| 				$tools['jpegtran'] = ewwwio()->local->get_path( 'jpegtran' );
 | |
| 			}
 | |
| 			// Check if we can (and should) do local PNG optimization.
 | |
| 			if ( ! empty( $ewww_webp_only ) ) {
 | |
| 				$optimize = false;
 | |
| 			} elseif ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ) ) {
 | |
| 				// Tell the user all PNG tools are disabled.
 | |
| 				$result = __( 'PNG optimization is disabled', 'ewww-image-optimizer' );
 | |
| 				// If the utility checking is on, optipng is enabled, but optipng cannot be found.
 | |
| 			} elseif ( empty( $tools['optipng'] ) ) {
 | |
| 				/* translators: %s: name of a tool like jpegtran */
 | |
| 				$result = sprintf( __( '%s is missing', 'ewww-image-optimizer' ), '<em>optipng</em>' );
 | |
| 				// If the utility checking is on, pngout is enabled, but pngout cannot be found.
 | |
| 			} else {
 | |
| 				// Turn optimization on if we made it through all the checks.
 | |
| 				$optimize = true;
 | |
| 			}
 | |
| 			// If optimization is turned on.
 | |
| 			if ( $optimize ) {
 | |
| 				// If lossy optimization is ON and full-size exclusion is not active.
 | |
| 				if ( 40 === (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_png_level' ) && $tools['pngquant'] && ! $skip_lossy ) {
 | |
| 					ewwwio_debug_message( 'attempting lossy reduction' );
 | |
| 					$cmd = "$nice " . $tools['pngquant'] . ' ' . ewww_image_optimizer_escapeshellarg( $file );
 | |
| 					ewwwio_debug_message( "running: $cmd" );
 | |
| 					exec( $cmd, $output, $exit );
 | |
| 					$quantfile = preg_replace( '/\.\w+$/', '-fs8.png', $file );
 | |
| 					if ( ewwwio_is_file( $quantfile ) && filesize( $file ) > filesize( $quantfile ) && ewww_image_optimizer_mimetype( $quantfile, 'i' ) === $type ) {
 | |
| 						ewwwio_debug_message( 'lossy reduction is better: original - ' . filesize( $file ) . ' vs. lossy - ' . filesize( $quantfile ) );
 | |
| 						rename( $quantfile, $file );
 | |
| 					} elseif ( ewwwio_is_file( $quantfile ) ) {
 | |
| 						ewwwio_debug_message( 'lossy reduction is worse: original - ' . filesize( $file ) . ' vs. lossy - ' . filesize( $quantfile ) );
 | |
| 						ewwwio_delete_file( $quantfile );
 | |
| 					} else {
 | |
| 						ewwwio_debug_message( 'pngquant did not produce any output' );
 | |
| 					}
 | |
| 				}
 | |
| 				$tempfile = $file . '.tmp.png';
 | |
| 				copy( $file, $tempfile );
 | |
| 				// If optipng is enabled.
 | |
| 				if ( $tools['optipng'] ) {
 | |
| 					// Retrieve the optimization level for optipng.
 | |
| 					$optipng_level = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_optipng_level' );
 | |
| 					$strip         = '';
 | |
| 					if (
 | |
| 						ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_remove' ) &&
 | |
| 						preg_match( '/0.7/', ewwwio()->local->test_binary( $tools['optipng'], 'optipng' ) ) &&
 | |
| 						! $keep_metadata
 | |
| 					) {
 | |
| 						$strip = '-strip all ';
 | |
| 					}
 | |
| 					// Run optipng on the PNG file.
 | |
| 					$cmd = "$nice " . $tools['optipng'] . " -o$optipng_level -quiet $strip " . ewww_image_optimizer_escapeshellarg( $tempfile );
 | |
| 					ewwwio_debug_message( "running: $cmd" );
 | |
| 					exec( $cmd, $output, $exit );
 | |
| 				}
 | |
| 				// If pngout is enabled.
 | |
| 				if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_pngout' ) ) {
 | |
| 					// Retrieve the optimization level for pngout.
 | |
| 					$pngout_level = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_pngout_level' );
 | |
| 					$strip        = '';
 | |
| 					if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_remove' ) || $keep_metadata ) {
 | |
| 						$strip = '-k1';
 | |
| 					}
 | |
| 					// Run pngout on the PNG file.
 | |
| 					$cmd = "$nice " . $tools['pngout'] . " -s$pngout_level -k1 -q " . ewww_image_optimizer_escapeshellarg( $tempfile );
 | |
| 					ewwwio_debug_message( "running: $cmd" );
 | |
| 					exec( $cmd, $output, $exit );
 | |
| 				}
 | |
| 				// Retrieve the filesize of the temporary PNG.
 | |
| 				$new_size = ewww_image_optimizer_filesize( $tempfile );
 | |
| 				// If the new PNG is smaller.
 | |
| 				if ( $new_size && $orig_size > $new_size && ewww_image_optimizer_mimetype( $tempfile, 'i' ) === $type ) {
 | |
| 					// Replace the original with the optimized file.
 | |
| 					rename( $tempfile, $file );
 | |
| 					// Store the results of the optimization.
 | |
| 					$result = "$orig_size vs. $new_size";
 | |
| 					// If the optimization didn't produce a smaller PNG.
 | |
| 				} else {
 | |
| 					if ( ewwwio_is_file( $tempfile ) ) {
 | |
| 						// Delete the optimized file.
 | |
| 						ewwwio_delete_file( $tempfile );
 | |
| 					}
 | |
| 					// Store the results.
 | |
| 					$result   = 'unchanged';
 | |
| 					$new_size = $orig_size;
 | |
| 				}
 | |
| 			} elseif ( ! $convert ) {
 | |
| 				// If conversion and optimization are both disabled we are done here.
 | |
| 				ewwwio_debug_message( 'calling webp, but neither convert or optimize' );
 | |
| 				$webp_result = ewww_image_optimizer_webp_create( $file, $orig_size, $type, $tools['cwebp'] );
 | |
| 				break;
 | |
| 			} // End if().
 | |
| 			// Retrieve the new filesize of the PNG.
 | |
| 			$new_size = ewww_image_optimizer_filesize( $file );
 | |
| 			// Double check for png2jpg conversion to see if we have an alpha image.
 | |
| 			if ( $convert && ewww_image_optimizer_png_alpha( $file ) && ! ewww_image_optimizer_jpg_background() ) {
 | |
| 				ewwwio_debug_message( 'PNG to JPG conversion turned off due to alpha' );
 | |
| 				$convert = false;
 | |
| 			}
 | |
| 			// If conversion is on and the PNG doesn't have transparency or the user set a background color to replace transparency.
 | |
| 			if ( $convert ) {
 | |
| 				ewwwio_debug_message( "attempting to convert PNG to JPG: $jpgfile" );
 | |
| 				if ( empty( $new_size ) ) {
 | |
| 					$new_size = $orig_size;
 | |
| 				}
 | |
| 				$magick_background = ewww_image_optimizer_jpg_background();
 | |
| 				if ( empty( $magick_background ) ) {
 | |
| 					$magick_background = '000000';
 | |
| 				}
 | |
| 				// Convert the PNG to a JPG with all the proper options.
 | |
| 				if ( ewwwio()->gmagick_support() ) {
 | |
| 					try {
 | |
| 						if ( ewww_image_optimizer_png_alpha( $file ) ) {
 | |
| 							$gmagick_overlay = new Gmagick( $file );
 | |
| 							$gmagick         = new Gmagick();
 | |
| 							$gmagick->newimage( $gmagick_overlay->getimagewidth(), $gmagick_overlay->getimageheight(), '#' . $magick_background );
 | |
| 							$gmagick->compositeimage( $gmagick_overlay, 1, 0, 0 );
 | |
| 						} else {
 | |
| 							$gmagick = new Gmagick( $file );
 | |
| 						}
 | |
| 						$gmagick->setimageformat( 'JPG' );
 | |
| 						$gmagick->setcompressionquality( $gquality );
 | |
| 						$gmagick->writeimage( $jpgfile );
 | |
| 					} catch ( Exception $gmagick_error ) {
 | |
| 						ewwwio_debug_message( $gmagick_error->getMessage() );
 | |
| 					}
 | |
| 					$jpg_size = ewww_image_optimizer_filesize( $jpgfile );
 | |
| 				}
 | |
| 				if ( ! $jpg_size && ewwwio()->imagick_support() ) {
 | |
| 					try {
 | |
| 						$imagick = new Imagick( $file );
 | |
| 						if ( ewww_image_optimizer_png_alpha( $file ) ) {
 | |
| 							$imagick->setImageBackgroundColor( new ImagickPixel( '#' . $magick_background ) );
 | |
| 							$imagick->setImageAlphaChannel( 11 );
 | |
| 						}
 | |
| 						$imagick->setImageFormat( 'JPG' );
 | |
| 						$imagick->setImageCompressionQuality( $gquality );
 | |
| 						$imagick->writeImage( $jpgfile );
 | |
| 					} catch ( Exception $imagick_error ) {
 | |
| 						ewwwio_debug_message( $imagick_error->getMessage() );
 | |
| 					}
 | |
| 					$jpg_size = ewww_image_optimizer_filesize( $jpgfile );
 | |
| 				}
 | |
| 				if ( ! $jpg_size && ewwwio()->gd_support() ) {
 | |
| 					ewwwio_debug_message( 'converting with GD' );
 | |
| 					// Retrieve the data from the PNG.
 | |
| 					$input = imagecreatefrompng( $file );
 | |
| 					// Retrieve the dimensions of the PNG.
 | |
| 					list($width, $height) = wp_getimagesize( $file );
 | |
| 					// Create a new image with those dimensions.
 | |
| 					$output = imagecreatetruecolor( $width, $height );
 | |
| 					if ( '' === $r ) {
 | |
| 						$r = 255;
 | |
| 						$g = 255;
 | |
| 						$b = 255;
 | |
| 					}
 | |
| 					// Allocate the background color.
 | |
| 					$rgb = imagecolorallocate( $output, $r, $g, $b );
 | |
| 					// Fill the new image with the background color.
 | |
| 					imagefilledrectangle( $output, 0, 0, $width, $height, $rgb );
 | |
| 					// Copy the original image to the new image.
 | |
| 					imagecopy( $output, $input, 0, 0, 0, 0, $width, $height );
 | |
| 					// Output the JPG with the quality setting.
 | |
| 					imagejpeg( $output, $jpgfile, $gquality );
 | |
| 				}
 | |
| 				$jpg_size = ewww_image_optimizer_filesize( $jpgfile );
 | |
| 				if ( $jpg_size ) {
 | |
| 					ewwwio_debug_message( "converted JPG filesize: $jpg_size" );
 | |
| 				} else {
 | |
| 					ewwwio_debug_message( 'unable to convert to JPG' );
 | |
| 				}
 | |
| 				// Next we need to optimize that JPG if jpegtran is enabled.
 | |
| 				if ( 10 === (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpg_level' ) && ewwwio_is_file( $jpgfile ) && ! empty( $tools['jpegtran'] ) ) {
 | |
| 					// Generate temporary file-name.
 | |
| 					$progfile = $jpgfile . '.prog';
 | |
| 					// Check to see if we are supposed to strip metadata.
 | |
| 					if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_remove' ) && ! $keep_metadata ) {
 | |
| 						// Don't copy metadata.
 | |
| 						$copy_opt = 'none';
 | |
| 					} else {
 | |
| 						// Copy all the metadata.
 | |
| 						$copy_opt = 'all';
 | |
| 					}
 | |
| 					if ( $jpg_size > 10240 ) {
 | |
| 						$progressive = '-progressive';
 | |
| 					} else {
 | |
| 						$progressive = '';
 | |
| 					}
 | |
| 					// Run jpegtran.
 | |
| 					$cmd = "$nice " . $tools['jpegtran'] . " -copy $copy_opt -optimize $progressive -outfile " . ewww_image_optimizer_escapeshellarg( $progfile ) . ' ' . ewww_image_optimizer_escapeshellarg( $jpgfile );
 | |
| 					ewwwio_debug_message( "running: $cmd" );
 | |
| 					exec( $cmd, $output, $exit );
 | |
| 					// Check the filesize of the new JPG.
 | |
| 					$opt_jpg_size = ewww_image_optimizer_filesize( $progfile );
 | |
| 					// If the best-optimized is smaller than the original JPG, and we didn't create an empty JPG.
 | |
| 					if ( $opt_jpg_size && $jpg_size > $opt_jpg_size ) {
 | |
| 						// Replace the original with the optimized file.
 | |
| 						rename( $progfile, $jpgfile );
 | |
| 						// Store the size of the optimized JPG.
 | |
| 						$jpg_size = $opt_jpg_size;
 | |
| 						ewwwio_debug_message( 'optimized JPG was smaller than un-optimized version' );
 | |
| 						// If the optimization didn't produce a smaller JPG.
 | |
| 					} elseif ( ewwwio_is_file( $progfile ) ) {
 | |
| 						ewwwio_delete_file( $progfile );
 | |
| 					}
 | |
| 				}
 | |
| 				ewwwio_debug_message( "converted JPG size: $jpg_size" );
 | |
| 				// If the new JPG is smaller than the original PNG.
 | |
| 				if ( $jpg_size && $new_size > $jpg_size && ewww_image_optimizer_mimetype( $jpgfile, 'i' ) === 'image/jpeg' ) {
 | |
| 					// Store the size of the JPG as the new filesize.
 | |
| 					$new_size = $jpg_size;
 | |
| 					// If the user wants originals delted after a conversion.
 | |
| 					if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_delete_originals' ) ) {
 | |
| 						// Delete the original PNG.
 | |
| 						ewwwio_delete_file( $file );
 | |
| 					}
 | |
| 					// Update the $file location to the new JPG.
 | |
| 					$file = $jpgfile;
 | |
| 					// Let webp know what we're dealing with now.
 | |
| 					$type = 'image/jpeg';
 | |
| 					// Successful conversion, so we store the increment.
 | |
| 					$converted = true;
 | |
| 				} else {
 | |
| 					$converted = false;
 | |
| 					if ( ewwwio_is_file( $jpgfile ) ) {
 | |
| 						// Otherwise delete the new JPG.
 | |
| 						ewwwio_delete_file( $jpgfile );
 | |
| 					}
 | |
| 				}
 | |
| 			} // End if().
 | |
| 			$webp_result = ewww_image_optimizer_webp_create( $file, $new_size, $type, $tools['cwebp'], $orig_size !== $new_size );
 | |
| 			break;
 | |
| 		case 'image/gif':
 | |
| 			// If gif2png is turned on, and the image is in the WordPress media library.
 | |
| 			if (
 | |
| 				empty( $ewww_webp_only ) &&
 | |
| 				1 === (int) $gallery_type &&
 | |
| 				$fullsize &&
 | |
| 				( ewww_image_optimizer_get_option( 'ewww_image_optimizer_gif_to_png' ) || ! empty( $ewww_convert ) ) &&
 | |
| 				! ewww_image_optimizer_is_animated( $file )
 | |
| 			) {
 | |
| 				// Generate the filename for a PNG:
 | |
| 				// if this is a resize version...
 | |
| 				if ( $converted ) {
 | |
| 					// just change the file extension.
 | |
| 					$pngfile = preg_replace( '/\.\w+$/', '.png', $file );
 | |
| 				} else {
 | |
| 					// If this is the full version...
 | |
| 					// construct the filename for the new PNG.
 | |
| 					$pngfile = ewww_image_optimizer_unique_filename( $file, '.png' );
 | |
| 				}
 | |
| 			} else {
 | |
| 				// Turn conversion OFF.
 | |
| 				$convert = false;
 | |
| 				$pngfile = '';
 | |
| 			}
 | |
| 			$compression_level = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_gif_level' );
 | |
| 			// Check for previous optimization, so long as the force flag is on and this isn't a new image that needs converting.
 | |
| 			if ( empty( $ewww_force ) && ! ( $new_image && $convert ) ) {
 | |
| 				$results_msg = ewww_image_optimizer_check_table( $file, $orig_size );
 | |
| 				$smart_reopt = ! empty( $ewww_force_smart ) && ewww_image_optimizer_level_mismatch( $ewww_image->level, $compression_level ) ? true : false;
 | |
| 				if ( $smart_reopt ) {
 | |
| 					ewwwio_debug_message( "smart re-opt found level mismatch for $file, db says " . $ewww_image->level . " vs. current $compression_level" );
 | |
| 					// If the current compression level is less than what was previously used, and the previous level was premium (or premium plus).
 | |
| 					if ( $compression_level && $compression_level < $ewww_image->level && $ewww_image->level > 20 ) {
 | |
| 						ewwwio_debug_message( "smart re-opt triggering restoration for $file" );
 | |
| 						ewww_image_optimizer_cloud_restore_single_image( $ewww_image->record );
 | |
| 					}
 | |
| 				} elseif ( $results_msg ) {
 | |
| 					return array( $file, $results_msg, $converted, $original );
 | |
| 				}
 | |
| 			}
 | |
| 			$ewww_image->level = $compression_level;
 | |
| 			if ( empty( $ewww_webp_only ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) && 10 === $compression_level ) {
 | |
| 				list( $file, $converted, $result, $new_size, $backup_hash ) = ewww_image_optimizer_cloud_optimizer( $file, $type, $convert, $pngfile, 'image/png', $skip_lossy );
 | |
| 				if ( $converted ) {
 | |
| 					// Check to see if the user wants the originals deleted.
 | |
| 					if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_delete_originals' ) ) {
 | |
| 						// Delete the original GIF.
 | |
| 						ewwwio_delete_file( $original );
 | |
| 					}
 | |
| 					$converted   = true;
 | |
| 					$webp_result = ewww_image_optimizer_webp_create( $file, $new_size, 'image/png', null, $orig_size !== $new_size );
 | |
| 				} else {
 | |
| 					$webp_result = ewww_image_optimizer_webp_create( $file, $new_size, $type, null, $orig_size !== $new_size );
 | |
| 				}
 | |
| 				break;
 | |
| 			}
 | |
| 			$tools['gifsicle'] = ewwwio()->local->get_path( 'gifsicle' );
 | |
| 			if ( $convert ) {
 | |
| 				// NOTE: we can only do local WebP if a GIF is converted to PNG.
 | |
| 				$tools['cwebp']    = ewwwio()->local->get_path( 'cwebp' );
 | |
| 				$tools['optipng']  = ewwwio()->local->get_path( 'optipng' );
 | |
| 				$tools['pngout']   = ewwwio()->local->get_path( 'pngout' );
 | |
| 				$tools['pngquant'] = ewwwio()->local->get_path( 'pngquant' );
 | |
| 			}
 | |
| 			// Check if we can (and should) do local GIF optimization.
 | |
| 			if ( ! empty( $ewww_webp_only ) ) {
 | |
| 				$optimize = false;
 | |
| 			} elseif ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_gif_level' ) ) {
 | |
| 				$result = __( 'GIF optimization is disabled', 'ewww-image-optimizer' );
 | |
| 				// If utility checking is on, and gifsicle is not installed.
 | |
| 			} elseif ( empty( $tools['gifsicle'] ) ) {
 | |
| 				/* translators: %s: name of a tool like jpegtran */
 | |
| 				$result = sprintf( __( '%s is missing', 'ewww-image-optimizer' ), '<em>gifsicle</em>' );
 | |
| 			} else {
 | |
| 				// Otherwise, turn optimization ON.
 | |
| 				$optimize = true;
 | |
| 			}
 | |
| 			// If local optimization is turned ON.
 | |
| 			if ( $optimize ) {
 | |
| 				$tempfile = $file . '.tmp'; // temporary GIF output.
 | |
| 				// Run gifsicle on the GIF.
 | |
| 				$cmd = "$nice " . $tools['gifsicle'] . ' -O3 --careful -o ' . ewww_image_optimizer_escapeshellarg( $tempfile ) . ' ' . ewww_image_optimizer_escapeshellarg( $file );
 | |
| 				ewwwio_debug_message( "running: $cmd" );
 | |
| 				exec( $cmd, $output, $exit );
 | |
| 				// Retrieve the filesize of the temporary GIF.
 | |
| 				$new_size = ewww_image_optimizer_filesize( $tempfile );
 | |
| 				// If the new GIF is smaller.
 | |
| 				if ( $new_size && $orig_size > $new_size && ewww_image_optimizer_mimetype( $tempfile, 'i' ) === $type ) {
 | |
| 					// Replace the original with the optimized file.
 | |
| 					rename( $tempfile, $file );
 | |
| 					// Store the results of the optimization.
 | |
| 					$result = "$orig_size vs. $new_size";
 | |
| 					// If the optimization didn't produce a smaller GIF.
 | |
| 				} else {
 | |
| 					if ( ewwwio_is_file( $tempfile ) ) {
 | |
| 						// Delete the optimized file.
 | |
| 						ewwwio_delete_file( $tempfile );
 | |
| 					}
 | |
| 					// Store the results.
 | |
| 					$result   = 'unchanged';
 | |
| 					$new_size = $orig_size;
 | |
| 				}
 | |
| 			} elseif ( ! $convert ) {
 | |
| 				// This is for WebP-only mode, no conversion/optimization, and it'll be done via API.
 | |
| 				$webp_result = ewww_image_optimizer_webp_create( $file, $orig_size, $type, null, $orig_size !== $new_size );
 | |
| 				break;
 | |
| 			}
 | |
| 			// Get the new filesize for the GIF.
 | |
| 			$new_size = ewww_image_optimizer_filesize( $file );
 | |
| 			// If conversion is ON and the GIF isn't animated.
 | |
| 			if ( $convert && ! ewww_image_optimizer_is_animated( $file ) ) {
 | |
| 				if ( empty( $new_size ) ) {
 | |
| 					$new_size = $orig_size;
 | |
| 				}
 | |
| 				// If optipng is enabled.
 | |
| 				if ( $tools['optipng'] ) {
 | |
| 					// Retrieve the optipng optimization level.
 | |
| 					$optipng_level = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_optipng_level' );
 | |
| 					if (
 | |
| 						ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_remove' ) &&
 | |
| 						preg_match( '/0.7/', ewwwio()->local->test_binary( $tools['optipng'], 'optipng' ) ) &&
 | |
| 						! $keep_metadata
 | |
| 					) {
 | |
| 						$strip = '-strip all ';
 | |
| 					} else {
 | |
| 						$strip = '';
 | |
| 					}
 | |
| 					// Run optipng on the GIF file.
 | |
| 					$cmd = "$nice " . $tools['optipng'] . ' -out ' . ewww_image_optimizer_escapeshellarg( $pngfile ) . " -o$optipng_level -quiet $strip " . ewww_image_optimizer_escapeshellarg( $file );
 | |
| 					ewwwio_debug_message( "running: $cmd" );
 | |
| 					exec( $cmd, $output, $exit );
 | |
| 				}
 | |
| 				// If pngout is enabled.
 | |
| 				if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_disable_pngout' ) && $tools['pngout'] ) {
 | |
| 					// Retrieve the pngout optimization level.
 | |
| 					$pngout_level = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_pngout_level' );
 | |
| 					// Run pngout on the GIF file directly (if optipng didn't work or isn't available).
 | |
| 					$cmd = "$nice " . $tools['pngout'] . " -s$pngout_level -q " . ewww_image_optimizer_escapeshellarg( $file ) . ' ' . ewww_image_optimizer_escapeshellarg( $pngfile );
 | |
| 					// BUT, if $pngfile exists, which means optipng was successful at converting the GIF.
 | |
| 					if ( ewwwio_is_file( $pngfile ) ) {
 | |
| 						// Run pngout on the PNG file.
 | |
| 						$cmd = "$nice " . $tools['pngout'] . " -s$pngout_level -q " . ewww_image_optimizer_escapeshellarg( $pngfile );
 | |
| 					}
 | |
| 					ewwwio_debug_message( "running: $cmd" );
 | |
| 					exec( $cmd, $output, $exit );
 | |
| 				}
 | |
| 				// Retrieve the filesize of the PNG.
 | |
| 				$png_size = ewww_image_optimizer_filesize( $pngfile );
 | |
| 				// If the new PNG is smaller than the original GIF.
 | |
| 				if ( $png_size && $new_size > $png_size && ewww_image_optimizer_mimetype( $pngfile, 'i' ) === 'image/png' ) {
 | |
| 					// Store the PNG size as the new filesize.
 | |
| 					$new_size = $png_size;
 | |
| 					// If the user wants original GIFs deleted after successful conversion.
 | |
| 					if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_delete_originals' ) ) {
 | |
| 						// Delete the original GIF.
 | |
| 						ewwwio_delete_file( $file );
 | |
| 					}
 | |
| 					// Update the $file location with the new PNG.
 | |
| 					$file = $pngfile;
 | |
| 					// Let webp know what we're dealing with now.
 | |
| 					$type = 'image/png';
 | |
| 					// Normally this would be at the end of the section, but we only want to do webp if the image was successfully converted to a png.
 | |
| 					$webp_result = ewww_image_optimizer_webp_create( $file, $new_size, $type, $tools['cwebp'], $orig_size !== $new_size );
 | |
| 					// Successful conversion, so we store the increment.
 | |
| 					$converted = true;
 | |
| 				} else {
 | |
| 					$converted = false;
 | |
| 					if ( ewwwio_is_file( $pngfile ) ) {
 | |
| 						ewwwio_delete_file( $pngfile );
 | |
| 					}
 | |
| 				}
 | |
| 			} // End if().
 | |
| 			break;
 | |
| 		case 'application/pdf':
 | |
| 			if ( ! empty( $ewww_webp_only ) ) {
 | |
| 				break;
 | |
| 			}
 | |
| 			$compression_level = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_pdf_level' );
 | |
| 			if ( empty( $ewww_force ) ) {
 | |
| 				$results_msg = ewww_image_optimizer_check_table( $file, $orig_size );
 | |
| 				$smart_reopt = ! empty( $ewww_force_smart ) && ewww_image_optimizer_level_mismatch( $ewww_image->level, $compression_level ) ? true : false;
 | |
| 				if ( $smart_reopt ) {
 | |
| 					ewwwio_debug_message( "smart re-opt found level mismatch for $file, db says " . $ewww_image->level . " vs. current $compression_level" );
 | |
| 					// If the current compression level is less than what was previously used, and the previous level was premium (or premium plus).
 | |
| 					if ( $compression_level && $compression_level < $ewww_image->level && $ewww_image->level > 20 ) {
 | |
| 						ewwwio_debug_message( "smart re-opt triggering restoration for $file" );
 | |
| 						ewww_image_optimizer_cloud_restore_single_image( $ewww_image->record );
 | |
| 					}
 | |
| 				} elseif ( $results_msg ) {
 | |
| 					return array( $file, $results_msg, $converted, $original );
 | |
| 				}
 | |
| 			}
 | |
| 			$ewww_image->level = $compression_level;
 | |
| 			if ( $compression_level > 0 ) {
 | |
| 				list( $file, $converted, $result, $new_size, $backup_hash ) = ewww_image_optimizer_cloud_optimizer( $file, $type );
 | |
| 			}
 | |
| 			break;
 | |
| 		case 'image/svg+xml':
 | |
| 			if ( ! empty( $ewww_webp_only ) ) {
 | |
| 				break;
 | |
| 			}
 | |
| 			$compression_level = (int) ewww_image_optimizer_get_option( 'ewww_image_optimizer_svg_level' );
 | |
| 			// Check for previous optimization, so long as the force flag is not on and this isn't a new image that needs converting.
 | |
| 			if ( empty( $ewww_force ) ) {
 | |
| 				$results_msg = ewww_image_optimizer_check_table( $file, $orig_size );
 | |
| 				$smart_reopt = ! empty( $ewww_force_smart ) && ewww_image_optimizer_level_mismatch( $ewww_image->level, $compression_level ) ? true : false;
 | |
| 				if ( $smart_reopt ) {
 | |
| 					ewwwio_debug_message( "smart re-opt found level mismatch for $file, db says " . $ewww_image->level . " vs. current $compression_level" );
 | |
| 					// If the current compression level is less than what was previously used, and the previous level was premium (or premium plus).
 | |
| 					if ( $compression_level && $compression_level < $ewww_image->level && $ewww_image->level > 0 ) {
 | |
| 						ewwwio_debug_message( "smart re-opt triggering restoration for $file" );
 | |
| 						ewww_image_optimizer_cloud_restore_single_image( $ewww_image->record );
 | |
| 					}
 | |
| 				} elseif ( $results_msg ) {
 | |
| 					return array( $file, $results_msg, $converted, $original );
 | |
| 				}
 | |
| 			}
 | |
| 			$ewww_image->level = $compression_level;
 | |
| 			if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) && $compression_level > 0 ) {
 | |
| 				list( $file, $converted, $result, $new_size, $backup_hash ) = ewww_image_optimizer_cloud_optimizer( $file, $type );
 | |
| 				break;
 | |
| 			}
 | |
| 			$tools['svgcleaner'] = ewwwio()->local->get_path( 'svgcleaner' );
 | |
| 			// If svgcleaner is disabled.
 | |
| 			if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_svg_level' ) ) {
 | |
| 				$result = __( 'SVG optimization is disabled', 'ewww-image-optimizer' );
 | |
| 			} elseif ( empty( $tools['svgcleaner'] ) ) {
 | |
| 				/* translators: %s: name of a tool like jpegtran */
 | |
| 				$result = sprintf( __( '%s is missing', 'ewww-image-optimizer' ), '<em>svgcleaner</em>' );
 | |
| 			} else {
 | |
| 				// Otherwise, turn optimization ON.
 | |
| 				$optimize = true;
 | |
| 			}
 | |
| 			// If local optimization is turned ON.
 | |
| 			if ( $optimize ) {
 | |
| 				$tempfile = $file . '.tmp.svg'; // temporary SVG output (must end with .svg)
 | |
| 				// Run svgcleaner on the SVG.
 | |
| 				$svgcleaner_options = array(
 | |
| 					'--allow-bigger-file',
 | |
| 					'--quiet',
 | |
| 				);
 | |
| 				if ( 1 === $compression_level ) {
 | |
| 					array_push(
 | |
| 						$svgcleaner_options,
 | |
| 						'--paths-to-relative=no',
 | |
| 						'--remove-unused-segments=no',
 | |
| 						'--convert-segments=no',
 | |
| 						'--merge-gradients=no',
 | |
| 						'--trim-ids=no',
 | |
| 						'--trim-colors=no',
 | |
| 						'--simplify-transforms=no',
 | |
| 						'--resolve-use=no'
 | |
| 					);
 | |
| 				}
 | |
| 				$cmd = "$nice " . $tools['svgcleaner'] . ' ' . implode( ' ', $svgcleaner_options ) . ' ' . ewww_image_optimizer_escapeshellarg( $file ) . ' ' . ewww_image_optimizer_escapeshellarg( $tempfile );
 | |
| 				ewwwio_debug_message( "running: $cmd" );
 | |
| 				exec( $cmd, $output, $exit );
 | |
| 				// Retrieve the filesize of the temporary SVG.
 | |
| 				$new_size = ewww_image_optimizer_filesize( $tempfile );
 | |
| 				// If the new SVG is smaller.
 | |
| 				if ( $new_size && $orig_size > $new_size && ewww_image_optimizer_mimetype( $tempfile, 'i' ) === $type ) {
 | |
| 					// Replace the original with the optimized file.
 | |
| 					rename( $tempfile, $file );
 | |
| 					// Store the results of the optimization.
 | |
| 					$result = "$orig_size vs. $new_size";
 | |
| 					// If the optimization didn't produce a smaller SVG.
 | |
| 				} else {
 | |
| 					if ( ewwwio_is_file( $tempfile ) ) {
 | |
| 						// Delete the optimized file.
 | |
| 						ewwwio_delete_file( $tempfile );
 | |
| 					}
 | |
| 					// Store the results.
 | |
| 					$result   = 'unchanged';
 | |
| 					$new_size = $orig_size;
 | |
| 				}
 | |
| 			}
 | |
| 			break;
 | |
| 		default:
 | |
| 			// If not a JPG, PNG, GIF, PDF or SVG tell the user we don't work with strangers.
 | |
| 			return array( false, __( 'Unsupported file type', 'ewww-image-optimizer' ) . ": $type", $converted, $original );
 | |
| 	} // End switch().
 | |
| 	// Allow other plugins to run operations on the images after optimization.
 | |
| 	// NOTE: it is recommended to do any image modifications prior to optimization, otherwise you risk un-optimizing your images here.
 | |
| 	do_action( 'ewww_image_optimizer_post_optimization', $file, $type, $fullsize );
 | |
| 	// If their cloud api license limit has been exceeded.
 | |
| 	if ( 'exceeded' === $result ) {
 | |
| 		return array( false, __( 'License exceeded', 'ewww-image-optimizer' ), $converted, $original );
 | |
| 	} elseif ( 'exceeded quota' === $result ) {
 | |
| 		return array( false, __( 'Soft Quota Reached', 'ewww-image-optimizer' ), $converted, $original );
 | |
| 	}
 | |
| 	if ( ! empty( $new_size ) ) {
 | |
| 		// Set correct file permissions.
 | |
| 		$stat = stat( dirname( $file ) );
 | |
| 		ewwwio_debug_message( 'folder mode: ' . $stat['mode'] );
 | |
| 		$perms = $stat['mode'] & 0000666; // Same permissions as parent folder, strip off the executable bits.
 | |
| 		ewwwio_debug_message( "attempting chmod with $perms" );
 | |
| 		ewwwio_chmod( $file, $perms );
 | |
| 
 | |
| 		$results_msg = ewww_image_optimizer_update_table( $file, $new_size, $orig_size, $original, $backup_hash );
 | |
| 		if ( ! empty( $webp_result ) ) {
 | |
| 			$results_msg .= '<br>' . $webp_result;
 | |
| 		}
 | |
| 		ewwwio_memory( __FUNCTION__ );
 | |
| 		return array( $file, $results_msg, $converted, $original );
 | |
| 	}
 | |
| 	ewwwio_memory( __FUNCTION__ );
 | |
| 	// Otherwise, send back the filename, the results (some sort of error message), the $converted flag, and the name of the original image.
 | |
| 	if ( ! empty( $webp_result ) && ! empty( $ewww_webp_only ) ) {
 | |
| 		$result = $webp_result;
 | |
| 		return array( true, $result, $converted, $original );
 | |
| 	}
 | |
| 	return array( false, $result, $converted, $original );
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Creates WebP images alongside JPG and PNG files.
 | |
|  *
 | |
|  * @param string $file The name of the JPG/PNG file.
 | |
|  * @param int    $orig_size The filesize of the JPG/PNG file.
 | |
|  * @param string $type The mime-type of the incoming file.
 | |
|  * @param string $tool The path to the cwebp binary, if installed.
 | |
|  * @param bool   $recreate True to keep the .webp image even if it is larger than the JPG/PNG.
 | |
|  * @return string Results of the WebP operation for display.
 | |
|  */
 | |
| function ewww_image_optimizer_webp_create( $file, $orig_size, $type, $tool, $recreate = false ) {
 | |
| 	ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
 | |
| 	global $ewww_force;
 | |
| 	$orig_size = ewww_image_optimizer_filesize( $file );
 | |
| 	$webpfile  = $file . '.webp';
 | |
| 	if ( apply_filters( 'ewww_image_optimizer_bypass_webp', false, $file ) ) {
 | |
| 		ewwwio_debug_message( "webp generation bypassed: $file" );
 | |
| 		return '';
 | |
| 	} elseif ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp' ) ) {
 | |
| 		return '';
 | |
| 	} elseif ( ! ewwwio_is_file( $file ) ) {
 | |
| 		ewwwio_debug_message( 'original file not found' );
 | |
| 		return esc_html__( 'Could not find file.', 'ewww-image-optimizer' );
 | |
| 	} elseif ( ! is_writable( $file ) ) {
 | |
| 		ewwwio_debug_message( 'original file not writable' );
 | |
| 		return esc_html__( 'File is not writable.', 'ewww-image-optimizer' );
 | |
| 	} elseif ( ewwwio_is_file( $webpfile ) && empty( $ewww_force ) && ! $recreate ) {
 | |
| 		ewwwio_debug_message( 'webp file exists, not forcing or recreating' );
 | |
| 		return esc_html__( 'WebP image already exists.', 'ewww-image-optimizer' );
 | |
| 	} elseif ( 'image/png' === $type && ewww_image_optimizer_is_animated_png( $file ) ) {
 | |
| 		ewwwio_debug_message( 'APNG found, WebP not possible' );
 | |
| 		return esc_html__( 'APNG cannot be converted to WebP.', 'ewww-image-optimizer' );
 | |
| 	}
 | |
| 	list( $width, $height ) = wp_getimagesize( $file );
 | |
| 	if ( $width > 16383 || $height > 16383 ) {
 | |
| 		return esc_html__( 'Image dimensions too large for WebP conversion.', 'ewww-image-optimizer' );
 | |
| 	}
 | |
| 	if ( empty( $tool ) || 'image/gif' === $type ) {
 | |
| 		if ( ewww_image_optimizer_get_option( 'ewww_image_optimizer_cloud_key' ) ) {
 | |
| 			ewww_image_optimizer_cloud_optimizer( $file, $type, false, $webpfile, 'image/webp' );
 | |
| 		} elseif ( ewwwio()->imagick_supports_webp() ) {
 | |
| 			ewww_image_optimizer_imagick_create_webp( $file, $type, $webpfile );
 | |
| 		} elseif ( ewwwio()->gd_supports_webp() ) {
 | |
| 			ewww_image_optimizer_gd_create_webp( $file, $type, $webpfile );
 | |
| 		} else {
 | |
| 			ewww_image_optimizer_cloud_optimizer( $file, $type, false, $webpfile, 'image/webp' );
 | |
| 		}
 | |
| 	} else {
 | |
| 		$nice = '';
 | |
| 		if ( PHP_OS !== 'WINNT' && ! ewwwio()->cloud_mode && ewwwio()->local->exec_check() ) {
 | |
| 			// Check to see if 'nice' exists.
 | |
| 			$nice = ewwwio()->local->find_nix_binary( 'nice' );
 | |
| 		}
 | |
| 		// Check to see if we are supposed to strip metadata.
 | |
| 		$copy_opt = ewww_image_optimizer_get_option( 'ewww_image_optimizer_metadata_remove' ) ? 'icc' : 'all';
 | |
| 		$quality  = (int) apply_filters( 'webp_quality', 75, 'image/webp' );
 | |
| 		if ( $quality < 50 || $quality > 100 ) {
 | |
| 			$quality = 75;
 | |
| 		}
 | |
| 		$sharp_yuv = defined( 'EIO_WEBP_SHARP_YUV' ) && EIO_WEBP_SHARP_YUV ? '-sharp_yuv' : '';
 | |
| 		if ( empty( $sharp_yuv ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_sharpen' ) ) {
 | |
| 			$sharp_yuv = '-sharp_yuv';
 | |
| 		}
 | |
| 		$lossless = '-lossless';
 | |
| 		if ( defined( 'EWWW_IMAGE_OPTIMIZER_LOSSY_PNG2WEBP' ) && EWWW_IMAGE_OPTIMIZER_LOSSY_PNG2WEBP ) {
 | |
| 			$lossless = "-q $quality $sharp_yuv";
 | |
| 		}
 | |
| 		switch ( $type ) {
 | |
| 			case 'image/jpeg':
 | |
| 				ewwwio_debug_message( "$nice " . $tool . " -q $quality $sharp_yuv -metadata $copy_opt -quiet " . ewww_image_optimizer_escapeshellarg( $file ) . ' -o ' . ewww_image_optimizer_escapeshellarg( $webpfile ) . ' 2>&1' );
 | |
| 				exec( "$nice " . $tool . " -q $quality $sharp_yuv -metadata $copy_opt -quiet " . ewww_image_optimizer_escapeshellarg( $file ) . ' -o ' . ewww_image_optimizer_escapeshellarg( $webpfile ) . ' 2>&1', $cli_output );
 | |
| 				if ( ! ewwwio_is_file( $webpfile ) && ewwwio()->imagick_supports_webp() && ewww_image_optimizer_is_cmyk( $file ) ) {
 | |
| 					ewwwio_debug_message( 'cmyk image skipped, trying imagick' );
 | |
| 					ewww_image_optimizer_imagick_create_webp( $file, $type, $webpfile );
 | |
| 				} elseif ( ewwwio_is_file( $webpfile ) && 'image/webp' !== ewww_image_optimizer_mimetype( $webpfile, 'i' ) ) {
 | |
| 					ewwwio_debug_message( 'non-webp file produced' );
 | |
| 				}
 | |
| 				break;
 | |
| 			case 'image/png':
 | |
| 				ewwwio_debug_message( "$nice " . $tool . " $lossless -metadata $copy_opt -quiet " . ewww_image_optimizer_escapeshellarg( $file ) . ' -o ' . ewww_image_optimizer_escapeshellarg( $webpfile ) . ' 2>&1' );
 | |
| 				exec( "$nice " . $tool . " $lossless -metadata $copy_opt -quiet " . ewww_image_optimizer_escapeshellarg( $file ) . ' -o ' . ewww_image_optimizer_escapeshellarg( $webpfile ) . ' 2>&1', $cli_output );
 | |
| 				break;
 | |
| 		}
 | |
| 	}
 | |
| 	$webp_size = ewww_image_optimizer_filesize( $webpfile );
 | |
| 	ewwwio_debug_message( "webp is $webp_size vs. $type is $orig_size" );
 | |
| 	if ( ewwwio_is_file( $webpfile ) && $orig_size < $webp_size && ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) ) {
 | |
| 		ewwwio_debug_message( 'webp file was too big, deleting' );
 | |
| 		ewwwio_delete_file( $webpfile );
 | |
| 		return esc_html__( 'WebP image was larger than original.', 'ewww-image-optimizer' );
 | |
| 	} elseif ( ewwwio_is_file( $webpfile ) && 'image/webp' === ewww_image_optimizer_mimetype( $webpfile, 'i' ) ) {
 | |
| 		// Set correct file permissions.
 | |
| 		$stat  = stat( dirname( $webpfile ) );
 | |
| 		$perms = $stat['mode'] & 0000666; // Same permissions as parent folder, strip off the executable bits.
 | |
| 		ewwwio_chmod( $webpfile, $perms );
 | |
| 		if ( $orig_size < $webp_size && ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_force' ) ) {
 | |
| 			return esc_html__( 'WebP image larger than original, saved anyway with Force WebP option.', 'ewww-image-optimizer' );
 | |
| 		}
 | |
| 		return 'WebP: ' . ewww_image_optimizer_image_results( $orig_size, $webp_size );
 | |
| 	} elseif ( ewwwio_is_file( $webpfile ) ) {
 | |
| 		ewwwio_debug_message( 'webp file mimetype did not validate, deleting' );
 | |
| 		ewwwio_delete_file( $webpfile );
 | |
| 		return esc_html__( 'WebP conversion error.', 'ewww-image-optimizer' );
 | |
| 	}
 | |
| 	return esc_html__( 'Image could not be converted to WebP.', 'ewww-image-optimizer' );
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Redirects back to previous page after PNGOUT installation.
 | |
|  */
 | |
| function ewww_image_optimizer_install_pngout_wrapper() {
 | |
| 	ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
 | |
| 	if ( ! current_user_can( apply_filters( 'ewww_image_optimizer_admin_permissions', '' ) ) ) {
 | |
| 		wp_die( esc_html__( 'You do not have permission to install image optimizer utilities.', 'ewww-image-optimizer' ) );
 | |
| 	}
 | |
| 	$sendback = ewww_image_optimizer_install_pngout();
 | |
| 	wp_safe_redirect( $sendback );
 | |
| 	ewwwio_memory( __FUNCTION__ );
 | |
| 	exit( 0 );
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Installs pngout from the official site.
 | |
|  *
 | |
|  * @return string The url from whence we came (settings page), with success or error parameters added.
 | |
|  */
 | |
| function ewww_image_optimizer_install_pngout() {
 | |
| 	if ( ! extension_loaded( 'zlib' ) || ! class_exists( 'PharData' ) ) {
 | |
| 		$pngout_error = __( 'zlib or phar extension missing from PHP', 'ewww-image-optimizer' );
 | |
| 	}
 | |
| 	if ( PHP_OS === 'Linux' ) {
 | |
| 		$os_string = 'linux';
 | |
| 	}
 | |
| 	if ( PHP_OS === 'FreeBSD' ) {
 | |
| 		$os_string = 'bsd';
 | |
| 	}
 | |
| 	$latest    = '20200115';
 | |
| 	$tool_path = trailingslashit( EWWW_IMAGE_OPTIMIZER_TOOL_PATH );
 | |
| 	if ( empty( $pngout_error ) ) {
 | |
| 		if ( PHP_OS === 'Linux' || PHP_OS === 'FreeBSD' ) {
 | |
| 			$download_result = download_url( 'http://www.jonof.id.au/files/kenutils/pngout-' . $latest . '-' . $os_string . '-static.tar.gz' );
 | |
| 			if ( is_wp_error( $download_result ) ) {
 | |
| 				$pngout_error = $download_result->get_error_message();
 | |
| 			} else {
 | |
| 				if ( ! ewwwio_check_memory_available( filesize( $download_result ) + 1000 ) ) {
 | |
| 					$pngout_error = __( 'insufficient memory available for installation', 'ewww-image-optimizer' );
 | |
| 				} else {
 | |
| 					$arch_type = 'i686';
 | |
| 					if ( ewww_image_optimizer_function_exists( 'php_uname' ) ) {
 | |
| 						$arch_type = php_uname( 'm' );
 | |
| 						if ( 'x86_64' === $arch_type ) {
 | |
| 							$arch_type = 'amd64';
 | |
| 						}
 | |
| 					}
 | |
| 
 | |
| 					$tmpname  = current( explode( '.', $download_result ) );
 | |
| 					$tmpname .= '-' . uniqid() . '.tar.gz';
 | |
| 					rename( $download_result, $tmpname );
 | |
| 					$download_result = $tmpname;
 | |
| 
 | |
| 					$pngout_gzipped  = new PharData( $download_result );
 | |
| 					$pngout_tarball  = $pngout_gzipped->decompress();
 | |
| 					$download_result = $pngout_tarball->getPath();
 | |
| 					$pngout_tarball->extractTo(
 | |
| 						EWWW_IMAGE_OPTIMIZER_BINARY_PATH,
 | |
| 						'pngout-' . $latest . '-' . $os_string . '-static/' . $arch_type . '/pngout-static',
 | |
| 						true
 | |
| 					);
 | |
| 
 | |
| 					if ( ewwwio_is_file( EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngout-' . $latest . '-' . $os_string . '-static/' . $arch_type . '/pngout-static' ) ) {
 | |
| 						if ( ! rename( EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngout-' . $latest . '-' . $os_string . '-static/' . $arch_type . '/pngout-static', $tool_path . 'pngout-static' ) ) {
 | |
| 							if ( empty( $pngout_error ) ) {
 | |
| 								$pngout_error = __( 'could not move pngout', 'ewww-image-optimizer' );
 | |
| 							}
 | |
| 						}
 | |
| 						if ( ! chmod( $tool_path . 'pngout-static', 0755 ) ) {
 | |
| 							if ( empty( $pngout_error ) ) {
 | |
| 								$pngout_error = __( 'could not set permissions', 'ewww-image-optimizer' );
 | |
| 							}
 | |
| 						}
 | |
| 						$pngout_version = ewwwio()->local->test_binary( ewww_image_optimizer_escapeshellarg( $tool_path ) . 'pngout-static', 'pngout' );
 | |
| 					} else {
 | |
| 						$pngout_error = __( 'extraction of files failed', 'ewww-image-optimizer' );
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 		} elseif ( PHP_OS === 'Darwin' ) {
 | |
| 			$latest          = '20200115';
 | |
| 			$os_ext          = 'tar.gz';
 | |
| 			$os_ext          = 'zip';
 | |
| 			$download_result = download_url( 'http://www.jonof.id.au/files/kenutils/pngout-' . $latest . '-macos.' . $os_ext );
 | |
| 			if ( is_wp_error( $download_result ) ) {
 | |
| 				$pngout_error = $download_result->get_error_message();
 | |
| 			} else {
 | |
| 				if ( ! ewwwio_check_memory_available( filesize( $download_result ) + 1000 ) ) {
 | |
| 					$pngout_error = __( 'insufficient memory available for installation', 'ewww-image-optimizer' );
 | |
| 				} else {
 | |
| 					$tmpname  = current( explode( '.', $download_result ) );
 | |
| 					$tmpname .= '-' . uniqid() . '.' . $os_ext;
 | |
| 					rename( $download_result, $tmpname );
 | |
| 					$download_result = $tmpname;
 | |
| 
 | |
| 					if ( 'zip' === $os_ext ) {
 | |
| 						WP_Filesystem();
 | |
| 						$unzipped = unzip_file(
 | |
| 							$download_result,
 | |
| 							EWWW_IMAGE_OPTIMIZER_BINARY_PATH
 | |
| 						);
 | |
| 					} else {
 | |
| 						$pngout_gzipped  = new PharData( $download_result );
 | |
| 						$pngout_tarball  = $pngout_gzipped->decompress();
 | |
| 						$download_result = $pngout_tarball->getPath();
 | |
| 						$pngout_tarball->extractTo(
 | |
| 							EWWW_IMAGE_OPTIMIZER_BINARY_PATH,
 | |
| 							'pngout-' . $latest . '-darwin/pngout',
 | |
| 							true
 | |
| 						);
 | |
| 					}
 | |
| 					if ( ewwwio_is_file( EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngout-' . $latest . '-macos/pngout' ) ) {
 | |
| 						if ( ! rename( EWWW_IMAGE_OPTIMIZER_BINARY_PATH . 'pngout-' . $latest . '-macos/pngout', $tool_path . 'pngout-static' ) ) {
 | |
| 							if ( empty( $pngout_error ) ) {
 | |
| 								$pngout_error = __( 'could not move pngout', 'ewww-image-optimizer' );
 | |
| 							}
 | |
| 						}
 | |
| 						if ( ! chmod( $tool_path . 'pngout-static', 0755 ) ) {
 | |
| 							if ( empty( $pngout_error ) ) {
 | |
| 								$pngout_error = __( 'could not set permissions', 'ewww-image-optimizer' );
 | |
| 							}
 | |
| 						}
 | |
| 						$pngout_version = ewwwio()->local->test_binary( ewww_image_optimizer_escapeshellarg( $tool_path ) . 'pngout-static', 'pngout' );
 | |
| 					} elseif ( ! empty( $unzipped ) && is_wp_error( $unzipped ) ) {
 | |
| 						$pngout_error = $unzipped->get_error_message();
 | |
| 					} else {
 | |
| 						$pngout_error = __( 'extraction of files failed', 'ewww-image-optimizer' );
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	} // End if().
 | |
| 	if ( PHP_OS === 'WINNT' ) {
 | |
| 		$download_result = download_url( 'http://advsys.net/ken/util/pngout.exe' );
 | |
| 		if ( is_wp_error( $download_result ) ) {
 | |
| 			$pngout_error = $download_result->get_error_message();
 | |
| 		} else {
 | |
| 			if ( ! rename( $download_result, $tool_path . 'pngout.exe' ) ) {
 | |
| 				if ( empty( $pngout_error ) ) {
 | |
| 					$pngout_error = __( 'could not move pngout', 'ewww-image-optimizer' );
 | |
| 				}
 | |
| 			}
 | |
| 			$pngout_version = ewwwio()->local->test_binary( '"' . $tool_path . 'pngout.exe"', 'pngout' );
 | |
| 		}
 | |
| 	}
 | |
| 	if ( is_string( $download_result ) && is_writable( $download_result ) ) {
 | |
| 		unlink( $download_result );
 | |
| 	}
 | |
| 	if ( ! empty( $pngout_version ) ) {
 | |
| 		$sendback = add_query_arg( 'ewww_pngout', 'success', remove_query_arg( array( 'ewww_pngout', 'ewww_error' ), wp_get_referer() ) );
 | |
| 	}
 | |
| 	if ( ! isset( $sendback ) ) {
 | |
| 		$sendback = add_query_arg(
 | |
| 			array(
 | |
| 				'ewww_pngout' => 'failed',
 | |
| 				'ewww_error'  => urlencode( $pngout_error ),
 | |
| 			),
 | |
| 			remove_query_arg( array( 'ewww_pngout', 'ewww_error' ), wp_get_referer() )
 | |
| 		);
 | |
| 	}
 | |
| 	return $sendback;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Redirects back to previous page after SVGCLEANER installation.
 | |
|  */
 | |
| function ewww_image_optimizer_install_svgcleaner_wrapper() {
 | |
| 	ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
 | |
| 	if ( ! current_user_can( apply_filters( 'ewww_image_optimizer_admin_permissions', '' ) ) ) {
 | |
| 		wp_die( esc_html__( 'You do not have permission to install image optimizer utilities.', 'ewww-image-optimizer' ) );
 | |
| 	}
 | |
| 	$sendback = ewww_image_optimizer_install_svgcleaner();
 | |
| 	wp_safe_redirect( $sendback );
 | |
| 	ewwwio_memory( __FUNCTION__ );
 | |
| 	exit( 0 );
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Installs svgcleaner from the official site.
 | |
|  *
 | |
|  * @return string The url from whence we came (settings page), with success or error parameters added.
 | |
|  */
 | |
| function ewww_image_optimizer_install_svgcleaner() {
 | |
| 	if ( ! extension_loaded( 'zlib' ) || ! class_exists( 'PharData' ) ) {
 | |
| 		$download_error = __( 'zlib or phar extension missing from PHP', 'ewww-image-optimizer' );
 | |
| 	}
 | |
| 	$os_chmod  = true;
 | |
| 	$os_binary = 'svgcleaner';
 | |
| 	$os_ext    = 'tar.gz';
 | |
| 	if ( PHP_OS === 'Linux' ) {
 | |
| 		$arch_type = 'x86_64';
 | |
| 		if ( ewww_image_optimizer_function_exists( 'php_uname' ) ) {
 | |
| 			$arch_type = php_uname( 'm' );
 | |
| 		}
 | |
| 		$os_string = 'linux_' . $arch_type;
 | |
| 	} elseif ( PHP_OS === 'Darwin' ) {
 | |
| 		$os_string = 'macos';
 | |
| 		$os_ext    = 'zip';
 | |
| 	} elseif ( PHP_OS === 'WINNT' ) {
 | |
| 		$os_chmod  = false;
 | |
| 		$os_string = 'win32';
 | |
| 		$os_binary = 'svgcleaner.exe';
 | |
| 		$os_ext    = 'zip';
 | |
| 	}
 | |
| 	$latest    = '0.9.5';
 | |
| 	$tool_path = trailingslashit( EWWW_IMAGE_OPTIMIZER_TOOL_PATH );
 | |
| 	if ( empty( $download_error ) ) {
 | |
| 		$download_result = download_url( 'https://github.com/RazrFalcon/svgcleaner/releases/download/v' . $latest . '/svgcleaner_' . $os_string . '_' . $latest . '.' . $os_ext );
 | |
| 		if ( is_wp_error( $download_result ) ) {
 | |
| 			$download_error = $download_result->get_error_message();
 | |
| 		} else {
 | |
| 			if ( ! ewwwio_check_memory_available( filesize( $download_result ) + 1000 ) ) {
 | |
| 				$download_error = __( 'insufficient memory available for installation', 'ewww-image-optimizer' );
 | |
| 			} else {
 | |
| 				$tmpname  = current( explode( '.', $download_result ) );
 | |
| 				$tmpname .= '-' . uniqid() . '.' . $os_ext;
 | |
| 				rename( $download_result, $tmpname );
 | |
| 				$download_result = $tmpname;
 | |
| 
 | |
| 				if ( 'zip' === $os_ext ) {
 | |
| 					WP_Filesystem();
 | |
| 					$unzipped = unzip_file(
 | |
| 						$download_result,
 | |
| 						EWWW_IMAGE_OPTIMIZER_BINARY_PATH
 | |
| 					);
 | |
| 					if ( is_wp_error( $unzipped ) ) {
 | |
| 						$download_error = $unzipped->get_error_message();
 | |
| 					}
 | |
| 				} else {
 | |
| 					$pkg_gzipped     = new PharData( $download_result );
 | |
| 					$pkg_tarball     = $pkg_gzipped->decompress();
 | |
| 					$download_result = $pkg_tarball->getPath();
 | |
| 					$pkg_tarball->extractTo(
 | |
| 						EWWW_IMAGE_OPTIMIZER_BINARY_PATH,
 | |
| 						'svgcleaner',
 | |
| 						true
 | |
| 					);
 | |
| 				}
 | |
| 				if ( ewwwio_is_file( EWWW_IMAGE_OPTIMIZER_BINARY_PATH . $os_binary ) ) {
 | |
| 					if ( ! rename( EWWW_IMAGE_OPTIMIZER_BINARY_PATH . $os_binary, $tool_path . $os_binary ) ) {
 | |
| 						if ( empty( $download_error ) ) {
 | |
| 							$download_error = __( 'could not move svgcleaner', 'ewww-image-optimizer' );
 | |
| 						}
 | |
| 					}
 | |
| 					if ( $os_chmod && ! chmod( $tool_path . $os_binary, 0755 ) ) {
 | |
| 						if ( empty( $download_error ) ) {
 | |
| 							$download_error = __( 'could not set permissions', 'ewww-image-optimizer' );
 | |
| 						}
 | |
| 					}
 | |
| 					if ( PHP_OS === 'WINNT' ) {
 | |
| 						$pkg_version = ewwwio()->local->test_binary( '"' . $tool_path . $os_binary . '"', 'svgcleaner' );
 | |
| 					} else {
 | |
| 						$pkg_version = ewwwio()->local->test_binary( ewww_image_optimizer_escapeshellarg( $tool_path ) . $os_binary, 'svgcleaner' );
 | |
| 					}
 | |
| 				} else {
 | |
| 					$download_error = __( 'extraction of files failed', 'ewww-image-optimizer' );
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	if ( is_string( $download_result ) && is_writable( $download_result ) ) {
 | |
| 		unlink( $download_result );
 | |
| 	}
 | |
| 	if ( ! empty( $pkg_version ) ) {
 | |
| 		ewww_image_optimizer_set_option( 'ewww_image_optimizer_disable_svgcleaner', false );
 | |
| 		if ( ! ewww_image_optimizer_get_option( 'ewww_image_optimizer_svg_level' ) ) {
 | |
| 			ewww_image_optimizer_set_option( 'ewww_image_optimizer_svg_level', 10 );
 | |
| 		}
 | |
| 		$sendback = add_query_arg( 'ewww_svgcleaner', 'success', remove_query_arg( array( 'ewww_svgcleaner', 'ewww_error' ), wp_get_referer() ) );
 | |
| 	}
 | |
| 	if ( ! isset( $sendback ) ) {
 | |
| 		$sendback = add_query_arg(
 | |
| 			array(
 | |
| 				'ewww_svgcleaner' => 'failed',
 | |
| 				'ewww_error'      => urlencode( $download_error ),
 | |
| 			),
 | |
| 			remove_query_arg( array( 'ewww_svgcleaner', 'ewww_error' ), wp_get_referer() )
 | |
| 		);
 | |
| 	}
 | |
| 	return $sendback;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Removes any binaries that have been installed in the wp-content/ewww/ folder.
 | |
|  */
 | |
| function ewww_image_optimizer_remove_binaries() {
 | |
| 	if ( ! class_exists( 'RecursiveIteratorIterator' ) ) {
 | |
| 		return;
 | |
| 	}
 | |
| 	if ( ! is_dir( EWWW_IMAGE_OPTIMIZER_TOOL_PATH ) ) {
 | |
| 		return;
 | |
| 	}
 | |
| 	$iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( EWWW_IMAGE_OPTIMIZER_TOOL_PATH ), RecursiveIteratorIterator::CHILD_FIRST, RecursiveIteratorIterator::CATCH_GET_CHILD );
 | |
| 	foreach ( $iterator as $file ) {
 | |
| 		if ( $file->isFile() ) {
 | |
| 			$path = $file->getPathname();
 | |
| 			if ( is_writable( $path ) ) {
 | |
| 				unlink( $path );
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	if ( ! class_exists( 'FilesystemIterator' ) ) {
 | |
| 		return;
 | |
| 	}
 | |
| 	clearstatcache();
 | |
| 	$iterator = new FilesystemIterator( EWWW_IMAGE_OPTIMIZER_TOOL_PATH );
 | |
| 	if ( ! $iterator->valid() ) {
 | |
| 		rmdir( EWWW_IMAGE_OPTIMIZER_TOOL_PATH );
 | |
| 	}
 | |
| }
 |