/system/expressionengine/third_party/ce_img/libraries/Ce_image.php
PHP | 5901 lines | 4299 code | 580 blank | 1022 comment | 856 complexity | 00e446de9ac0bcf9f8e5b5f706fc82f8 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- <?php
- error_reporting(E_ALL);
- ini_set('display_errors', '1');
- /**
- * CE Image: Powerful image manipulation made easy.
- * Last Updated: 19 June 2012
- *
- * License:
- * CE Image is licensed under the Commercial License Agreement found at http://www.causingeffect.com/software/expressionengine/ce-image/license-agreement
- * Here are a couple of specific points from the license to note again:
- * - One license grants the right to perform one installation of CE Image. Each additional installation of CE Image requires an additional purchased license.
- * - You may not reproduce, distribute, or transfer CE Image, or portions thereof, to any third party.
- * - You may not sell, rent, lease, assign, or sublet CE Image or portions thereof.
- * - You may not grant rights to any other person.
- * - You may not use CE Image in violation of any United States or international law or regulation.
- * - The only exceptions to the above four (4) points are any methods clearly designated as having an MIT-style license. Those portions of code specifically designated as having an MIT-style license, and only those portions, will remain bound to the terms of that license.
- * If you have any questions about the terms of the license, or would like to report abuse of its terms, please contact software@causingeffect.com.
- *
- * @package CE Image
- * @author Causing Effect, Aaron Waldon
- * @link http://www.causingeffect.com
- * @copyright 2012
- * @version 1.6.5
- * @license http://www.causingeffect.com/software/expressionengine/ce-image/license-agreement Causing Effect Commercial License Agreement
- */
- class Ce_image
- {
- private $valid_filters = array(
- //native IMG_FILTER_ filters
- 'brightness' => 'imagefilter',
- 'colorize' => 'imagefilter',
- 'contrast' => 'imagefilter',
- 'edgedetect' => 'imagefilter',
- 'emboss' => 'imagefilter',
- 'grayscale' => 'imagefilter',
- 'mean_removal' => 'imagefilter',
- 'negate' => 'imagefilter',
- 'pixelate' => 'imagefilter',
- 'smooth' => 'imagefilter',
- //custom filters
- '_pixelate' => array( 'self', 'pixelate' ),
- 'gaussian_blur' => array( 'self', 'gaussian_blur' ),
- 'selective_blur' => array( 'self', 'selective_blur' ),
- 'auto_sharpen' => array( 'self', 'auto_sharpen' ),
- 'cemboss' => array( 'self', 'emboss_color' ),
- 'dot' => array( 'self', 'dot' ),
- 'noise' => array( 'self', 'noise' ),
- 'opacity' => array( 'self', 'opacity' ),
- 'replace_colors' => array( 'self', 'replace_colors' ),
- 'scatter' => array( 'self', 'scatter' ),
- 'sepia' => array( 'self', 'sepia' ),
- 'sharpen' => array( 'self', 'unsharp_mask' ),
- 'sobel_edgify' => array( 'self', 'prep_edgify' ) //calls class method before calling filter
- );
- private $factory_defaults = array(
- 'allow_overwrite_original' => false,
- 'allow_scale_larger' => false,
- 'auto_cache' => false,
- 'base' => '',
- 'bg_color' => false,
- 'bg_color_default' => 'ffffff',
- 'border' => false,
- 'cache_dir' => '/images/made/',
- 'crop' => false,
- 'current_domain' => '',
- 'dir_permissions' => 0775,
- 'disable_xss_check' => false,
- 'fallback_src' => '',
- 'filename' => '',
- 'filename_prefix' => '',
- 'filename_suffix' => '',
- 'filters' => array(),
- 'flip' => false,
- 'force_remote' => false,
- 'hash_filename' => false,
- 'height' => 0,
- 'hide_relative_path' => false,
- 'image_permissions' => 0644,
- 'made_regex' => '',
- 'max_height' => 0,
- 'max_width' => 0,
- 'memory_limit' => 64,
- 'min_height' => 0,
- 'min_width' => 0,
- 'overwrite_cache' => false,
- 'quality' => 100,
- 'reflection' => false,
- 'remote_cache_time' => 1440,
- 'remote_dir' => '/images/remote/',
- 'rotate' => 0,
- 'rounded_corners' => false,
- 'save_type' => false,
- 'src_regex' => '',
- 'text' => false,
- 'unique' => 'filename',
- 'watermark' => false,
- 'width' => 0
- );
- //---------- don't change anything below here ----------
- private $is_open = false; //whether or not an image is actually open
- private $is_open_ready = false; //whether or not the image is ready to be opened
- private $is_data_ready = false; //whether or not the image data is ready
- private $image_data = array( 'width' => '', 'height' => '', 'type' => '', 'ext' => '' );
- private $image_data_orig = array( 'width' => '', 'height' => '', 'type' => '', 'ext' => '', 'src' => '' );
- private $image_types = array( 'png', 'gif', 'jpg', 'jpeg' );
- private $is_remote = false;
- private $remote_src = '';
- private $x_offset = 0;
- private $y_offset = 0;
- private $src_x_offset = 0;
- private $src_y_offset = 0;
- private $width_desired = 0;
- private $height_desired = 0;
- private $x_options = array('left', 'right', 'center');
- private $y_options = array('top', 'bottom', 'center');
- private $same_as_source = false;
- private $debug_messages = array();
- private $is_transparent = false;
- private $defaults = array();
- //watermark
- private $filetime_wm = 0;
- private $wm_image_data = array( 'width' => '', 'height' => '', 'type' => '', 'src' => '' );
- private $wm_array;
- //rounded corners
- private $corner_options = array('all', 'tl', 'tr', 'bl', 'br');
- private $corners = false;
- private $corners_array;
- //reflection
- private $reflection = false;
- private $reflection_array = array();
- //flag if actual image dimensions needs to be checked
- private $check_size = false;
- //flip
- private $flip_options = array('h', 'v');
- //disable XSS check
- private $disable_xss_check = false;
- //For dev testing with versions of PHP before 5.2.0, windows has to swap / with \
- private $windows_dev = false;
- private $final_action = 'none';
- /**
- * Initiates the class and optionally accepts an array of default settings. Also determines whether or not CodeIgniter is installed and available to use.
- *
- * @param array $default_settings The default settings.
- */
- function __construct( $default_settings = array() )
- {
- //set the factory defaults
- $this->defaults = $this->factory_defaults;
- //merge the params with the defaults
- $this->set_default_settings( $default_settings );
- $this->EE =& get_instance();
- }
- // ---------------------------------------------------------------------------- SETTINGS ----------------------------------------------------------------------------
- /**
- * Accepts settings to integrate with the default settings.
- *
- * @param array $default_settings The default settings that will override the previously set default settings.
- * @return void
- */
- public function set_default_settings( $default_settings = array() )
- {
- $defaults = $this->defaults;
- //override the defaults
- if ( count( $default_settings ) > 0 )
- {
- foreach ( $default_settings as $key => $value )
- {
- if ( ! in_array( $key, $defaults ) )
- {
- unset( $default_settings[$key] );
- }
- }
- $defaults = array_merge( $defaults, $default_settings );
- }
- //reset the defaults array
- $this->defaults = $defaults;
- unset( $defaults );
- //now that our default array is created, apply them as class properties
- $this->reset_to_default_settings();
- }
- /**
- * Accepts settings to temporarily override the default settings. The settings will not be persistent when subsequent images are opened/made.
- *
- * @param array $temp_settings The temporary settings that will override any previously set default settings.
- * @return void
- */
- private function set_temp_settings( $temp_settings = array() )
- {
- //reset class properties
- $this->check_size = false;
- $this->disable_xss_check = false;
- $this->filetime_wm = 0;
- $this->height_desired = 0;
- $this->is_remote = false;
- $this->remote_src = '';
- $this->src_x_offset = 0;
- $this->src_y_offset = 0;
- $this->width_desired = 0;
- $this->wm_array = array();
- $this->x_offset = 0;
- $this->y_offset = 0;
- $this->same_as_source = false;
- //reset the defaults
- $this->reset_to_default_settings();
- //set the temp settings
- if ( count( $temp_settings ) > 0 )
- {
- foreach ($temp_settings as $key => $val)
- {
- if ( in_array( $key, $this->factory_defaults ) )
- {
- $this->$key = $val;
- }
- }
- }
- }
- /**
- * Resets the class properties to match the default array
- *
- * @return void
- */
- private function reset_to_default_settings()
- {
- $defaults = $this->defaults;
- //set the class properties to the defaults array
- if ( count( $defaults ) > 0 )
- {
- foreach ($defaults as $key => $val)
- {
- $this->$key = $val;
- }
- }
- }
- /**
- * Resets the settings back to the 'factory defaults'
- *
- * @return void
- */
- public function reset_to_factory_settings()
- {
- $this->defaults = $this->factory_defaults;
- $this->reset_to_default_settings();
- }
- /**
- * Retrieves all of the current settings.
- *
- * @return array
- */
- private function get_current_settings()
- {
- $settings = array();
- foreach ( $this->factory_defaults as $name => $setting )
- {
- $settings[$name] = $this->$name;
- }
- return $settings;
- }
- /**
- * Removes double slashes, except when they are preceded by ':', so that 'http://', etc are preserved.
- *
- * @param string $str The string from which to remove the double slashes.
- * @return string The string with double slashes removed.
- */
- private function remove_duplicate_slashes( $str )
- {
- return preg_replace( '#(?<!:)//+#', '/', $str );
- }
- // ---------------------------------------------------------------------------- OPEN ----------------------------------------------------------------------------
- /**
- * Opens an image. Call this function if you would like to get data from an image without manipulating it. This function is also called by the 'make' method.
- *
- * @param string|resource $src The image source. Can be a relative path to document root, a full server (absolute) path, a URL (remote or local), an HTML snippet, or a GD2 image resource.
- * @param array $temp_settings The settings that will temporary override the previously set default settings, for this image only.
- * @return bool Will return true on success and false on failure.
- */
- public function open( $src = '', $temp_settings = array() )
- {
- $is_string = ! is_resource( $src );
- $this->set_temp_settings( $temp_settings );
- $this->is_data_ready = false;
- $this->is_open_ready = false;
- $this->is_open = false;
- //base path
- $base = ( $this->base != '') ? $this->base : $_SERVER['DOCUMENT_ROOT'];
- $base = str_replace('\\', '/', $this->EE->security->xss_clean( $base ) );
- $this->base = $this->remove_duplicate_slashes( $base . '/' );
- $this->debug_messages[] = "Base path: '$this->base'";
- if ( $is_string ) //string src
- {
- $this->src = $src;
- //check to make sure the source is not blank
- if ( $this->src == '' && $this->fallback_src == '' )
- {
- $this->debug_messages[] = 'Source and fallback source cannot both be blank.';
- return false;
- }
- $this->src = str_replace('\\', '/', $this->src);
- //get the source from the first image tag, if one exists
- if ( preg_match('#<img.+src="(.*)".*>#Uims', $this->src, $matches) )
- {
- $this->src = $matches[1];
- }
- $this->src = $this->EE->security->xss_clean( $this->src );
- $this->fallback_src = str_replace('\\', '/', $this->fallback_src);
- $this->fallback_src = $this->EE->security->xss_clean( $this->fallback_src );
- //source and fallback source
- $this->debug_messages[] = "Source image: '$this->src', Fallback image: '$this->fallback_src'";
- if ( $this->src == '' || $this->check_src_image() == false )
- {
- //source is not readable or does not exist, write debug message and check fallback source
- $this->debug_messages[] = "Source image is not readable or does not exist: '$this->src'.";
- $this->src = $this->fallback_src;
- if ( $this->src == '' || $this->check_src_image() == false )
- {
- //fallback source is not readable, not much more to do...
- $this->debug_messages[] = "Fallback source image is not readable or does not exist: '$this->src'.";
- return false;
- }
- }
- //get the path info
- $info = pathinfo( $this->src );
- //get the relative path
- if ( $this->is_above_root ) //normal
- {
- $this->relative = ( $this->hide_relative_path ) ? '' : preg_replace( '@' . preg_quote( $this->base, '@' ) . '@', '', '/' . $info['dirname'] . '/', 1 );
- }
- else //we don't want to reveal server info below web root
- {
- $this->relative = '';
- if ( ! $this->hide_relative_path && ! empty( $info['dirname'] ) )
- {
- $this->relative = substr( md5( $info['dirname'] ), 0, 16 ) . '/';
- }
- }
- }
- else //resource
- {
- $this->src = '';
- $this->handle = $src;
- $this->is_above_root = true;
- $this->relative = '';
- }
- //auto cache directory
- if ( $this->auto_cache != '' && $this->is_above_root )
- {
- $this->auto_cache = $this->EE->security->xss_clean( $this->remove_duplicate_slashes( '/' . $this->auto_cache . '/' ) );
- $this->cache_full = $this->remove_duplicate_slashes( $this->base . $this->relative . $this->auto_cache );
- }
- else
- {
- //cache paths
- $this->cache_dir = $this->remove_duplicate_slashes( '/' . $this->cache_dir . '/' );
- $this->cache_full = $this->remove_duplicate_slashes( $this->base . $this->cache_dir . $this->relative );
- }
- if ( $this->windows_dev )
- {
- $this->cache_full = str_replace( '/', '\\', $this->cache_full);
- }
- if ( $is_string ) //string src
- {
- //get the image data
- $status = $this->get_image_data();
- if ( $status === 'try again' )
- {
- return $this->open( $this->fallback_src );
- }
- else if ($status === false)
- {
- return false;
- }
- //original extension (use this if possible to preserve casing)
- if ( isset( $info['extension'] ) )
- {
- $this->image_data_orig['ext'] = $info['extension'];
- }
- else
- {
- $this->image_data_orig['ext'] = '';
- }
- //get original filename
- if ( isset( $info['filename'] ) ) //>= PHP 5.2.0
- {
- $filename = $info['filename'];
- }
- else //< PHP 5.2.0
- {
- $filename = substr_replace( $info['basename'], '', strrpos( $info['basename'], '.' . $this->image_data_orig['ext'] ), strlen( '.' . $this->image_data_orig['ext'] ) );
- }
- //store original filename
- $this->filename_orig = $this->EE->security->sanitize_filename( $filename );
- $this->filename_final = $this->filename_orig;
- }
- else //resource
- {
- $filename = 'temp';
- $width = round( imagesx( $this->handle ) );
- $height = round( imagesy( $this->handle ) );
- $this->image_data = array( 'width' => $width, 'height' => $height, 'type' => '', 'ext' => '' );
- $this->image_data_orig = array( 'width' => $width, 'height' => $height, 'type' => '', 'ext' => '', 'src' => '' );
- $this->filename_orig = '';
- $this->filename_final = '';
- $this->is_open = true;
- }
- //---------- filename ----------
- $temp = trim( $this->filename );
- $filename = ( $temp === '' ) ? $filename : $temp;
- $this->filename = $this->EE->security->sanitize_filename( $filename );
- $this->is_open_ready = true;
- $this->is_data_ready = true;
- return true;
- }
- /**
- * Retrieves the image data for the current src image.
- *
- * @return bool Will return true on success and false on failure.
- */
- private function get_image_data()
- {
- //get the image info
- $data = @getimagesize( $this->src );
- $success = true;
- if ( ! $data )
- {
- $success = false;
- }
- else
- {
- $ext = '';
- switch ( $data[2] )
- {
- case IMAGETYPE_GIF:
- $ext = 'gif';
- break;
- case IMAGETYPE_PNG:
- $ext = 'png';
- break;
- case IMAGETYPE_JPEG:
- $ext = 'jpg';
- break;
- default:
- $success = false;
- }
- }
- if ( ! $success )
- {
- $this->debug_messages[] = 'Unknown image format.';
- //there is a small chance the image was an error page, try and use the fallback source
- if ( $this->src != $this->fallback_src && $this->fallback_src != '' ) //retry with the fallback as the source
- {
- $this->debug_messages[] = 'Reprocessing using the fallback image.';
- return 'try again'; //try again
- }
- return false;
- }
- //$this->image_data_orig['type'] = $data[2];
- $this->image_data = array( 'width' => $data[0], 'height' => $data[1], 'ext' => $ext );
- $this->image_data_orig = array( 'width' => $data[0], 'height' => $data[1], 'ext' => $ext, 'type' => $data[2], 'src' => $this->src );
- return true;
- }
- /**
- * Opens the actual image resource.
- * @param bool $original
- * @return bool Returns true on success and false on failure.
- */
- private function open_real( $original = false )
- {
- if ( ! $this->is_open_ready )
- {
- //return false;
- $this->open( $this->src );
- }
- if ( $this->is_open )
- {
- return true;
- }
- //set the memory limit
- $this->set_memory_limit();
- if ( $this->src != '' ) //do not try to open if the src is '', because it's a resource
- {
- $which = ( $original ) ? 'image_data_orig' : 'image_data';
- if ( isset( $this->{$which}['type'] ) && $this->{$which}['type'] != '' )
- {
- switch ( $this->{$which}['type'] )
- {
- case IMAGETYPE_GIF:
- $type = 'gif';
- break;
- case IMAGETYPE_PNG:
- $type = 'png';
- break;
- case IMAGETYPE_JPEG:
- $type = 'jpg';
- break;
- default:
- $type = '';
- }
- }
- else if (in_array(strtolower($this->{$which}['ext']), $this->image_types))
- {
- $type = strtolower($this->{$which}['ext']);
- }
- //open the file and create main image handle
- switch ( $type )
- {
- case 'gif':
- $success = @imagecreatefromgif( $this->src );
- break;
- case 'png':
- $success = @imagecreatefrompng( $this->src );
- break;
- case 'jpg':
- case 'jpeg':
- $success = @imagecreatefromjpeg( $this->src );
- break;
- default:
- $this->debug_messages[] = 'Unknown image format for image creation.';
- $success = false;
- }
- if ( $success === false )
- {
- $this->debug_messages[] = "A problem occurred trying to open the image '$this->src'.";
- return false;
- }
- else
- {
- $this->handle = $success;
- }
- }
- $this->is_open = true;
- $this->debug_messages[] = "Image opened '$this->src'.";
- return true;
- }
- /**
- * Attempts to determine the server path from the image src parameter. Will also download a remote image if applicable and return its server path.
- *
- * @return bool Returns true if the image is found successfully and false otherwise.
- */
- private function check_src_image()
- {
- //perform any advanced preg_replaces if they exist
- $replacements = $this->src_regex;
- if ( $replacements != false && is_array( $replacements ) && count( $replacements ) > 0 )
- {
- $find = array();
- $replace = array();
- foreach( $replacements as $f => $r )
- {
- $find[] = '@' . $f . '@';
- $replace[] = $r;
- }
- $this->src = preg_replace( $find, $replace, $this->src );
- //show the new source
- $this->debug_messages[] = "Regexed source: '$this->src'";
- }
- //adjust for protocol-relative URLs
- if ( substr( $this->src, 0, 3 ) == '://' )
- {
- if ( isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' )
- {
- $this->src = 'https' . $this->src;
- }
- else
- {
- $this->src = 'http' . $this->src;
- }
- }
- //check if a URL
- if ( substr( $this->src, 0, 4 ) == 'http' )
- {
- $info = parse_url( $this->src );
- if ( $info === false )
- {
- $this->debug_messages[] = "The url '{$this->src}' could not be parsed. Is your URL malformed?";
- return false;
- }
- $current_domain_override = $this->current_domain;
- if ( $current_domain_override == '' ) //no domain specified, try to figure it out
- {
- $current_domain_override = $this->EE->security->xss_clean( preg_replace( '@' . preg_quote( 'www.', '@' ) . '@', '', $_SERVER['SERVER_NAME'], 1 ) );
- }
- else //use the current domain value as set in plugin or config
- {
- $temp = parse_url( $current_domain_override );
- if ( $temp === false )
- {
- $this->debug_messages[] = "The url '{$current_domain_override}' could not be parsed. Is it malformed?";
- return false;
- }
- if ( ! isset( $temp['host'] ) ) //verify that the host key is set
- {
- $this->debug_messages[] = "The value specified for the 'current_domain' is invalid.";
- return false;
- }
- $current_domain_override = preg_replace( '@' . preg_quote( 'www.', '@') . '@', '', $temp['host'], 1 );
- }
- $path = isset( $info['path'] ) ? $info['path'] : '';
- if ( $this->force_remote || preg_replace( '@' . preg_quote( 'www.', '@') . '@', '', $info['host'], 1 ) != $current_domain_override ) //remote
- {
- $this->is_remote = true;
- $this->remote_src = $this->src;
- //get remote_dir param
- $this->remote_dir = $this->remove_duplicate_slashes( '/' . $this->remote_dir . '/' );
- $temp = $this->base . '/' . $this->remote_dir . $info['scheme'] . '_' . $info['host'] . $path;
- //create and sanitize the file path
- $temp = $this->EE->security->xss_clean( $this->remove_duplicate_slashes( $temp ) );
- $path_info = pathinfo( $temp );
- //make sure the query string gets worked in if applicable
- if ( isset( $info['query'] ) )
- {
- $path_info['dirname'] = $this->remove_duplicate_slashes( $path_info['dirname'] . '/' . md5( $info['query'] ) );
- }
- $remote_cache = $path_info['dirname'];
- $remote_filename = $this->EE->security->sanitize_filename( $path_info['basename'] );
- $file = $remote_cache . '/' . $remote_filename;
- $file_exists = @file_exists( $file );
- if ( $file_exists )
- {
- //determine the course of action for refreshing the remote image depending on the settings
- $file_m_time = @filemtime( $file ); //filetime of cached image
- if ( $this->remote_cache_time != -1 ) //don't worry about re-downloading the remote image if remote_cache_time is -1
- {
- //check the timestamp of the image
- $remote_timestamp = 0;
- //see if the user has curl so we can check the timestamp
- if ( $this->remote_cache_time == 0 && function_exists( 'curl_init' ) ) //check if the remote image is newer than the downloaded version if remote_cache_time is 0
- {
- $this->debug_messages[] = "Checking whether the remote image '{$this->remote_src}' is newer than the cached version via cURL.";
- $curl = curl_init( $this->remote_src );
- curl_setopt($curl, CURLOPT_NOBODY, true); //only fetch headers
- curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); //no output
- curl_setopt($curl, CURLOPT_FILETIME, true); //attempt to get date modified
- //follow location will throw an error if safe mode or an open basedir restrictions is enabled
- if ( ! ini_get('open_basedir') && ! ini_get('safe_mode') )
- {
- curl_setopt( $curl, CURLOPT_FOLLOWLOCATION, true );
- }
- if ( curl_exec($curl) !== false)
- {
- $remote_timestamp = curl_getinfo($curl, CURLINFO_FILETIME);
- }
- }
- $delete_cache = false;
- if ( $remote_timestamp != 0 && $remote_timestamp > $file_m_time ) //the remote image is newer
- {
- $this->debug_messages[] = "The remote image '{$this->remote_src}' is newer than the cached version.";
- $delete_cache = true;
- }
- else if (time() - $file_m_time > $this->remote_cache_time * 60) //the remote file has expired
- {
- $this->debug_messages[] = "The local cache of the remote image has expired.";
- $delete_cache = true;
- }
- //delete the current remote cache file
- if ( $delete_cache )
- {
- @unlink( $file );
- //recheck if the file exists
- $file_exists = @file_exists( $file );
- }
- }
- }
- //if the image is not on the server, download it
- if ( ! $file_exists )
- {
- if ( $this->windows_dev )
- {
- $remote_cache = str_replace('/', '\\', $remote_cache);
- }
- if ( $this->save_remote_image( $remote_cache, $remote_filename ) === false )
- {
- return false;
- }
- }
- //change the source from the remote image to the downloaded image
- $this->src = $this->remove_duplicate_slashes( $remote_cache . '/' . $remote_filename );
- }
- else //local
- {
- $this->src = $path;
- }
- }
- //---------- figure out source path ----------
- $this->is_above_root = true;
- $temp = $this->remove_duplicate_slashes( $this->base . $this->src );
- if ( @is_readable( $temp ) === true ) //relative path
- {
- //create full path for source
- $this->src = $this->remove_duplicate_slashes( realpath($temp) );
- $this->src = str_replace('\\', '/', $this->src);
- }
- //see if path below web root
- if ( strpos($this->src, $this->base) === false )
- {
- $this->is_above_root = false;
- }
- //make sure the image is readable and is not a directory
- if ( @is_dir( $this->src ) || @is_readable( $this->src ) !== true )
- {
- return false;
- }
- return true;
- }
- /**
- * Saves a remote image.
- *
- * @param string $remote_cache The server path to the remote images' cache folder.
- * @param string $remote_filename The URL of the remote image.
- * @return bool Returns true if the image is saved successfully and false otherwise.
- */
- private function save_remote_image( $remote_cache, $remote_filename )
- {
- $this->set_memory_limit();
- @ini_set('default_socket_timeout', 30);
- @ini_set('allow_url_fopen', true);
- @ini_set('user_agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:5.0) Gecko/20100101');
- $url = str_replace( ' ', '%20', $this->src );
- if ( function_exists( 'curl_init' ) ) //try to get the image using cURL
- {
- $curl = curl_init();
- curl_setopt($curl, CURLOPT_URL, $url ); //set the URL
- curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); //no output
- curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, false); //no timeout
- //follow location will throw an error if safe mode or an open basedir restrictions is enabled
- if ( ! ini_get('open_basedir') && ! ini_get('safe_mode') )
- {
- curl_setopt( $curl, CURLOPT_FOLLOWLOCATION, true );
- }
- $remote_image = curl_exec($curl);
- if ( empty( $remote_image ) ) //cURL failed
- {
- $this->debug_messages[] = 'Could not get remote image using cURL.';
- return false;
- }
- }
- else //try to get the image using file_get_contents
- {
- $remote_image = @file_get_contents( $url );
- if ( empty( $remote_image ) ) //file_get_contents failed and cURL is not enabled, not much more we can do...
- {
- $this->debug_messages[] = 'Could not get remote image using file_get_contents.';
- return false;
- }
- }
- if ( $this->disable_xss_check || $this->EE->security->xss_clean( $remote_image, true ) === true )
- {
- //check if the directory exists
- if ( ! @is_dir( $remote_cache ) )
- {
- //try to make the directory
- if ( ! @mkdir( $remote_cache . '/', $this->dir_permissions, true ) )
- {
- $this->debug_messages[] = "Could not create the cache directory '$remote_cache/' for remote images.";
- return false;
- }
- }
- //ensure the directory is writable
- if ( ! @is_writable( $remote_cache ) )
- {
- $this->debug_messages[] = "Cache directory for remote images '$remote_cache' is not writable.";
- return false;
- }
- if ( file_put_contents( $remote_cache . '/' . $remote_filename, $remote_image) === false )
- {
- $this->debug_messages[] = "Could not write the remote image '{$remote_cache}/{$remote_filename}'.";
- return false;
- }
- }
- else //file failed the XSS test
- {
- $this->debug_messages[] = 'Remote image failed XSS test.';
- return false;
- }
- //the image should have been saved successfully, let's attempt to update permissions
- if ( ! @chmod( $remote_cache . '/' . $remote_filename, $this->image_permissions ) )
- {
- $this->debug_messages[] = "File permissions for '{$remote_cache}/{$remote_filename}' could not be changed to '$this->image_permissions'.";
- }
- $remote_image = null;
- $this->debug_messages[] = "The remote image '{$url}' was downloaded successfully.";
- return true;
- }
- // ---------------------------------------------------------------------------- RETURN FUNCTIONS ----------------------------------------------------------------------------
- /**
- * The currently open image resource.
- *
- * @return resource|bool The resource on success and false on failure.
- */
- public function get_resource()
- {
- if ( $this->open_real() == false )
- {
- $this->debug_messages[] = 'A resource could not be returned, because an image is not open.';
- return false;
- }
- if ( isset( $this->handle ) && is_resource($this->handle) )
- {
- return $this->handle;
- }
- else
- {
- $this->debug_messages[] = 'A resource could not be returned, because a valid resource was not found.';
- return false;
- }
- }
- /**
- * Returns a clone of the currently open image resource.
- *
- * @return resource|bool The resource clone on success and false on failure.
- */
- public function clone_resource()
- {
- if ( $this->open_real() == false )
- {
- $this->debug_messages[] = 'A resource could not be cloned, because an image is not open.';
- return false;
- }
- if ( isset( $this->handle ) && is_resource( $this->handle ) )
- {
- $width = round( imagesx( $this->handle ) );
- $height = round( imagesy( $this->handle ) );
- $clone = imagecreatetruecolor( $width, $height );
- if ( @imagecopy( $clone, $this->handle, 0, 0, 0, 0, $width, $height ) )
- {
- return $clone;
- }
- else
- {
- $this->debug_messages[] = 'There was an error cloning the image.';
- return false;
- }
- }
- else
- {
- $this->debug_messages[] = 'There image could not be cloned, because a valid resource was not found.';
- return false;
- }
- }
- /**
- * Returns the type of action that was taken. Can be one of the following:
- * none - No action was taken.
- * saved - The image was successfully saved.
- * cached - A cached image was found and used.
- *
- * @return string
- */
- public function get_final_action()
- {
- return $this->final_action;
- }
- /**
- * The height of the current image.
- *
- * @return int The current image's height.
- */
- public function get_height()
- {
- return $this->image_data['height'];
- }
- /**
- * The height of the original image.
- *
- * @return int The original image's height
- */
- public function get_original_height()
- {
- return $this->image_data_orig['height'];
- }
- /**
- * The width of the current image.
- *
- * @return int The current image's width.
- */
- public function get_width()
- {
- return $this->image_data['width'];
- }
- /**
- * The width of the original image.
- *
- * @return int The original image's width.
- */
- public function get_original_width()
- {
- return $this->image_data_orig['width'];
- }
- /**
- * The extension of the current image.
- *
- * @return string The current image's extension.
- */
- public function get_extension()
- {
- return ( $this->get_server_path() != '' ) ? $this->image_data['ext'] : '';
- }
- /**
- * The extension of the original image.
- *
- * @return string The original image's extension.
- */
- public function get_original_extension()
- {
- return $this->image_data_orig['ext'];
- }
- /**
- * The relative path (from document root) of the current image.
- *
- * @return string The current image's relative path.
- */
- public function get_relative_path()
- {
- $path = preg_replace( '@' . preg_quote( $this->base, '@' ) . '@', '', '/' . $this->src, 1 );
- //perform any advanced preg_replaces if they exist
- $replacements = $this->made_regex;
- if ( $replacements != false && is_array( $replacements ) && count( $replacements ) > 0 )
- {
- $find = array();
- $replace = array();
- foreach( $replacements as $f => $r )
- {
- $find[] = '#' . $f . '#';
- $replace[] = $r;
- }
- $path = preg_replace( $find, $replace, $path );
- //show the new made path
- $this->debug_messages[] = "Regexed made: '$path'.";
- }
- return $path;
- }
- /**
- * The relative path (from document root) of the original image.
- *
- * @return string The original image's relative path.
- */
- public function get_original_relative_path()
- {
- $path = preg_replace( '@' . preg_quote( $this->base, '@' ) . '@', '', '/' . $this->image_data_orig['src'], 1 );
- return $path;
- }
- /**
- * The file type of the current image. Will return 'jpg', 'png', or 'gif'.
- *
- * @return string
- */
- public function get_type()
- {
- $type = strtolower( $this->image_data['ext'] );
- if ( $type == 'jpeg' )
- {
- $type = 'jpg';
- }
- return $type;
- }
- /**
- * The file type of the original image. Will return 'jpg', 'png', or 'gif'.
- *
- * @return string
- */
- public function get_type_orig()
- {
- switch ( $this->image_data_orig['type'] )
- {
- case 1;
- return 'gif';
- break;
- case 2:
- return 'jpg';
- break;
- case 3:
- return 'png';
- break;
- }
- return 'unknown';
- }
- /**
- * The file name of the current image, without the file extension.
- *
- * @return string The current image's file name.
- */
- public function get_filename()
- {
- return ( $this->get_server_path() != '' ) ? $this->filename_final : '';
- }
- /**
- * The file name of the original image, without the file extension.
- *
- * @return string The original image's file name.
- */
- public function get_original_filename()
- {
- return $this->filename_orig;
- }
- /**
- * The server path of the current image.
- *
- * @return string The current image's server path.
- */
- public function get_server_path()
- {
- return $this->src;
- }
- /**
- * The server path of the original image.
- *
- * @return string The original image's server path.
- */
- public function get_original_server_path()
- {
- return $this->image_data_orig['src'];
- }
- /**
- * The array of debug messages.
- *
- * @return array The debug messages.
- */
- public function get_debug_messages()
- {
- return $this->debug_messages;
- }
- /**
- * Returns the file size of the image.
- *
- * @param bool $bytes_only If the file size should be returned in bytes, or converted to a human readable format (default).
- * @return int|string|bool Returns int if $bytes_only is true, string if $bytes_only is false, and false if an error.
- */
- public function get_filesize( $bytes_only = false )
- {
- if ( $this->src != '' && ( $this->is_data_ready || $this->is_open_ready ) )
- {
- $filesize = @filesize( $this->src );
- if ( $filesize !== false)
- {
- return ( $bytes_only ) ? $filesize : Ce_image_tools::convert( $filesize );
- }
- else
- {
- $this->debug_messages[] = "The file size could not be found for '$this->src'.";
- return false;
- }
- }
- else
- {
- $this->debug_messages[] = 'The file size could not be retrieved, because an image is not open.';
- return false;
- }
- }
- /**
- * Returns the file size of the original image.
- *
- * @param bool $bytes_only If the file size should be returned in bytes, or converted to a human readable format (default).
- * @return int|string|bool Returns int if $bytes_only is true, string if $bytes_only is false, and false if an error.
- */
- public function get_original_filesize( $bytes_only = false )
- {
- if ( $this->get_original_server_path() != '' && ( $this->is_data_ready || $this->is_open_ready ) )
- {
- $filesize = @filesize( $this->image_data_orig['src'] );
- if ( $filesize !== false)
- {
- return ( $bytes_only ) ? $filesize : Ce_image_tools::convert( $filesize );
- }
- else
- {
- $this->debug_messages[] = "The original file size could not be found for '{$this->image_data_orig['src']}'.";
- return false;
- }
- }
- else
- {
- $this->debug_messages[] = 'The original file size could not be retrieved, because an image is not open.';
- return false;
- }
- }
- /**
- * Creates a tag for the current image. It will automatically add in the images width, height, and alt tag if they are not passed in as attributes.
- *
- * @param array $attributes The attributes to be used for the image.
- * @param bool $closing_slash Whether or not to include a closing slash (defaults to true).
- * @return string The HTML image tag.
- */
- public function create_tag( $attributes = array(), $closing_slash = true )
- {
- if ( $this->src == '' OR ! $this->is_data_ready )
- {
- $this->debug_messages[] = 'The image tag could not be created, because an image is not open.';
- return false;
- }
- if ( ! array_key_exists( 'src', $attributes ) )
- {
- $attributes['src'] = $this->get_relative_path();
- }
- if ( ! array_key_exists( 'width', $attributes ) )
- {
- $attributes['width'] = $this->get_width();
- }
- if ( ! array_key_exists( 'height', $attributes ) )
- {
- $attributes['height'] = $this->get_height();
- }
- if ( ! array_key_exists( 'alt', $attributes ) )
- {
- $attributes['alt'] = '';
- }
- $attr = '';
- foreach( $attributes as $attribute => $value )
- {
- $value = str_replace('"', '"', $value );
- $attr .= $attribute . '="' . $value . '" ';
- }
- $closing_slash = ($closing_slash) ? '/' : '';
- return '<img ' . $attr . $closing_slash . '>';
- }
- /**
- * Creates a tag for the original image. It will automatically add in the images width, height, and alt tag if they are not passed in as attributes.
- *
- * @param array $attributes The attributes to be used for the image.
- * @param bool $closing_slash Whether or not to include a closing slash (defaults to true).
- * @return string The HTML image tag.
- */
- public function create_original_tag( $attributes = array(), $closing_slash = true )
- {
- if ( $this->get_original_server_path() == '' OR ! $this->is_data_ready )
- {
- $this->debug_messages[] = 'The image tag could not be created, because an image is not open.';
- return false;
- }
- if ( ! array_key_exists( 'src', $attributes ) )
- {
- $attributes['src'] = $this->get_original_relative_path();
- }
- if ( ! array_key_exists( 'width', $attributes ) )
- {
- $attributes['width'] = $this->get_original_width();
- }
- if ( ! array_key_exists( 'height', $attributes ) )
- {
- $attributes['height'] = $this->get_original_height();
- }
- if ( ! array_key_exists( 'alt', $attributes ) )
- {
- $attributes['alt'] = '';
- }
- $attr = '';
- foreach( $attributes as $attribute => $value )
- {
- $value = str_replace('"', '"', $value );
- $attr .= $attribute . '="' . $value . '" ';
- }
- $closing_slash = ($closing_slash) ? '/' : '';
- return '<img ' . $attr . $closing_slash . '>';
- }
- /**
- * Creates ASCII art for an image. Each character represents one pixel from the image.
- *
- * @param bool $use_colors Whether or not to colorize the characters.
- * @param array $ascii_characters The array of characters to be used for the ASCII art.
- * @param bool $repeat Whether or not the characters should repeat in consecutive order (true) or be placed depending on the darkness of the pixel (false).
- * @param bool $space_for_trans If the $repeat parameter is set to true, you can set this parameter to determine whether or not a space should be used for transparent pixels.
- * @return string|bool The HTML for the ASCII art on success, false on failure.
- */
- public function get_ascii_art( $use_colors = true, $ascii_characters = array('#', '@', '%', '=', '+', '*', ':', '-', '.', ' '), $repeat = false, $space_for_trans = false )
- {
- //check the settings
- if ( ! is_bool( $use_colors) )
- {
- $use_colors = true;
- }
- //repeat characters?
- if ( ! is_bool( $repeat) )
- {
- $repeat = false;
- }
- //use space character for transparent pixels?
- if ( ! is_bool( $space_for_trans ) )
- {
- $space_for_trans = false;
- }
- if ( $this->open_real() == false )
- {
- $this->debug_messages[] = 'The ASCII art could not be generated, because an image is not open.';
- return false;
- }
- return $this->create_ascii_art( $this->handle, $use_colors, $ascii_characters, $repeat, $space_for_trans );
- }
- /**
- * Organizes the colors used in your image by frequency of occurrence, and groups them by a threshold.
- *
- * @param int $quantity The maximum number of colors (color groups) to return.
- * @param int $threshold Value from 0 (very low grouping) to 100 (very high grouping).
- * @return array|bool On success, returns an array of results with each result being an array with the following keys: 'color', 'color_count', 'color_percent'. On failure, returns false.
- */
- public function get_top_colors( $quantity = 5, $threshold = 33 )
- {
- if ( ! is_numeric( $quantity) )
- {
- $this->debug_messages[] = 'Invalid quantity of return colors for top colors.';
- return false;
- }
- if ( ! is_numeric( $threshold ) || $threshold < 0 || $threshold > 100 )
- {
- $this->debug_messages[] = 'Invalid threshold for top colors. Must be between 0 and 100, inclusive.';
- return false;
- }
- if ( $this->open_real() )
- {
- return $this->find_top_colors( $this->handle, $quantity, $threshold );
- }
- else
- {
- $this->debug_messages[] = 'The top colors could not be retrieved, because an image is not open.';
- return false;
- }
- }
- /**
- * Gets the average color for the image.
- *
- * @return string The hexadecimal color value of the average color of the generated image.
- */
- public function get_average_color()
- {
- if ( $this->open_real() )
- {
- return $this->find_average_color( $this->handle );
- }
- else
- {
- $this->debug_messages[] = 'The average color could not be retrieved, because no image is open.';
- return false;
- }
- }
- // ---------------------------------------------------------------------------- CLOSE ----------------------------------------------------------------------------
- /**
- * Closes the image.
- *
- * @return void
- */
- public function close()
- {
- if ( $this->is_open )
- {
- $this->close_real();
- }
- $this->src = '';
- $this->fallback_src = '';
- $this->image_data = array( 'width' => '', 'height' => '', 'ext' => '');
- $this->image_data_orig = array( 'width' => '', 'height' => '', 'type' => '', 'ext' => '', 'src' => '');
- $this->wm_image_data = array( 'width' => '', 'height' => '', 'type' => '', 'src' => '' );
- $this->debug_messages = array();
- $this->is_data_ready = false;
- }
- /**
- * Closes the open image resource(s).
- *
- * @return void
- */
- private function close_real()
- {
- if ( is_resource( $this->handle ) )
- {
- imagedestroy( $this->handle );
- unset( $this->handle );
- }
- $this->is_open = false;
- }
- // ---------------------------------------------------------------------------- PREPARE SETTINGS ----------------------------------------------------------------------------
- /**
- * Cleans up some of the settings to ensure they are in the correct format for the class to use.
- *
- * @return bool true on success, false on failure
- */
- private function prep_settings()
- {
- //---------- get other params ----------
- //allow_scale_larger parameter
- if ( ! is_bool( $this->allow_scale_larger ) )
- {
- $this->allow_scale_larger = false;
- }
- //get bg_color param
- $this->bg_color = Ce_image_tools::hex_cleanup( $this->bg_color );
- //get bg_color_default param
- $this->bg_color_default = Ce_image_tools::hex_cleanup( $this->bg_color_default );
- if ( $this->bg_color_default == false )
- {
- $this->bg_color_default = 'ffffff';
- }
- //get filter param
- $filter_array = $this->filters;
- if ( ! is_array( $filter_array ) )
- {
- $filter_array = ( trim( $filter_array ) != '' ) ? array( $filter_array ) : array();
- }
- $filters = array();
- $count = count( $filter_array );
- if ( $count != 0 )
- {
- foreach( $filter_array as $filter )
- {
- //make filter an array if applicable
- if ( ! is_array($filter) && trim( $filter ) != '' )
- {
- $filter = array( $filter );
- }
- //make sure the filter has a name
- if ( ! isset( $filter['0'] ) || trim($filter['0']) == '' )
- {
- continue;
- }
- //make sure the filter exists
- $filter_name = trim($filter['0']);
- if ( isset( $this->valid_filters[$filter_name] ) )
- {
- //if a native image filter is being used, make sure it exists with this installation
- if ( $this->valid_filters[$filter_name] === 'imagefilter' && ! defined( 'IMG_FILTER_' . strtoupper($filter_name) ) )
- {
- continue;
- }
- //add the filter
- $filters[] = $filter;
- }
- }
- }
- unset( $filter_array );
- $this->filters = $filters;
- unset( $filters );
- //get crop param
- if ( ! is_array( $this->crop ) )
- {
- $this->crop = array( $this->crop );
- }
- $crop = $this->crop;
- $this->do_crop = ( isset( $crop[0] ) && $crop[0] === true );
- //get border param
- $border = $this->border;
- if ( $border != false && isset( $border[0] ) && is_numeric( $border[0] ) && $border[0] > 0 )
- {
- $this->check_size = true;
- if ( isset( $border[1] ) )
- {
- $temp = Ce_image_tools::hex_cleanup( $border[1] );
- if ( $temp != '' )
- {
- $this->border[1] = $temp;
- }
- else
- {
- $this->border[1] = 'ffffff';
- }
- }
- else
- {
- $this->border[1] = 'ffffff';
- }
- }
- else
- {
- $this->border[0] = 0;
- $this->border[1] = 'ffffff';
- }
- //get rounded_corners param
- $corners = $this->rounded_corners;
- $corners_array = array();
- if ( is_array( $corners ) && count( $corners ) > 0 )
- {
- if ( ! is_array( $corners[0] ) )
- {
- $corners = array( $corners );
- }
- foreach ( $corners as $corner )
- {
- //get the position
- if ( isset( $corner[0] ) && in_array( $corner[0], $this->corner_options ) )
- {
- $corner_array = array();
- $pos = $corner[0];
- //get the radius
- $rad = 15;
- if ( isset( $corner[1] ) && is_numeric( $corner[1] ) )
- {
- $rad = $corner[1];
- }
- //get the color (will end up being: hex, or '')
- $col = '';
- if ( isset( $corner[2] ) )
- {
- $col = Ce_image_tools::hex_cleanup( $corner[2] );
- }
- if ( $pos == 'all' )
- {
- if ( $rad > 0 )
- {
- $corners_array['tl'] = array( $rad, $col );
- $corners_array['tr'] = array( $rad, $col );
- $corners_array['bl'] = array( $rad, $col );
- $corners_array['br'] = array( $rad, $col );
- }
- else
- {
- $corners_array = array();
- }
- }
- else
- {
- if ( $rad > 0 )
- {
- $corners_array[$pos] = array( $rad, $col );
- }
- else
- {
- unset( $corners_array[$pos] );
- }
- }
- }
- }
- }
- $this->corners_array = $corners_array;
- $this->corners = ( count($this->corners_array) > 0 );
- //get flip param
- if ( ! is_array( $this->flip ) && in_array( $this->flip, $this->flip_options ) )
- {
- $this->flip = array( $this->flip );
- }
- $flip = $this->flip;
- if ( is_array( $flip ) )
- {
- foreach( $flip as $i => $f )
- {
- if ( ! in_array( $f, $this->flip_options ) )
- {
- unset( $flip[$i] );
- }
- }
- //remove duplicate values
- $this->flip = array_unique( $flip );
- if ( count( $flip ) > 0 )
- {
- $this->flip = $flip;
- }
- else
- {
- $this->flip = false;
- }
- }
- else
- {
- $this->flip = false;
- }
- //get reflection param
- $ref = $this->reflection;
- $reflection_array = array();
- if ( is_array( $ref ) && count( $ref ) > 0 )
- {
- $reflection_array[0] = ( isset( $ref[0] ) && is_numeric( $ref[0] ) ) ? trim( $ref[0] ) : 0; //gap
- $reflection_array[1] = ( isset( $ref[1]) && is_numeric( $ref[1]) ) ? trim( $ref[1] ): 80; //start opacity
- $reflection_array[2] = ( isset( $ref[2]) && is_numeric( $ref[2]) ) ? trim( $ref[2] ): 0; //end opacity
- $reflection_array[3] = ( isset( $ref[3]) && is_numeric( str_replace( '%', '', $ref[3] ) ) ) ? trim( $ref[3] ) : '50%'; //ref_height
- }
- $this->reflection_array = $reflection_array;
- if ( count($this->reflection_array) > 0 )
- {
- $this->reflection = true;
- $this->check_size = true;
- }
- //get rotate param
- if ( $this->rotate != 0 && is_numeric( $this->rotate ) && $this->rotate % 360 != 0 )
- {
- $this->check_size = true;
- }
- else
- {
- $this->rotate = false;
- }
- //get overwrite_cache param
- if ( ! is_bool( $this->overwrite_cache ) )
- {
- $this->overwrite_cache = false;
- }
- //get hash_filename param
- if ( ! is_bool( $this->hash_filename ) )
- {
- $this->hash_filename = false;
- }
- //get save_type param
- $save_type = trim( $this->save_type );
- if ( $save_type == '' )
- {
- $save_type = ( $this->image_data_orig['ext'] ) ? $this->image_data_orig['ext'] : $this->get_type_orig();
- }
- if ( ! in_array( strtolower( $save_type ), $this->image_types ) )
- {
- $save_type = 'jpg';
- }
- $this->image_data['ext'] = $save_type;
- //check quality to be valid
- if ( ! is_numeric( $this->quality ) || $this->quality < 0 || $this->quality > 100 )
- {
- $this->quality = 100;
- }
- //---------- find new dimensions ----------
- if ( $this->windows_dev )
- {
- $this->src = str_replace('/', '\\', $this->src);
- }
- $result = $this->get_dimensions();
- if ( ! $result )
- {
- return false;
- }
- //prepare the text
- if ( $this->text != false )
- {
- $this->get_text_preference();
- }
- return true;
- }
- /**
- * Determines which text preference, if any, meets the minimum dimensions requirement and sets it as the class' text property.
- *
- * @return void
- */
- function get_text_preference()
- {
- //if a single text array, wrap it in an array
- if ( is_array( $this->text ) && ! is_array( $this->text[0] ) )
- {
- $this->text = array( $this->text );
- }
- //---------- get preference by minimum dimension ----------
- //let's see what preferences are being passed in for minimum dimensions, and see if we can find one that works
- $final_pref_ind = -1;
- foreach ( $this->text as $index => $text_pref )
- {
- //break up the chunks
- if ( is_array( $text_pref ) && count( $text_pref ) > 1 )
- {
- //size limits should be here
- if ( count( $text_pref[1] ) == 2 )
- {
- list( $min_w, $min_h ) = $text_pref[1];
- //check the dimensions
- if ( $this->do_crop == false )
- {
- if ( ($min_w == 0 || $min_w <= $this->width_final) && ($min_h == 0 || $min_h <= $this->height_final) )
- {
- //this pref will work
- $final_pref_ind = $index;
- break 1;
- }
- }
- else
- {
- if ( ($min_w == 0 || $min_w <= $this->width_desired) && ($min_h == 0 || $min_h <= $this->height_desired) )
- {
- //this pref will work
- $final_pref_ind = $index;
- break 1;
- }
- }
- }
- else
- {
- //both params are not there...we'll assume this is the one they wanted
- $final_pref_ind = $index;
- break 1;
- return;
- }
- }
- else
- {
- //no size limits found, so this pref will do
- $final_pref_ind = $index;
- break 1;
- }
- }
- if ( $final_pref_ind == -1 )
- …
Large files files are truncated, but you can click here to view the full file